使用规则进行怪异行为

问题描述 投票:1回答:1

我有一个规则来创建一个文件,另一个规则来复制它。但是在运行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

makefile gnu
1个回答
0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.