0

I have a command with two dollar signs (secondary expansion)

$(PREFIX)/bin/gdk-pixbuf-query-loaders > $(shell $(PREFIX)/bin/gdk-pixbuf-query-loaders | awk -F "=" '/LoaderDir/ {print $$2}' | tr -d ' ')/../loaders.cache

The shell command should extract a path from the following output:

...
# LoaderDir = /home/redux/x-libs/i686-nptl-linux-gnu/lib/gdk-pixbuf-2.0/2.10.0/loaders
...

When I run make then the rule expands to the following command:

/home/redux/x-libs/i686-nptl-linux-gnu/bin/gdk-pixbuf-query-loaders > /home/redux/x-libs/i686-nptl-linux-gnu/lib/gdk-pixbuf-2.0/2.10.0/loaders/../loaders.cache

That's OK, but if I use a second makefile that starts the first one, then the rule expands to

/home/redux/x-libs/i686-nptl-linux-gnu/bin/gdk-pixbuf-query-loaders > /../loaders.cache

and an error occures:

/bin/sh: 11: cannot create /../loaders.cache: Permission denied

The command to start the first makefile from the second makefile is as follows:

$(MAKE) -f $(makefile_path)/build_libs_for_host.mk .print_and_write_triplets $(RULES) JOBS=$(JOBS) HOST=$(patsubst build_host_%,%,$@)

And the command (in bash) to start the second makefile (that starts the first one I created) is:

time make -f ~/_dev/_pro/second.mk all RULES=build_gdk_pixbuf JOBS=-j4 |& tee ~/log_20170221_x-libs.txt

Both makefiles use .SECONDEXPANSION:. I can't see the mistake.

Now I'm stuck. What's wrong with this expansion?

GNU make has some magic rules and maybe I have to add a parameter to the $(MAKE) line?

B. A. Sylla
  • 419
  • 3
  • 13
  • Recursive make? Sounds like "fun". – melpomene Feb 21 '17 at 10:06
  • `,SECONDEXPANSION` relates only to evaluating prerequisites of rules; it has absolutely no effect on the contents of recipes. Given the information here we can't help you, there's something else missing that you haven't told us. I recommend running the individual commands and printing their output to see what the difference is. Perhaps one of the variables you've added to the command line is changing the behavior gdk-pixbuf-query-loaders. Add `$(info $(shell $(PREFIX)/bin/gdk-pixbuf-query-loaders))` and compare the two ways of invoking make. – MadScientist Feb 21 '17 at 12:45

1 Answers1

0

I found a solution. My full rule is too complex so I post simplified code to explain my solution.

First we have a rule that creates a folder and uses $(shell ...) in the same command:

all:
    mkdir -p $(PREFIX) && \
    cd $(PREFIX) && \
    cat $(PREFIX)/../$(INPUT) > $(shell cat $(PREFIX)/../$(INPUT) | awk -F "=" '/LoaderDir/ {print $$2}' | tr -d ' ')/./loaders.cache
    touch $@
    @echo [DONE]

This can fail, if the folder was not created before. In that case $(shell ...) will expand to an empty string. And the cat command will fail. We see here that this is not an expansion problem. It's a timing problem.

The solution is to break this rule into two parts:

all_pass1:
    mkdir -p $(PREFIX) && \
    touch $@
    @echo [DONE]

all_pass2: all_pass1
    cd $(PREFIX) && \
    cat $(PREFIX)/../$(INPUT) > $(shell cat $(PREFIX)/../$(INPUT) | awk -F "=" '/LoaderDir/ {print $$2}' | tr -d ' ')/./loaders.cache
    touch $@
    @echo [DONE]

Ok I have a solution. But I wonder why my first makefile worked and the second that started the first fail. And that's the reason why I posted this problem. That still seems to me like some GNU make magic.

For me it's solved, but feel free to comment or present a better solution, if you think there is a better one.

B. A. Sylla
  • 419
  • 3
  • 13