0

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

  • Just to note, I don't know what you mean in your question title by `.PHONY pattern rule`, but you are not declaring _anything_ `.PHONY` here since its prerequisite list is empty. But, phoniness is not related to your question anyway. – MadScientist Jun 08 '21 at 11:53
  • @MadScientist D'oh, that was a typo. Anyway, I just added that info just in case it triggered some different behavior, but I guess it doesn't. – alx - recommends codidact Jun 08 '21 at 11:56
  • @MadScientist, could you review the tests I added? It looks like .PHONY: is doing something... – alx - recommends codidact Jun 08 '21 at 15:58
  • Looks like I'm having this problem too: https://stackoverflow.com/a/3096699/6872717 If someone needs to know, I could only find that behavior with `make -p`. The other debug options like `--trace` or `-d` were useless in this case. – alx - recommends codidact Jun 08 '21 at 16:13
  • 1
    When asking please explain clearly what is wrong with the results you show (what you expected to be different). It takes a lot of time to suss out the problem you're trying to solve on our own. But yes, as that other question mentions, a `.PHONY` target is never eligible to be looked up with implicit rules. That's one of the primary reasons to declare a target `.PHONY`: to improve performance. You can use the `FORCE` trick if all you care about it ensuring rebuilds without improving performance. – MadScientist Jun 08 '21 at 16:28
  • 1
    My original comment about "not doing anything" only referred to your initial question/ makefile, where the `.PHONY` target had no prerequisites. That is a no-op. – MadScientist Jun 08 '21 at 16:29

2 Answers2

2

You need to examine the section on How Patterns Match where you will find this text:

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.

(and more detail about how this works).

MadScientist
  • 92,819
  • 9
  • 109
  • 136
1

As per documentation and @MadScientist answer, this is how patterns match. But workaround is very simple: replace your prefix rules with suffix rules and this directory mangling will not stand in the way.

Example:

$ cat Makefile
.PHONY: %-clean
%-clean:
        $(info $*)

.PHONY: foo
foo: /as/d-clean
        @:

.PHONY: bar
bar: ./as/d-clean
        @:

Output:

$ make foo
/as/d
$ make bar
as/d

BTW. Please note that .PHONY: requires target name, it does not automagically apply to the target that follows.

raspy
  • 3,995
  • 1
  • 14
  • 18