Makefile all target order - makefile

Does order in makefile all target matters ?
For eg. if I have -
all : target1 target2 target3
Does the order matters here i.e. will target2 be always executed after target3 ?

The POSIX standard for make requires that make consider prerequisites in the order they were listed in the makefile.
So yes, in your example make is required to first try to build target1, then try to build target2, then try to build target3, then, if any of those targets were updated, it will try to run the recipe for all if one exists.
However, it's a bad idea to rely on this when you write your makefile.
First, what if someone runs make target3 but you can't build target3 until target2 is complete? Then make target3 will not try to build target2 because make doesn't know that it's needed.
Second, if you invoke make -j (parallel builds) then make can try to build target1, target2, and target3 all at the same time. If they rely on each other this will likely break things.
If you have a dependency relationship between two targets, you should tell make about it by declaring a prerequisite. That way you know your build is reliable.

Related

Ignore prereq Makefile targets

I have a Makefile:
.PHONY: target0 target1
target0:
<command>
target1: target0
<command>
How can I run make target1 and force it to skip target0?
Neither GNU make nor any other make I know provides a means to ignore out-of-date prerequisites. It is antithetical to make's design and goals. Targets that don't exist or (with GNU make) that are .PHONY are always considered out-of-date at the beginning of a run. So, with that makefile, make target1 will always build target0 as well.
That you pose the question at all suggests that you have modeled something as a prerequisite that isn't really a prerequisite. Perhaps you did so to aggregate targets, for example. In that case, you could consider rewriting your makefile, maybe like so:
.PHONY: all target0 target1
target0:
<command>
target1:
<command>
all: target0 target1
With that, you can build just target0 or just target1 or both (all), as you choose, but you do need to request both when that's in fact what you want. When you do request both, you will probably get target0 built before target1 unless you use the -j option. But if you need to ensure that target0 is built first when both are to be built, then you could do this, instead:
.PHONY: all target0 target1
target0:
<command>
target1:
<command>
all:
make target0
make target1
With GNU make:
make -W target0 target1
From the manual
on "Instead of Executing Recipes":
Each ‘-W’ flag is followed by a file name. The given files’ modification
times are recorded by make as being the present time, although the actual
modification times remain the same.
Without the ‘-n’ or ‘-q’ flag, when make is actually executing recipes,
the ‘-W’ flag can direct make to act as if some files had been modified,
without actually running the recipes for those files.

Global prerequisite in GNU make - is it possible

