Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call functions within order-only prerequisites?

Tags:

makefile

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 ./
  • The first component, "utility/debug.js", is properly copied from the stem (%).
  • The second component, "./", is the output of calling the dir function in the prerequisites list.
  • The third component, an empty string, is the output of calling my my_dir function in the prerequisites list.

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.

like image 804
John Freeman Avatar asked Oct 08 '22 12:10

John Freeman


1 Answers

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.

like image 56
eriktous Avatar answered Oct 13 '22 11:10

eriktous