build multiple targets in a makefile without all target - makefile

I have a list of targets that are all calling msgfmt for a specific language. I would like to call them all, but I do not really want to create a huge all target. Is there some other way to tell make that multiple targets should be build?

The all target is not special in any way. It is only by convention that this is the first, and thus the default target. Any other phony target can take its' place.
Just create some target, declare it as .PHONY, let all your msgfmt targets as prerequisites of this target, and make it something other then your first one.
If you already have a list of targets in a variable, you can use that variable as the prerequisite list.

Related

gnu make: why called "top-level" target?

In the context of the GNU make tool the term "top-level target" is used.
Are there other types of targets? Can there be targets "nested" inside other targets?
I could not find anything searching for "nested target", "inner target" or "enclosing target".
There is no such thing as a "nested", "inner", or "enclosing" target in a makefile. Of course, you can "collect" targets implicitly by declaring prerequisites: if you build the target it also builds all its prerequisites.
The term top-level target as used in that section of the GNU make manual is your subjective understanding of the final goals that your makefile wants to create. So if your makefile should create a program and a library, those are the "top-level targets" that section refers to.
That page is discussing only a set of common targets that many makefiles implement. None of those are built into make or have any special meaning to make itself.
The top-level target is the target given to make on the command line. Or it's the default target in the Makefile. Other targets would be intermediate or dependent targets.

Makefile - does using .PHONY for running commands was intended when creating make?

I know we can set up commands such as all, clean, install etc in makefile and use .PHONY to tell make they're not associated with files.
But I was wondering - when creating make and makefile - was this kind of use (to run such commands) combined with .PHONY designed for that purpose? Or maybe .PHONY was added later to easily extend make to support those kind of commands?
I also read this but there wasn't anything else there except the regular known usage.
Thanks!
I do not know the history of GNU make.
The use of .PHONY is exactly what you suspect: have targets (which can thus be goals, or commands, if you wish) that are not files, and that work even if, by accident, a file with the same name exists. It is one single and clearly defined purpose.
In certain cases you want to force a target file to be re-built even if it is up-to-date, and you can declare it a prerequisite of .PHONY for this purpose, but it is frequently the sign that your makefile is not what it should be.
Another frequent situation is the grouping of several targets (real or phony) as prerequisites of one single other phony target.
But in both cases, we can say that the resulting phony target is a kind of command. In the first case it is a command that forces the build of a file. In the second it is a kind of alias for a series of actions.

Using Makefile variable before definition in included file

I've encountered a little problem during my Makefile learning adventure.
I have prepared two scripts. The first one is the main Makefile:
all:
#echo $(COMPONENTNAME)
include ~/Projects/tests/mk
And here's the mk file
COMPONENTNAME:=ISeeYou
Now, when I run
make all
I get
ISeeYou
I am not sure why... I was convinced that a variable must be defined before it is used. And the include is after COMPONENTNAME is being used. My suspicion is that all of the includes are done first, and then the target creation is started. Is that the case?
My suspicion is that all of the includes are done first, and then the target creation is started.
Yes, you are right.
All global sections in Makefile should be completely parsed before make is able to decide, which targets(and in which order) should be built. Target's recipes are evaluated only when it is needed to build target. This is explicitely stated in make manual:
The other way in which make processes recipes is by expanding any variable references in them. This occurs after make has finished reading all the makefiles and the target is determined to be out of date; so, the recipes for targets which are not rebuilt are never expanded.

Makefile generator creates two files

I have a generator program that creates two version files, say ver.h and ver.cpp. My ultimate build target depends on both of these files, and the rule for building both is that one program. If I did this:
build : ver.h ver.cpp
ver.h ver.cpp :
./gen/version/program
then a parallel build could run program twice, which, while not bad is just excessive. I figure I could have them both depend on a phony target:
ver.h ver.cpp : do-version-impl
do-version-impl:
./gen/version/program
.PHONY : do-version-impl
Is that the best way to do this? It smells a little funny to have to introduce a phony rule to do this.
Using the phony target as the prerequisite is a bad idea. program will be run even if ver.* files exist, which is a false positive error.
More subtly, GNU Make is only guaranteed to update its file timestamp, if that file is a target of a rule with a recipe. So here, even though program is always run, anything that in turn depends on ver.* files might not get updated at all!
In my opinion it is best to not make up unnatural patterns for each target, but instead, go explicit:
There is a "main" file that you are generating, that is ver.cpp. Use the "no-op" recipe ; for the other one, which can be put on the same line like this:
ver.h: ver.cpp ;
ver.cpp: Makefile
./gen/version/program
This method starts with what you wrote, but adds the very important ;.
If you did not have a natural candidate for the "main" file, then in my opinion it is best to use a "sentinel":
ver.h ver.cpp: sentinel ;
sentinel: Makefile
./gen/version/program
touch $#
Again, this method is similar to one of your methods, but very importantly, does not use a phony, but a real file.
See 10.5.1 Introduction to Pattern Rules specifically the last paragraph:
10.5.1 Introduction to Pattern Rules
...
A pattern rule need not have any prerequisites that contain ‘%’, or in fact any prerequisites at all. Such a rule is effectively a general wildcard. It provides a way to make any file that matches the target pattern. See Last Resort.
...
Pattern rules may have more than one target. Unlike normal rules, this does not act as many different rules with the same prerequisites and recipe. If a pattern rule has multiple targets, make knows that the rule’s recipe is responsible for making all of the targets. The recipe is executed only once to make all the targets. When searching for a pattern rule to match a target, the target patterns of a rule other than the one that matches the target in need of a rule are incidental: make worries only about giving a recipe and prerequisites to the file presently in question. However, when this file’s recipe is run, the other targets are marked as having been updated themselves.
So you could use something like this:
v%r.h v%r.cpp:
./gen/version/program
I believe you need that odd patterning to have make consider the pattern to match (I don't believe it will match % against an empty string as ver%.h ver%.cpp would need). (I can't find reference to this in the manual at the moment though.)

Multiple instances of the same target for make

I am working on a Makefile written by someone else in my lab and I see the following:
include /path/to/Makefile.inc
TARGET_A: pre_req_1 pre_req_2
cmd_1;
cmd_2;
...
When I look at /path/to/Makefile.inc I see that it also includes a target TARGET_A
with other pre-requisites and recipes.
Is this a normal practice? (and would it work?) Would make treat the two rules separately? Can we safely make any assumptions about which one is considered first?
It is a dangerous practice since it is confusing to know which one is applied.
The "include" will act has if the included file content was in the Makefile, and the targets will be overrided while reading the Makefile. So, the last target will be honored, and the first one (in the included file) will be ignored.

Resources