Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include path prefix in GNU Make pattern rule

Consider the following:

%.foo: %.bar
    echo $< > $@ 

Assuming we have one file 1.bar, the command executed is simply echo 1.bar > 1.foo. However, when % contains a path, rather than just a file name, it start becoming finicky. My problem is that I want to prepend another path to %.bar, the pattern becomes completely mangled. I.e., when %.bar is nice/path/1.bar, this becomes impossible:

%.foo: /project/something/%.bar
    echo $< > $@

This will run, but it executes echo nice/path//project/something/1.bar > 1.foo in stead of echo /project/something/nice/path1.bar > 1.foo

The reason for this is in how make does its pattern rules. From the docs:

When the target pattern does not contain a slash (and it usually does not), directory names in the file names are removed from the file name before it is compared with the target prefix and suffix. [...] The directories are ignored only for the purpose of finding an implicit rule to use, not in the application of that rule. Thus, ‘e%t’ matches the file name src/eat, with ‘src/a’ as the stem. When prerequisites are turned into file names, the directories from the stem are added at the front, while the rest of the stem is substituted for the ‘%’. The stem ‘src/a’ with a prerequisite pattern ‘c%r’ gives the file name src/car

Is there any way I can turn this off for a specific rule?

like image 943
Gx1sptDTDa Avatar asked Apr 22 '15 13:04

Gx1sptDTDa


People also ask

What is Addprefix in makefile?

What is add prefix in makefile? $(addprefix prefix , names …) The argument names is regarded as a series of names, separated by whitespace; prefix is used as a unit. The value of prefix is prepended to the front of each individual name and the resulting larger names are concatenated with single spaces between them.

What is Realpath in makefile?

realpath() expands all symbolic links and resolves references to /./ , /../ and extra / characters in the input path and returns the canonicalized absolute pathname.

Can a make target be a directory?

Yes, a Makefile can have a directory as target. However, you shouldn't. When a file is added or removed from a directory, its mtime is updated.

What is a target and a rule in makefile?

A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.


1 Answers

You may like to read up on How Patterns Match:

When the target pattern does not contain a slash (and it usually does not), directory names in the file names are removed from the file name before it is compared with the target prefix and suffix. After the comparison of the file name to the target pattern, the directory names, along with the slash that ends them, are added on to the prerequisite file names generated from the pattern rule’s prerequisite patterns and the file name. The directories are ignored only for the purpose of finding an implicit rule to use, not in the application of that rule. Thus, ‘e%t’ matches the file name src/eat, with ‘src/a’ as the stem. When prerequisites are turned into file names, the directories from the stem are added at the front, while the rest of the stem is substituted for the ‘%’. The stem ‘src/a’ with a prerequisite pattern ‘c%r’ gives the file name src/car.

The above explains why nice/path/ is prepended to prerequisite /project/something/1.bar.


One fix would be to use full file names in rules, e.g.:

${CURDIR}/nice/path/%.foo: /project/something/%.bar    
like image 185
Maxim Egorushkin Avatar answered Nov 15 '22 22:11

Maxim Egorushkin