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?
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.