John Freeman
John Freeman

Reputation: 2692

How to call functions within order-only prerequisites?

Given this bit of Makefile:

# for pattern matching
$(OBJDIR) := build

# just to see if a level of indirection will work
my_dir = $(dir $(1))

$(OBJECTS) : $(OBJDIR)/% : $(HEADERS) $(SRCDIR)/% | % $(dir %) $(call my_dir,%)
  @echo output-only = $|

This is a static pattern rule with order-only prerequisites.

Consider the target "build/utility/debug.js". The output of the above rule will be this:

output-only = utility/debug.js ./

If I change my_dir to this:

my_dir = $(1)

The output remains the same. If I change it to this:

my_dir = "foo"

Then make complains there is no rule to make "foo" (which is expected). It appears, then, that $(1) is not getting bound in the call to my_dir.

What's going on? Why can't I pass the stem to a function? I have a workaround that uses secondary expansion, but I want to know why I can't write my rule this way.

EDIT: I'm new to stackoverflow, forgive me if this is not the way things are done here.

I want $(1) because I am passing the stem as an argument to my_dir, as Alex pointed out.

I don't know why it was suggested I want "$". I don't believe $ by itself expands to anything in any context.

I know that automatic variables are only available in the recipe. I am not using an automatic variable in the prerequisites - I am using the stem:

Each target is matched against the target-pattern to extract a part of the target name, called the stem. This stem is substituted into each of the prereq-patterns to make the prerequisite names (one from each prereq-pattern). - the manual

The fact that the stem is available is demonstrated by the example: the stem expands to the correct value when used alone, but not when passed to a function.

Upvotes: 6

Views: 2122

Answers (2)

eriktous
eriktous

Reputation: 6649

As can be seen in this section of the GNU make manual, variable and function references in the list of prerequisites are immediately expanded, during the read in phase. This means, before any pattern matching is done, so the % has no special meaning yet; it is interpreted as a literal character in the two function references, $(dir %) and $(call my_dir,%), both having ./ as a result, which get merged in the reference to $| in the recipe.

I don't know of any other workaround than the one you already found, i.e. secondary expansion.

Upvotes: 3

MadScientist
MadScientist

Reputation: 100856

Note $1 is not a special variable that expands to anything interesting related to pattern rules (or static pattern rules). The $1 variable only has unique behavior within the context of a user-defined macro invoked by the $(call ...) function.

You wanted to use $*, not $1; $* is an automatic variable which expands to the stem of the target of the rule.

However, in all versions of make (including the POSIX standard definition of make), automatic variables (including $*, $<, $@, $^, etc.) are only available in the context of the recipe. They are not available in the context of the target or prerequisite lists. See the GNU make manual section on Automatic Variables for more details.

As you suggest, there is a GNU make-specific feature enabled by the .SECONDEXPANSION pseudo target which provides a way to avoid this limitation.

Upvotes: 3

Related Questions