【问题标题】:Variables inside makefile function are not expanded correctly?makefile 函数中的变量没有正确展开?
【发布时间】:2016-12-14 13:46:02
【问题描述】:

这是一个玩具 Makefile。 我想创建文件“a”、“b”、“c”以及“a.out”、“b.out”、“c.out”。

LIST=a b c
all: $(addsuffix .out,$(LIST))

define FUN
  in := $(1)
  out := $(1).out
  $$(in) :
        echo $(1) > $$(in)
  $$(out) : $$(in)
        echo $$(in) > $$(out)
endef
$(foreach p,$(LIST),\
  $(eval $(call FUN,$(p))))

当我使用“make -n”测试运行它时,版本 GNU Make 4.1, 实际执行的命令是:

echo a > c
echo c > c.out
echo b > c
echo c > c.out
echo c > c
echo c > c.out

但是,预期的结果是:

echo a > a
echo a > a.out
echo b > b
echo b > b.out
echo c > c
echo c > c.out

有人可以帮助解释 Makefile 的行为或如何修复此脚本吗?谢谢。

【问题讨论】:

    标签: makefile


    【解决方案1】:

    您为什么不到处使用$1 变量而不是创建新变量?没有规则说您必须在扩展中使用变量。你可以写成:

    define FUN
      $1 :
            echo $1 > $1
      $1.out : $1
            echo $1 > $1.out
    endef
    

    如果你不想这样做,你可以像这样使用automatic variables

    define FUN
      $1 :
            echo $$@ > $$@
      $1.out : $1
            echo $$< > $$@
    endef
    

    编辑

    没有看到某种现实的例子就很难判断。对您的问题的简短回答是否定的,没有什么神奇的方法可以在 makefile 中创建“可变范围”。

    您应该始终使用$@$&lt; 和其他自动变量。这就是他们的目的。如果您有其他需要的变量赋值,并且希望将它们设置为变量而不是直接使用调用参数,那么您只有两个选择:特定于目标的变量或constructed macro names

    但我并没有真正看到“目标特定变量的长列表”的问题。为什么要麻烦全局设置变量然后再将它们设置为特定于目标?如果您只是将它们直接设置为特定于目标的变量,则只需编写一次。目前还不清楚你对它们的使用有什么“尴尬”,所以我不能说这是否足够。

    此外,您应该在主目标上设置特定于目标的变量,而不是先决条件,因为特定于目标的变量是通过先决条件列表“继承”的。

    所以,像这样:

    define FUN
      $1.out : FOO = $(some complex thing)
    
      $1 :
            echo $$(FOO) > $$@
      $1.out : $1
            echo $$(FOO) from $$< > $$@
    endef
    

    【讨论】:

    • 在这个简化的例子中,你的答案很有效。但对于真正的问题,我确实希望找到一种在define ... endef 中使用变量的方法,而不需要一长串特定于目标的变量。您碰巧知道解决方案吗?谢谢。
    【解决方案2】:

    这是我回答这个问题的尝试,它对代码进行了繁琐的修复。我在这里发帖的原因是等待更好的答案。

    根据 GNU Make 手册 (https://www.gnu.org/software/make/manual/make.html#Reading-Makefiles),立即评估目标和先决条件,并推迟配方部分。

    在我的示例中,$$(out) : $$(in) 会立即进行评估。这就是我所期望的。但echo $$(in) &gt; $$(out) 稍后会展开。此时,$$(in) 变为 c$$(out) 变为 c.out。但这不是我想要的。

    在我看来,一个尴尬的解决方法是使用特定于目标的变量 (https://www.gnu.org/software/make/manual/make.html#Target_002dspecific)。现在 Makefile 如下所示:

    LIST=a b c
    all: $(addsuffix .out,$(LIST))
    
    define FUN
      in := $(1)
      out := $(1).out
      $$(in) : in=$(1)
      $$(in) :
        echo $(1) > $$(in)
      $$(out) : $$(in)
        echo $$(in) > $$(out)
    endef
    $(foreach p,$(LIST),\
      $(eval $(call FUN,$(p))))
    

    目标特定变量在$$(in) : in=$(1) 中指定。 但是,当配方部分有多个变量时,您将不得不添加多个特定于目标的变量,这看起来不太好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-21
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多