makefilepattern-matchinggnu-makecode-cleanup

Makefile: reuse value of % of a pattern rule inside the recipe


In a Makefile I have:

images/schematic.pdf: images/schematic.svg
      inkscape -D -z --file=$^ --export-pdf=$@ --export-latex
      sed -i "s:schematic:images/schematic:g" $@_tex

What this rule does is:

My problem:

I have many rules in this form i. e. where only schematic is changed. I would like to use a pattern-rule that replaces schematic by %. And to use % in the recipe (in the sed command).

However the rule:

images/%.pdf: images/%.svg
     inkscape -D -z --file=$^ --export-pdf=$@ --export-latex
     sed -i "s:%:images/%:g" $@_tex

does not work: % is interpreted literally in the recipe.

I also tried to replace % in the recipe by $% but this variable seems to be empty.

Unsatisfactory solution:

Add a line in the recipe to create a (make) variable that will hold the result of notdir(removeprefix($<)) (using this question or a call to bash because there is no removeprefix in GNU Make).


Solution

  • You want $*. From https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html :

    $*: The stem with which an implicit rule matches (see How Patterns Match). If the target is dir/a.foo.b and the target pattern is a.%.b then the stem is dir/foo. The stem is useful for constructing names of related files.

    In a static pattern rule, the stem is part of the file name that matched the ‘%’ in the target pattern.

    In an explicit rule, there is no stem; so ‘$*’ cannot be determined in that way. Instead, if the target name ends with a recognized suffix (see Old-Fashioned Suffix Rules), ‘$*’ is set to the target name minus the suffix. For example, if the target name is ‘foo.c’, then ‘$*’ is set to ‘foo’, since ‘.c’ is a suffix. GNU make does this bizarre thing only for compatibility with other implementations of make. You should generally avoid using ‘$*’ except in implicit rules or static pattern rules.

    If the target name in an explicit rule does not end with a recognized suffix, ‘$*’ is set to the empty string for that rule.

    $% is an automatic variable, but it's for archive (.a library) members, and almost never useful.