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)