I am trying to simplify a Makefile. In that, I tried to have a pattern rule for removing files:
.PHONY:
rm-%:
rm $*
where % would contain the name of the file (usually the absolute path with a leading slash).
And then I just state that rm-/some/file is a dependency of make uninstall
, and expect make to match this pattern rule.
However, it bite me. I did some tests and realized that the problem was that a leading slash did not match that pattern rule:
~/src/test$ cat Makefile
.PHONY:
a-/%:
$(info /$*)
.PHONY:
b-%:
$(info $*)
.PHONY:
foo: a-/as/d
@:
.PHONY:
bar: b-/as/d
@:
~/src/test$ make foo
/as/d
~/src/test$ make bar
make: *** No rule to make target 'b-/as/d', needed by 'bar'. Stop.
~/src/test$
Why do I need to specify that leading slash in the pattern rule (but not other slashes)?
The GNU make documentation says this:
the ‘%’ matches any nonempty substring, while other characters match only themselves
https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html#Pattern-Intro
EDIT: Fix some typos about .PHONY:
, use a suffix instead of a prefix as suggested in the answers/comments, and test further:
As I initially suspected, .PHONY:
is doing something weird:
~/src/test/$ tree a b c d
a
└── a
b
└── b
c
└── c
d
└── d
0 directories, 4 files
~/src/test$ cat Makefile
%-rmdir:
rmdir $(@D)
%-rm:
rm $*
.PHONY: ./a/.-rmdir
./a/.-rmdir: ./a/a-rm
.PHONY: ./b/-rmdir
./b/-rmdir: ./b/b-rm
./c/.-rmdir: ./c/c-rm
./d/-rmdir: ./d/d-rm
.PHONY: foo
foo: ./a/.-rmdir ./b/-rmdir ./c/.-rmdir ./d/-rmdir
$(info foo)
~/src/test$ make foo
rm a/a
rm b/b
rm c/c
rmdir c
rm d/d
rmdir d
foo