我有一个规则来创建一个文件,另一个规则来复制它。但是在运行make时,该规则的先决条件被调用了两次,但我不知道为什么!
如果先决条件中有一个$(shell ./myscript)而不是实际的$(warning ...),则该脚本会被调用两次!
再现错误的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
为什么START输出两次?如果我有一个调用脚本而不是$(warning)的函数,则该脚本将被调用两次。
我不知道...我想保留.SECONDEXPANSION,因为我不希望在不调用规则时调用$(shell脚本...)或$(警告...)。我无法列出将要安装在.PRECIOUS中的所有文件,因为由于该文件是由外部脚本生成的,因此我不知道。 (例如doxygen)。使用.PRECIOUS:%.copy,第一次将START输出两次,但是一旦文件存在,则将START输出一次...
谢谢!
带有实际大小写的Makefile:
NAME := test
INSTALL_DIR := /usr/doc
# generate the documentation into $$*/documentation
generateDoc-%:
@doxygen $*/config
install-$(NAME): generateDoc-$(NAME) install-doc-$(NAME)
.PHONY: install-$(NAME)
.PRECIOUS: $(INSTALL_DIR)/%
.SECONDEXPANSION:
$$*/documentation/%: $$(INSTALL_DIR)/$$*
@cp $< $@
install-doc-%: $$(warning START) $$(shell ls $$*/documentation) $$(warning END)
@echo done
make -d
解释说,在建立目标test
之后,它将尝试建立目标install-copy-test
(调用第一对START / END)。之后,它将查找带有中间文件test.copy
的规则。
所有这些都假设您运行了make install-test
> 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