Gnu make, multiple sets of grouped targets - gnu-make

I have a makefile that includes two rules each of which defines a (completely different) grouped target. The intention in each case is (of course) to generate all of the targets by executing the associated recipe once.
If both rules are present, each using the target separator "&:", I get "warning: overriding recipe for target '&'", with the first lines of each of the two recipes cited.
If I change either rule to use the standard target separator ":", the warning goes away.
I can provide extracts from the makefile but believe the above description is as concise as it will get.

Grouped targets were introduced in GNU make version 4.3.
Your version of GNU make is too old and doesn't recognize this syntax (it thinks that & is a target name).

Related

Why does gnu make delete this file?

Consider this Makefile:
.PHONY: all
all: main.txt
main.txt: build/main.txt
cp build/main.txt .
%/main.txt: %/data.txt
cp $*/data.txt $*/main.txt
%/data.txt:
touch $*/data.txt
After running make, build/data.txt is removed automatically. Why is this the case?
I tried adding .PRECIOUS: build/% to the file, but it it not help, the file was still removed. How can I prevent this?
According to the GNU Make documentation
You can also list the target pattern of an implicit rule (such as ‘%.o’) as a prerequisite file of the special target .PRECIOUS to preserve intermediate files created by rules whose target patterns match that file’s name.
the prerequisite for.PRECIOUS needs to be the (exact) target pattern of an existing implicit rule.
In your case this would be %/data.txt instead.
The documentation hints at this, but is not particularly clear about it.
As a side note: As far as I can tell build/main.txt is not automatically deleted since it is explicitly named as a prerequisite for the main.txt target and build/data.txt is automatically deleted since it is never explicitly named.

Should the longer synonyms for local variables be used in a Makefile?

In make (I am using OpenBSD’s implementation, but I suppose the question is relevant for GNU make as well), we have the following so called local variables
# The name of the target
% The name of the archive member (for library rules)
! The name of the archive file (for library rules)
? The list of prerequisites for this target that were deemed out of date
< The name of the prerequisite from which this target is to be built (for inference rules)
* The file prefix of the file, containing only the file portion, no suffix or preceding directory components
(roughly from make(1) on OpenBSD)
These local variables have synonyms: for exampe, .IMPSRC for < or .TARGET for #. The manual in FreeBSD says these longer versions are preferred. OpenBSD’s man page mentions no such thing, but says these longer names are an extension.
Is it better to use to longer names? Which is better for compatibility? Are both POSIX?
Those variables are called automatic variables in GNU make and internal variables in the POSIX standard.
The long names for these are purely BSD make inventions, they do not exist in any other version of make (such as GNU make) and they are not mentioned in the POSIX standard for make.
It's up to you whether you want to use them, but they are completely non-portable. Of course you could always define them yourself if you wanted to implement a compatibility layer.

Randomize Make goals for a target

I have a C++ library and it has a few of C++ static objects. The library could suffer from C++ static initialization fiasco. I'm trying to vet unforeseen translation unit dependencies by randomizing the order of the *.o files during a build.
I visited 2.3 How make Processes a Makefile in the GNU manual and it tells me:
Goals are the targets that make strives ultimately to update. You can override this behavior using the command line (see Arguments to Specify the Goals) ...
I also followed to 9.2 Arguments to Specify the Goals, but a treatment was not provided. It did not surprise me.
Is it possible to have Make randomize its goals? If so, then how do I do it?
If not, are there any alternatives? This is in a test environment, so I have more tools available to me than just GNUmake.
Thanks in advance.
This is really implementation-defined, but GNU Make will process targets from left to right.
Say you have an OBJS variable with the objects you want to randomize, you could write something like (using e.g. shuf):
RAND_OBJS := $(shell shuf -e -- $(OBJS))
random_build: $(RAND_OBJS)
This holds as long as you're not using parallel make (-j option). If you are the order will still be randomized, but it will also depend on number of jobs, system load, current phase of the moon, etc.
Next release of GNU make will have --shuffle mode. It will allow you to execute prerequisites in random order to shake out missing dependencies by running $ make --shuffle.
The feature was recently added in https://savannah.gnu.org/bugs/index.php?62100 and so far is available only in GNU make's git tree.

GNU Make: disable all built-in rules, except desired ones

Twice in the past, GNU make has destroyed my work because some of its built-in rules have .c files as a target.
If you have a file called foo.c, and also a foo.l Lex scanner or foo.y Yacc parser, watch out! GNU make assumes that the .c file is a target made from these (it's evidently a POSIX requirement!), and it will will do something like mv y.tab.c foo.c or lex -t foo.l > foo.c.
What is the way to disable all such hidden, dangerous rules (whether known or unknown) while keeping the useful ones?
Specifically, how can we give this request to GNU Make: "please retain all your rules related to (for example) .c and .o files, and disable all rules which involve any other file type"?
From the manual:
Many of the predefined implicit rules are implemented in make as
suffix rules, so which ones will be defined depends on the suffix list...
If you modify the suffix list, the only predefined suffix rules in
effect will be those named by one or two of the suffixes that are on
the list you specify; rules whose suffixes fail to be on the list are
disabled...
If you wish to eliminate the default known suffixes instead of just
adding to them, write a rule for .SUFFIXES with no prerequisites. By
special dispensation, this eliminates all existing prerequisites of
.SUFFIXES. You can then write another rule to add the suffixes you
want.
.SUFFIXES: # Delete the default suffixes
.SUFFIXES: .c .o # Define a new suffix list

make does not realize that a relative path name dependency is the same as an absolute pathname target

The following is a simplified makefile for a problem I'm having:
all: /tmp/makey/../filey
#echo All done
/tmp/filey:
#echo Filey
When I run make it says:
make-3.79.1-p7: * No rule to make target /tmp/makey/../filey', needed byall'. Stop.
Clearly it does not realize that /tmp/makey/../filey is the same as /tmp/filey. Any ideas how I can make this work?
Thanks
Ciao
-- Murali
Newer versions of GNU make have $(abspath ...) and $(realpath ...) functions you can apply to your prerequisites and targets to resolve the paths to the same string. If you've constructed these names yourself (for example, $(PREFIX)/../filey) then you can use $(dir $(PREFIX))filey instead.
Other than that, there's no way to solve this problem. Make uses string matching on targets and if the strings are not identical, they don't match (there's a special case to ignore the simple prefix ./) Even if make understood this distinction (by applying abspath itself to each target name, maybe) it would still not help in the face of symbolic links for example.
The only "real" answer would be for make to understand something about the underlying file system (device IDs and inodes for example) that let you talk about files without referring to their pathname. However, in a portable program like make doing this is problematic.

Resources