没有第二次扩展的先决条件中的Target目录

时间:2015-11-09 17:17:53

标签: makefile gnu-make automatic-variable

让我们假设,我想打电话

make somepath/abc.pot

取决于somepath / somefiles.c

到目前为止我创建的目标看起来像

%.pot: $(dir $@)*.c
    @echo "it works"
ifeq (,$(wildcard $@))
#   pot-file does not exist, do something
else
#   pot-file already exists, do something else
endif

但不能用作Automatic Variables 像$ @在先决条件中不可用。

如果找到,我可以启用第二次扩展

.SECONDEXPANSION:
%.pot: $$(dir $$@)*.c
    @echo "it works"
ifeq (,$(wildcard $@))
#   pot-file does not exist, do something
else
#   pot-file already exists, do something else
endif

允许我在先决条件中使用$ @但是会破坏我的ifeq语句,然后它会导致第一个分支。如果我将ifeq更改为

ifeq (,$$(wildcard $$@))

它再次起作用,但我真的不明白为什么。

现在有两个问题:

A)是否有其他方法可以启用第二次扩展以在我的先决条件中拥有目标路径?

B)如果启用了第二次扩展,为什么ifeq (,$(wildcard $@))语句总是会产生第一个分支?

1 个答案:

答案 0 :(得分:0)

根本不要在食谱中使用ifeq。只需使用普通的shell功能。它效果更好。

.SECONDEXPANSION:
%.pot: $$(dir $$@)*.c
    @echo "it works"
    if [ ! -f $@ ]; then \
        : pot-file does not exist, do something; \
    else \
        : pot-file already exists, do something else; \
    fi

那就是说在先决条件列表中使用通配符通常是一个坏主意,因为它们被全局化的时间不可靠并且可能导致奇怪的行为。有关问题的一个示例,请参阅Pitfalls of Using Wildcards

如果您需要根据某些外部因素(如操作系统)编写不同的配方内容,那么您需要在生成解析时检测到该配方内容并拥有正确切换的配方/生成文件的两个副本。您可以那个内联,但不能按内联方式执行该操作。

您的原始尝试(在食谱中使用ifeq无效。他们没有做你认为他们做的事。他们可能出现工作,但他们没有按照您的预期工作。

考虑这个makefile:

全部:c

a:
        @touch a

c: a

.SECONDEXPANSION:

c d:
ifeq (,$(wildcard a))
        @echo "a doesn't exist (make)"
else
        @echo 'a does exist (make)'
endif
        @if [ ! -f a ]; then \
            echo "a doesn't exist (sh)"; \
        else \
            echo 'a does exist (sh)'; \
        fi
ifeq (,$$(wildcard a))
        @echo "a doesn't exist (make se)"
else
        @echo 'a does exist (make se)'
endif

在一个空目录中,您希望输出make(假设ifeq按您希望的方式工作):

a does exist (make)
a does exist (sh)
a does exist (make se)

右?但事实并非如此。你得到:

a doesn't exist (make)
a does exist (sh)
a does exist (make se)

好的,你认为,如果没有二次扩张,那就是没有用的东西。但是二级扩展版本正常运行。但事实并非如此。

如果你在一个空目录中运行make d(注意d目标没有列出a作为先决条件,所以它不会创建它)你会期望以下输出:

a doesn't exist (make)
a doesn' exist (sh)
a doesn' exist (make se)

右?但你实际得到的是:

a doesn't exist (make)
a doesn't exist (sh)
a does exist (make se)

所以看起来二级扩展版本也不起作用。

查看make数据库可以解释原因。

在空目录中运行make -qprR | awk '/c: a/,/^$/; /d:/,/^$/',您会看到:

c: a
#  Implicit rule search has not been done.
#  File does not exist.
#  File has been updated.
#  Needs to be updated (-q is set).
# variable set hash-table stats:
# Load=0/32=0%, Rehash=0, Collisions=0/2=0%
#  commands to execute (from `Makefile', line 12):
        @echo "a doesn't exist (make)"
        @if [ ! -f a ]; then \
        echo "a doesn't exist (sh)"; \
        else \
        echo 'a does exist (sh)'; \
        fi
        @echo 'a does exist (make se)'


d:
#  Implicit rule search has not been done.
#  Modification time never checked.
#  File has not been updated.
#  commands to execute (from `Makefile', line 12):
        @echo "a doesn't exist (make)"
        @if [ ! -f a ]; then \
        echo "a doesn't exist (sh)"; \
        else \
        echo 'a does exist (sh)'; \
        fi
        @echo 'a does exist (make se)'

正如您所看到的,它不包含ifeq行,而只包含ifeq逻辑的“正确”分支。

这就是问题,ifeq条件在make解析时计算,在任何配方运行之前 well (因此在创建任何文件之前等)。< / p>