bug-make
[Top][All Lists]
Advanced

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

Re: 回复: 回复: Implicit rule for linking multiple object files


From: Paul Smith
Subject: Re: 回复: 回复: Implicit rule for linking multiple object files
Date: Thu, 11 Aug 2022 15:03:41 -0400
User-agent: Evolution 3.44.3 (by Flathub.org)

On Fri, 2022-08-12 at 02:37 +0800, ljh wrote:
> Aren't the order of compiling object files of first two rules
> certain?

The POSIX standard for make mandates that prerequisites are tried by
make in the order they are listed in the prerequisite list, with the
exception that implicit rules will prepend the prerequisites (this is
what you want, else the $< variable will contain some random target).

GNU make will, of course, obey the standard.

The problem is that when you enable parallel builds (make -j), even
though make will still try things in the order in which they are
listed, you can get files built in other orders depending on how long
prerequisites take to be built.

The correct way to write makefiles is to declare all the dependency
relationships between targets explicitly in the makefile, and NOT rely
on implicit ordering of prerequisites.

When you write a rule in make like this:

   target: prereq1 prereq1

this tells make that "target" depends on "prereq1" and "prereq2", and
so make will never start building "target" until after BOTH "prereq1"
and "prereq2" are done.

However, that rule says NOTHING about any relationship between
"prereq1" and "prereq2", to each other.  As far as make is concerned
these targets are 100% independent and make will definitely not ensure
that, for example, "prereq1" is complete before it starts building
"prereq2" (for example when you use -j).

If you want to define a relationship between "prereq1" and "prereq2",
you have to put that in a separate rule.  See below.

> # ok: in order of writing, with recipe
> x: y.o z.o x.o
>     $(CC) $^ -o $@

Since you've declared your own rule here the pattern rule is not used
and, as long as you don't use -j, you are guaranteed that the
prerequisites are built in that order.

> # ok: compiles x.o last, no mentioning x.o
> x: y.o z.o

Here the pattern rule is used, but the pattern rule chosen is "% :
%.cpp" which means it will not build x.o at all.  Instead it builds the
y.o and z.o object files, then it does the compile of x.cpp and link
together in one command.  If you examine the link line make prints very
carefully you'll see that it contains x.cpp not x.o, and there will be
no x.o file in your directory when you're done:

   g++ -o x x.cpp y.o z.o
            ^^^^^

So, this works for your specific purposes.

Note that when your module requirements get more complex, it's very
likely this will no longer work.  It's a magical accident of the fact
that your file that uses modules has the same name as the program
you're trying to create.

> The rest of the below three rules are not suitable if compiling order
> matters.
> 
> # compiles x.o first, mentioning x.o
> x: y.o z.o x.o
> 
> # compiles x.o first
> x: $(patsubst %.y,%.o,$(wildcard *.y))
> 
> # in order of file names, with recipe
> x: $(patsubst %.y,%.o,$(wildcard *.y))
>     $(CC) $^ -o $@ 

None of the 5 rules above are really suitable, if compiling order
matters.

If compiling order matters, then you should tell make what the
necessary order is, by declaring prerequisites.

If it's the case that x.o can't be created until y.o and z.o are
completed, then you have to write that into your makefile, like this:

  x.o : y.o z.o

(note you don't need a recipe here: you can use the default rule to
build the x.o file.  You're just telling make about some extra
prerequisites it has to complete before it can build x.o)



reply via email to

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