在Makefile目标中定义局部变量

问题描述 投票:0回答:3

如何在Makefile目标中定义局部变量?

我想避免重复文件名,例如:

zsh:
    FILENAME := "text.txt"
    @echo "Copying ${FILENAME}...";
    scp "${FILENAME}" "user@host:/home/user/${FILENAME}"

但是我收到错误:

FILENAME := "text.txt"
/bin/sh: FILENAME: command not found

$(FILENAME)

相同

尝试

zsh:
    export FILENAME="text.txt"
    @echo "Copying ${FILENAME} to $(EC2)";

给我一个空值:

Copying ...
gnu-make makefile
3个回答
13
投票

您不能在配方中定义 make 变量。食谱在 shell 中运行并且必须使用 shell 语法

如果您想定义 make 变量,请在配方之外定义它,如下所示:

FILENAME := text.txt
zsh:
        @echo "Copying ${FILENAME}...";
        scp "${FILENAME}" "user@host:/home/user/${FILENAME}"

注意,在将值分配给 make 变量时,在值周围添加引号实际上是不正确的。 Make 不关心引号(在变量值或扩展中),也不以任何方式特殊对待它们。


3
投票

目标的规则由 shell 执行,因此您可以使用 shell 语法设置变量:

zsh:
    @FILENAME="text.txt"; \
    echo "Copying $${FILENAME}..."; \
    scp "$${FILENAME}" "user@host:/home/user/$${FILENAME}"

请注意:

  • 我使用
    \
    转义行尾,以便所有内容都执行 一样的壳
  • 我通过编写
    $
    来转义 shell 变量中的
    $$
    (否则
    make
    将尝试将它们解释为
    make
    变量)。

对于这条规则,它显然取决于一个名为

text.txt
的文件, 您也可以将
text.txt
声明为显式依赖项,然后编写:

zsh: text.txt
    @echo "Copying $<..."; \
    scp "$<" "user@host:/home/user/$<"

0
投票

您可以使用 eval 在配方中设置变量。从这里的答案,我了解到您甚至可以通过自动在目标前面添加伪局部变量来创建伪局部变量。这是通过在变量前面加上

$@_
前缀来实现的。

mytarget:
    $(eval $@_foo = bar)
    @echo mytarget: $($@_foo)

other: mytarget
    @echo other: $($@_foo)

现在我们可以看到这按预期工作了。

mytarget
有变量,而
other
看不到它。

$ make other
mytarget: bar
other:
© www.soinside.com 2019 - 2024. All rights reserved.