Reputation: 823
Similar questions have been asked already, but I do not understand their answers.
About matching, make
's documentation says
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.
Consider the following example: my makefile is
%.out: input/%.in
echo $<
and I perform the following steps:
mkdir hello
mkdir -p input/hello
touch input/hello/world.in
make hello/world.out
This results in make not finding any rule how to build its target. But actually, I do not understand how the documentation explains this behavior, although it seems that the community agrees on that being the documented behavior. Also, I do not know how to circumvent this; resorting to fixed directory names unfortunately is no (easy to implement) option.
Upvotes: 1
Views: 1340
Reputation: 99164
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.
Make is trying to build the file hello/world.out
, and looks for a matching rule. In this rule, the target pattern (%.out
) does not contain a slash, so Make removes the directory name from the file name (leaving world.out
) before comparing it to the target, %.out
. It matches!
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.
So the stem is world
, and Make first constructs the prerequisite name according to the pattern (input/world.in
) and then adds the directory name it removed earlier (hello/
), so the rule requires the prerequisite hello/input/world.in
, which does not exist (and cannot be built).
One solution is to use the vpath
directive:
vpath %.in input
%.out: %.in
echo $<
Now Make knows to search for hello/world.in
in input/
.
Upvotes: 2