I have a Makefile with tons of targets and would like for a certain script to get executed first, irrespective of what target is being called. I like to call it a global prerequisite.
I do not want to create a target for the script and set it as a prerequisite for all existing targets (which, as I said aren't few). Besides, someone else could add a target in future and not add my script as a prerequisite for their target, so the global prerequisite would take care of that.
Does GNU-make provide for a means to achieve this?
Another approach:
-include dummy
.PHONY: dummy
dummy:
run-the-script
Make will always attempt to rebuild any file which the makefile attempts to include (if it is out of date or does not exist). In this case there is no such file, and the rule to build it runs the script and does nothing else.
There is a solution without modifying your existing Makefile (main difference with the answers pointed to by tripleee). Just create a makefile containing:
.PHONY: all
all:
pre-script
#$(MAKE) -f Makefile --no-print-directory $(MAKECMDGOALS) MAKE='$(MAKE) -f Makefile'
post-script
$(MAKECMDGOALS): all ;
The only drawback is that the pre- and post- scripts will always be run, even if there is nothing else to do. But they will not be run if you invoke make with one of the --dry-run options (other difference with the answers pointed to by tripleee).

defer prerequisite expansion until after a (different) target creation

I want to be able use the result of a target created in a rule in the prerequisite of another rule in GNU make. So for example:
PREREQ = $(shell echo "reading target1" >&2; cat target1)
target1:
echo "prereq" > $#
target2: target1 $(PREREQ)
echo foo > $#
target2 should depend on prereq as read from the target1 file, but that is not in the file until the target1 recipe is executed.
Granted this is very contrived example with I am sure lots of suggestions about how to refactor this particular example but I'm not looking to refactor this example. This is just a simplified example of my more complicated problem where I need to derive prerequisites from the contents of a file that is not created until a recipe in the Makefile is executed.
The question is, [how] can I make expansion of $(PREREQ) (and therefore the execution of the $(shell cat target1) defer until after the target1 rule is actually executed?
Update: I tried .SECONDARYEXPANSION: but that doesn't seem to do the job:
$ make -d target2
...
reading target1
cat: target1: No such file or directory
...
Updating goal targets....
Considering target file 'target2'.
File 'target2' does not exist.
Considering target file 'target1'.
File 'target1' does not exist.
Finished prerequisites of target file 'target1'.
Must remake target 'target1'.
echo "prereq" > target1
[ child management ]
Successfully remade target file 'target1'.
Finished prerequisites of target file 'target2'.
Must remake target 'target2'.
echo foo > target2
[ child management ]
Successfully remade target file 'target2'.
As you can see, "reading target" was only printed once at the very beginning demonstrating that PREREQ is not expanded again due to the .SECONDEXPANSION: and the list of targets Considered for target2 did not include prereq.
Deferring the expansion of the prerequisite $(PREREQ) can be achieved by conditionally creating the target2 and relying on recursion:
ifndef expand-prereq
target2: target1
$(MAKE) --no-print-directory -f $(lastword $(MAKEFILE_LIST)) $# expand-prereq=y
else
target2: target1 $(PREREQ)
echo foo > $#
endif
The first time make runs for this makefile, the variable expand-prereq is not defined and therefore, the first targe2 rule is generated as a result of the conditional. This kind of dummy rule makes possible to update target1 without expanding $(PREREQ).
Matching this rule results in target1 being updated (since target1 is a prerequisite of this rule) and make being called recursively for the same makefile and with target2 as target.
The second time make is (recursively) invoked, the variable expand-prereq was defined by means of the command-line argument expand-prereq=y, so the second target2 rule is generated as a result of the else branch this time. This rule is the one that actually produces the target target2. Note that before this rule can be matched, target1 has been already created as a side effect of the first dummy rule, so the expansion of $(PREREQ) happens after target1 has been created (what you were looking for).
You could write the complete rule for target2 to a separate file and -include it:
Including Other Makefiles
How Makefiles Are Remade
The exact mechanics will depend on your specific use case, and it may well be impossible to achieve what we need using this approach, but it supports a variety of styles for automated dependency generation.
There are several solutions:
GNU make 4.4 has been released! Haven't tried yet, but the release notes claim that secondary expansion only expands the prerequisites when they're considered. Furthermore you can delay execution with the .WAIT special prerequisite. That works fine, I tested. If .WAIT really delays the second expansion of the prerequisites after .WAIT, you're good.
Recursive make. Restart make after the prerequisites for the second rule were updated. This is a bit lame solution, can't recommend it.
Produce the prerequisites into make include file(s). Make automatically restarts after updating include files (re-exec). I'm currently using this method, and it works great. Better than recursive make but still slow, as all the makefiles have to be parsed again. A possible solution is comparing the old and new prerequisites, and only updating the include file, if its content changed. The second rule also needs to be modified to do nothing, if the content changed. Make will run all rules before restarting, but if they don't update their targets, after the restart they'll be executed again, now with the proper prerequisites. An interesting feature of make is that you can define make variables inside a recipe, and use them in other recipes (but not in the prereq list, unless #1 above reall works).

Is it possible to make all targets '.PHONY' ? (gmake)

I have a Makefile, where none of the targets reference files, so if this can be done in some loop it would be
convenient.
Is there some way to set every target in a makefile as .PHONY ?
The reason I'm asking this is I never want any files in the same directory as the makefile to conflict with the targets (where the makefile will automatically associate any target with a directory of file).
You can ensure targets always build by defining one empty "FORCE" target and have all you're other targets depend on it
target1: FORCE
./foobar $#
target2: FORCE
./dongle $#
FORCE:
(as suggested in the make manual)
You can also run "make -B" instead of "make"?
`-B'
`--always-make'
Consider all targets out-of-date. GNU `make' proceeds to consider
targets and their prerequisites using the normal algorithms;
however, all these targets are remade, regardless of the status of
their prerequisites.

What does "all" stand for in a makefile?

I read some tutorials concerning Makefiles but for me it is still unclear for what the target "all" stands for and what it does.
Any ideas?
A build, as Makefile understands it, consists of a lot of targets. For example, to build a project you might need
Build file1.o out of file1.c
Build file2.o out of file2.c
Build file3.o out of file3.c
Build executable1 out of file1.o and file3.o
Build executable2 out of file2.o
If you implemented this workflow with makefile, you could make each of the targets separately. For example, if you wrote
make file1.o
it would only build that file, if necessary.
The name of all is not fixed. It's just a conventional name; all target denotes that if you invoke it, make will build all what's needed to make a complete build. This is usually a dummy target, which doesn't create any files, but merely depends on the other files. For the example above, building all necessary is building executables, the other files being pulled in as dependencies. So in the makefile it looks like this:
all: executable1 executable2
all target is usually the first in the makefile, since if you just write make in command line, without specifying the target, it will build the first target. And you expect it to be all.
all is usually also a .PHONY target. Learn more here.
The manual for GNU Make gives a clear definition for all in its list of standard targets.
If the author of the Makefile is following that convention then the target all should:
Compile the entire program, but not build documentation.
Be the the default target. As in running just make should do the same as make all.
To achieve 1 all is typically defined as a .PHONY target that depends on the executable(s) that form the entire program:
.PHONY : all
all : executable
To achieve 2 all should either be the first target defined in the make file or be assigned as the default goal:
.DEFAULT_GOAL := all
Not sure it stands for anything special. It's just a convention that you supply an 'all' rule, and generally it's used to list all the sub-targets needed to build the entire project, hence the name 'all'. The only thing special about it is that often times people will put it in as the first target in the makefile, which means that just typing 'make' alone will do the same thing as 'make all'.
The target "all" is an example of a dummy target - there is nothing on disk called "all". This means that when you do a "make all", make always thinks that it needs to build it, and so executes all the commands for that target. Those commands will typically be ones that build all the end-products that the makefile knows about, but it could do anything.
Other examples of dummy targets are "clean" and "install", and they work in the same way.
If you haven't read it yet, you should read the GNU Make Manual, which is also an excellent tutorial.

Resources