二次扩展和两个makefile
Secondary expansion and two makefiles
我有一个带有两个美元符号的命令(二次扩展)
$(PREFIX)/bin/gdk-pixbuf-query-loaders > $(shell $(PREFIX)/bin/gdk-pixbuf-query-loaders | awk -F "=" '/LoaderDir/ {print $}' | tr -d ' ')/../loaders.cache
shell 命令应从以下输出中提取路径:
...
# LoaderDir = /home/redux/x-libs/i686-nptl-linux-gnu/lib/gdk-pixbuf-2.0/2.10.0/loaders
...
当我 运行 make 时,规则扩展为以下命令:
/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
没关系,但如果我使用第二个 makefile 来启动第一个 makefile,则规则会扩展为
/home/redux/x-libs/i686-nptl-linux-gnu/bin/gdk-pixbuf-query-loaders > /../loaders.cache
发生错误:
/bin/sh: 11: cannot create /../loaders.cache: Permission denied
从第二个makefile开始第一个makefile的命令如下:
$(MAKE) -f $(makefile_path)/build_libs_for_host.mk .print_and_write_triplets $(RULES) JOBS=$(JOBS) HOST=$(patsubst build_host_%,%,$@)
启动第二个 makefile(启动我创建的第一个 makefile)的命令(在 bash 中)是:
time make -f ~/_dev/_pro/second.mk all RULES=build_gdk_pixbuf JOBS=-j4 |& tee ~/log_20170221_x-libs.txt
两个 makefile 都使用 .SECONDEXPANSION:
。我看不出错误。
现在我卡住了。这个扩展有什么问题?
GNU make 有一些神奇的规则,也许我必须在 $(MAKE)
行中添加一个参数?
我找到了解决办法。我的完整规则太复杂,所以我 post 简化了代码来解释我的解决方案。
首先我们有一个创建文件夹并在同一命令中使用 $(shell ...)
的规则:
all:
mkdir -p $(PREFIX) && \
cd $(PREFIX) && \
cat $(PREFIX)/../$(INPUT) > $(shell cat $(PREFIX)/../$(INPUT) | awk -F "=" '/LoaderDir/ {print $}' | tr -d ' ')/./loaders.cache
touch $@
@echo [DONE]
如果之前没有创建文件夹,这可能会失败。在这种情况下 $(shell ...)
将扩展为一个空字符串。并且 cat 命令将失败。我们在这里看到这不是扩展问题。这是一个时间问题。
解决方案是将此规则分为两部分:
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 $}' | tr -d ' ')/./loaders.cache
touch $@
@echo [DONE]
好的,我有办法。但我想知道为什么我的第一个 makefile 有效而第二个开始第一个失败。这就是我 post 解决这个问题的原因。在我看来,这仍然像是一些 GNU 魔法。
对我来说它已经解决了,但如果您认为有更好的解决方案,请随时发表评论或提出更好的解决方案。
我有一个带有两个美元符号的命令(二次扩展)
$(PREFIX)/bin/gdk-pixbuf-query-loaders > $(shell $(PREFIX)/bin/gdk-pixbuf-query-loaders | awk -F "=" '/LoaderDir/ {print $}' | tr -d ' ')/../loaders.cache
shell 命令应从以下输出中提取路径:
...
# LoaderDir = /home/redux/x-libs/i686-nptl-linux-gnu/lib/gdk-pixbuf-2.0/2.10.0/loaders
...
当我 运行 make 时,规则扩展为以下命令:
/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
没关系,但如果我使用第二个 makefile 来启动第一个 makefile,则规则会扩展为
/home/redux/x-libs/i686-nptl-linux-gnu/bin/gdk-pixbuf-query-loaders > /../loaders.cache
发生错误:
/bin/sh: 11: cannot create /../loaders.cache: Permission denied
从第二个makefile开始第一个makefile的命令如下:
$(MAKE) -f $(makefile_path)/build_libs_for_host.mk .print_and_write_triplets $(RULES) JOBS=$(JOBS) HOST=$(patsubst build_host_%,%,$@)
启动第二个 makefile(启动我创建的第一个 makefile)的命令(在 bash 中)是:
time make -f ~/_dev/_pro/second.mk all RULES=build_gdk_pixbuf JOBS=-j4 |& tee ~/log_20170221_x-libs.txt
两个 makefile 都使用 .SECONDEXPANSION:
。我看不出错误。
现在我卡住了。这个扩展有什么问题?
GNU make 有一些神奇的规则,也许我必须在 $(MAKE)
行中添加一个参数?
我找到了解决办法。我的完整规则太复杂,所以我 post 简化了代码来解释我的解决方案。
首先我们有一个创建文件夹并在同一命令中使用 $(shell ...)
的规则:
all:
mkdir -p $(PREFIX) && \
cd $(PREFIX) && \
cat $(PREFIX)/../$(INPUT) > $(shell cat $(PREFIX)/../$(INPUT) | awk -F "=" '/LoaderDir/ {print $}' | tr -d ' ')/./loaders.cache
touch $@
@echo [DONE]
如果之前没有创建文件夹,这可能会失败。在这种情况下 $(shell ...)
将扩展为一个空字符串。并且 cat 命令将失败。我们在这里看到这不是扩展问题。这是一个时间问题。
解决方案是将此规则分为两部分:
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 $}' | tr -d ' ')/./loaders.cache
touch $@
@echo [DONE]
好的,我有办法。但我想知道为什么我的第一个 makefile 有效而第二个开始第一个失败。这就是我 post 解决这个问题的原因。在我看来,这仍然像是一些 GNU 魔法。
对我来说它已经解决了,但如果您认为有更好的解决方案,请随时发表评论或提出更好的解决方案。