[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Make 3.82: weird "circular dependency" and missing $< expansion

From: Edward Welbourne
Subject: Re: Make 3.82: weird "circular dependency" and missing $< expansion
Date: Tue, 03 May 2011 15:03:32 +0200

> So, the circular dependency issue is because of this:
>> %.eps: %.pdf
>> %.eps %.pdf: %.dat

Technically, not a circular dependency: in the directed graph of
dependencies, there is no cycle.  If we ignore the directedness of
some edges, we get a cycle; but the edges *are* directed, and we must
go the wrong way along at least one of them to complete a (non-empty)
journey from any node back to itself, so it's not a true cycle.
(There is no file for which rules have been given that enable us to
make this file from itself, by a series of steps via other files.)
The digraph is acyclic - but it's not a tree: and "not a tree" is the
actual problem here.

Because there are two routes through the dependency graph from %.eps
to %.dat, one going directly, the other going via %.pdf, make has an
ambiguity it can't sensibly resolve (if any %.eps is asked for, for
which a matching %.dat does exist); so "Circular" is the wrong
complaint, but Akim's rules are ambiguous, and this is the problem.
Quite likely, Akim's rules' commands will actually end up with the
same %.eps either way; but make has no way to know that, so it
complains if it's got to chose between two different routes through
the directed graph.

Make *could* try disambiguating in one way or another; chose the
shortest path through the digraph, for example; but then we'll see
cases where there are distinct paths of equal length; make could chose
the first, among the equal shortest, for which it read a rule; but
then the outcome would depend on the order of parsing of make-file
fragments, which might go via an include directive with a wildcard,
whose order of inclusion is implicitly haphazard, so make's results
would be unpredictable, which is bad.  (Further: the individual steps
in the equal-length paths may be interleaved, making it hard to decide
which path was read "first".)  Complaining about ambiguity is the
robust course of action.

> When make wants to build foo.eps it finds the first rule and sees that
> it can build foo.eps if it can build foo.pdf, so make looks for a rule
> to build foo.pdf and finds that it can build it from foo.dat... but that
> rule ALSO builds foo.eps.  Now make has two rules that can build foo.eps
> and one of them is required to build its own prerequisite.

thus, indeed, the simplest solution is to omit %.eps from the %.dat

%.eps: %.pdf
%.pdf: %.dat

I'm guessing, however, that there's an optimisation at play for the
ones that can be generated from %.dat, since it can produce both the
%.pdf and the %.eps at the same time.  It may thus be necessary to
construct a list of files %.eps for which there is no matching %.dat
and use that as pre-selector for Akim's first rule, e.g. as

ALLDAT := $(wildcard $(hither)/*.dat $(yon)/*.dat)
ALLPDF := $(ALLDVI:%.dvi=%.pdf) $(ALLDAT:%.dat=%.pdf) \
        $(wildcard $(thomas)/*.pdf $(richard)/*.pdf $(henry)/*.pdf)
#... or whatever
ALLEPS := $(ALLPDF:%.pdf=%.eps)
EPSnoDAT := $(filter-out $(ALLDAT:%.dat=%.eps), $(ALLEPS))

$(EPSnoDAT): %.eps: %.pdf

%.eps %.pdf: %.dat

with whatever rules Akim currently use on the last two.

> It all depends on the order in which make searches the rules, which is
> why changing things in the makefile matters.  If make finds the second
> rule first then it sees it can build foo.eps and foo.pdf from foo.dat
> and it's all good.  No circularity.

Well, it still gets told the same edges in its directed graph, so it's
just as "cyclic" - when you ignore the direction on at least some
edges; i.e. it's not a tree - it's just that it's not interested in
the %.eps: %.pdf rule by the time it reads it, so it doesn't get
confused about it.  The fact that this depends on the orer of rules
strikes me as highly suspect; it may be "by design" but I'd read it as
saying make isn't really building the full directed graph of
dependencies.  If Akim has some other rules that make a %.pdf from
sources other than %.dat, make should chain that with the rule to make
a %.eps from %.pdf and hence from this other source (when the %.dat
doesn't exist).  Further, if any %.dat actually exists, and its
corresponding %.eps is asked for, make should report the ambiguity of
the situation, regardless of the order in which it meets the pattern
rules, because ambiguity should be reported - how else will the
make-files' maintainer learn about a complication that may be making
make's results unpredictable ?


reply via email to

[Prev in Thread] Current Thread [Next in Thread]