Adding target prerequisites via a pattern - makefile

In a project I'm working on, I have a directory full of source files which require a special executable to compile. My initial reaction is to do:
SomeDirectory/%.o: my-special-compiler
...to add the dependency for all %.o files.
Except of course this doesn't work, because pattern rules are special and while the above index will add a prerequisite for a non pattern rule, for pattern rules it seems to do nothing.
I don't have a list of all .o files in SomeDirectory at this point in the build system. Is there a way I can achieve the same effect without having to refactor my build system?
This is GNU Make, if it helps.

Not simply by adding a new rule. You must list each of the object files and add that prerequisite specifically to them. A pattern rule with no recipe cancels the pattern rule.
Probably your best option is to follow the model created for auto-dependency generation and automatically generate a file that contains that extra prerequisite, as a side-effect of creating the object file... then include it.

Related

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.)

Compilation order in make rule

I have a compilation rule as follows,
$(compiled_objs) : $(obj_dir)/%.o: $(src_base)/%.cpp
It creates .o dso objects from specific .cpp files in src_base and works fine.
Question:
My question is that is there a way in gnu Makefiles to sort the order in which %.cpp files are processed. For example, in each src_base, i have a file called xxxLast.cpp and i want to create the object for *Last.cpp after all other .cpp files from $src_dir directory has already been processed.
Use-Case:
My use case is not common but i want to embedd the md5sum of all other .o objects in xxxLast.cpp file for which i can add additional handling in my rule.
I haven't done much work on makefiles. Help will be highly appreciated and thanks in advance.
Somewhere else in your makefile you'll have a target that depends on $(compiled_objs):
all_objects: $(compiled_objs)
Make will build the prerequisites of any target in the order they are listed. So if you want a particular object to be built last, then you just put it at the end of the compiled_objs macro.
Be aware that during parallel builds make will still walk the commands to run in the same order, BUT due to parallelization effects they may actually run in a different order, or at least you can't know that the last one will be started after all the previous ones have completed.
For your situation I really don't recommend just stucking the last object at the end and hoping. You should define this relationship explicitly using make rules, so:
all_objects: xxxLast.o
xxxLast.o: $(compiled_objs-but-not-xxxLast.o)
...generate md5sums for $^...
xxxLast.o $(compiled_objs-but-not-xxxLast.o): $(obj_dir)/%.o: $(src_base)/%.cpp

how do makefile dependencies work?

I am currently confused as to how makefile targets work. I have a current understanding, and I don't know if it is correct because the tutorials I've been reading aren't very clear to me. Here is my current understanding
when you run 'make' in the terminal, the makefile utility finds the first target in the makefile and tries to run it, but before doing so it looks at all of the dependencies in the file
(this is where I start getting confused): If the dependency is a target in the makefile, but does not exist as a file in the makefile's directory, make simply runs the target. If the dependency is a file name, but not a target in the makefile, the utility checks for the existance of the file, and if the file doesn't exist, the utility yells at you. If the dependency is a file that exists in the directory AND a target, the target is run provided that any of the files that the file-target depend on are newer than the associated file.
Do I have it down right? Is it simpler than I'm making it out to be?
You have it right, more or less, but it can be stated a little more clearly. You're right about how make chooses the initial target, except of course if the user specifies a specific target on the make command line then that one is used instead of the first one.
Then make basically implements a recursive algorithm for each target, that works like this:
Find a rule to build that target. If there is no rule to build the target, make fails.
For each prerequisite of the target, run this algorithm with that prerequisite as the target.
If either the target does not exist, or if any prerequisite's modification time is newer than the target's modification time, run the recipe associated with the target. If the recipe fails, (usually) make fails.
That's it! Of course, this hides a number of complex issues: in particular item #1 (finding a rule) can be complex in situations where you have no implicit rule for the target. Also behaviors such as what to do when a rule fails can be modified.
But that's the basic algorithm!
for the question you asked your understanding is correct !!
If you are still confused have a look at this :: http://www.jfranken.de/homepages/johannes/vortraege/make_inhalt.en.html
once comfortable move to other more complete manuals like the GNU manual for make.

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.

build multiple targets in a makefile without all target

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.

Resources