Makefile 用规则做出奇怪的行为
我有一个创建文件的规则,还有一个复制它的规则。但是在运行make时,规则的先决条件被调用了两次,但我不知道为什么 如果先决条件中有$(shell./myscript)而不是实际的$(警告…),则会调用该脚本两次 复制错误的生成文件:Makefile 用规则做出奇怪的行为,makefile,gnu,Makefile,Gnu,我有一个创建文件的规则,还有一个复制它的规则。但是在运行make时,规则的先决条件被调用了两次,但我不知道为什么 如果先决条件中有$(shell./myscript)而不是实际的$(警告…),则会调用该脚本两次 复制错误的生成文件: NAME := test $(NAME): @touch $@ install-$(NAME): $(NAME) install-copy-$(NAME) .PHONY: install-$(NAME) .PRECIOUS: %.copy .SECO
NAME := test
$(NAME):
@touch $@
install-$(NAME): $(NAME) install-copy-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: %.copy
.SECONDEXPANSION:
%.copy: $$*
@cp $< $@
install-copy-%: $$(warning START) $$*.copy $$(warning END)
@echo done
make: START
make: START
make: END
done
make: START
make: END
done
NAME := test
INSTALL_DIR := saved
# generate the documentation into $$*/
generateDoc-%:
touch $*/$(shell head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
install-$(NAME): generateDoc-$(NAME) install-doc-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: $(INSTALL_DIR)/%
.SECONDEXPANSION:
$(INSTALL_DIR)/%: $$(NAME)/$$*
cp $< $@
install-doc-%: $$(warning START) $$(subst $$*,$$(INSTALL_DIR),$$(shell find $$* -type f)) $$(warning END)
@echo done
预期输出:
NAME := test
$(NAME):
@touch $@
install-$(NAME): $(NAME) install-copy-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: %.copy
.SECONDEXPANSION:
%.copy: $$*
@cp $< $@
install-copy-%: $$(warning START) $$*.copy $$(warning END)
@echo done
make: START
make: START
make: END
done
make: START
make: END
done
NAME := test
INSTALL_DIR := saved
# generate the documentation into $$*/
generateDoc-%:
touch $*/$(shell head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
install-$(NAME): generateDoc-$(NAME) install-doc-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: $(INSTALL_DIR)/%
.SECONDEXPANSION:
$(INSTALL_DIR)/%: $$(NAME)/$$*
cp $< $@
install-doc-%: $$(warning START) $$(subst $$*,$$(INSTALL_DIR),$$(shell find $$* -type f)) $$(warning END)
@echo done
为什么START被输出两次?
如果我有一个调用脚本而不是$(警告)的函数,那么脚本将被调用两次
我不知道。。。
我希望保留.second扩展,因为我不希望在未调用规则时调用$(shell脚本…)或$(警告…)。
我无法列出将安装在.PRECIOUS中的所有文件,因为我不知道,因为此文件是由外部脚本生成的。(像强氧)。使用.PRECIOUS:%.copy第一次输出START两次,但一旦文件存在,则输出START一次
谢谢
带有真实案例的Makefile:
NAME := test
$(NAME):
@touch $@
install-$(NAME): $(NAME) install-copy-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: %.copy
.SECONDEXPANSION:
%.copy: $$*
@cp $< $@
install-copy-%: $$(warning START) $$*.copy $$(warning END)
@echo done
make: START
make: START
make: END
done
make: START
make: END
done
NAME := test
INSTALL_DIR := saved
# generate the documentation into $$*/
generateDoc-%:
touch $*/$(shell head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
install-$(NAME): generateDoc-$(NAME) install-doc-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: $(INSTALL_DIR)/%
.SECONDEXPANSION:
$(INSTALL_DIR)/%: $$(NAME)/$$*
cp $< $@
install-doc-%: $$(warning START) $$(subst $$*,$$(INSTALL_DIR),$$(shell find $$* -type f)) $$(warning END)
@echo done
NAME:=test
安装目录:=已保存
#将文档生成到$$*/
generateDoc-%:
触摸$*/$(壳体封头/开发/铀矿场-tr-dc A-Za-z0-9封头-c 13;回波“”)
安装-$(名称):generateDoc-$(名称)安装文档-$(名称)
.PHONY:install-$(名称)
.PRECIOUS:$(安装目录)/%
.第二次扩展:
$(安装目录)/%:$$(名称)/$$*
cp$<$@
安装文档-%:$$(警告开始)$$(子文件$$*,$$(安装目录),$$(shell查找$$*-类型f))$$(警告结束)
@回音完成
make-d
解释了在进行目标测试之后,它会尝试使目标安装副本测试(调用第一对开始/结束)。之后,它将使用中间文件test.copy
查找规则
所有这些都假设您运行makeinstalltest
> make install-test -n
touch test
make: START
make: END
make: START
make: END
cp test test.copy
done
rm test.copy
自然的解决办法是指定
.PRECIOUS: $(NAME).copy
我不知道,但是把警告
语句放在先决条件列表中是非常奇怪的。是的,这只是为了表明先决条件被读取了两次。。。我使用一个shell命令来列出需要安装的文件,而不是此警告。此命令代价高昂,我不想启动两次。如果doxygen在/usr/doc中创建文件,则shell ls$$$*/documentation
将找不到要从中复制的文件no,首先,我们使用generateDoc-%生成文档:它将文档文件生成到test/documentation中,然后我们调用install doc-,将文档安装到/usr/doc:ls test/documentation中会找到所有生成的文件。但是目标`$(NAME)/documentation/%`是最新的,cp测试/文档/%
到/usr/doc
将不会发生。我无法在preciouse中添加.copy,我可以只添加preciouse:%.copy但不起作用。(仅当文件已存在时有效,但不是第一次)。我无法添加所有.copy名称,因为它的文件是由外部脚本(doxygen)生成的。因此,我运行doxygen命令,然后运行$(shell在doxygen目录中查找,以获取要安装的所有文件),因此解决方案不起作用:(您可以将.PRECIOUS:$(名称)。甚至在.SECONDEXPANSION:
之前复制。
(实际上,$(名称):
也可以移到上面)。我的意思是,$(名称).copy
,而不是%.copy
!是的,但我不能。这里只是一个复制我的案例的例子。在我的真实案例中,它不是$(NAME).copy,但所有由doxygen生成的文件。我无法添加。请珍惜doxygen将生成的所有文件名。您明白吗?让我们尝试准备一个简单的示例,更好地表示您的用例。此外,您是否需要保留.copy文件?也许,make最终删除它们会更好?