首页 文章

GNU Makefile变量赋值=,?=,:=和=之间有什么区别?

提问于
浏览
651

任何人都可以清楚地解释变量赋值在Makefile中是如何工作的 .

有什么区别:

VARIABLE = value
 VARIABLE ?= value
 VARIABLE := value
 VARIABLE += value

我已经阅读了GNU Make _491214中的section对我有意义 .

5 回答

  • 875

    使用 = 会为变量赋值 . 如果变量已有值,则替换它 . 使用时,该值将被扩展 . 例如:

    HELLO = world
    HELLO_WORLD = $(HELLO) world!
    
    # This echoes "world world!"
    echo $(HELLO_WORLD)
    
    HELLO = hello
    
    # This echoes "hello world!"
    echo $(HELLO_WORLD)
    

    使用 := 类似于使用 = . 但是,在使用它时,不是在扩展值时,而是在赋值期间扩展它 . 例如:

    HELLO = world
    HELLO_WORLD := $(HELLO) world!
    
    # This echoes "world world!"
    echo $(HELLO_WORLD)
    
    HELLO = hello
    
    # Still echoes "world world!"
    echo $(HELLO_WORLD)
    
    HELLO_WORLD := $(HELLO) world!
    
    # This echoes "hello world!"
    echo $(HELLO_WORLD)
    

    如果先前未分配变量,则使用 ?= 为变量赋值 . 如果先前为变量分配了一个空白值( VAR= ),我认为它仍然被认为是设置 . 否则,函数与 = 完全相同 .

    使用 += 就像使用 = ,但不是替换值,而是将值附加到当前值,中间有一个空格 . 如果变量先前已使用 := 设置,我认为它已扩展 . 在我认为使用它时,结果值会扩展 . 例如:

    HELLO_WORLD = hello
    HELLO_WORLD += world!
    
    # This echoes "hello world!"
    echo $(HELLO_WORLD)
    

    如果使用类似 HELLO_WORLD = $(HELLO_WORLD) world! 的东西,将导致递归,这很可能会结束Makefile的执行 . 如果使用了 A := $(A) $(B) ,则结果与使用 += 的结果不完全相同,因为 B:= 展开,而 += 不会导致 B 展开 .

  • 5

    我建议你用"make"做一些实验 . 这是一个简单的演示,显示了 =:= 之间的区别 .

    /* Filename: Makefile*/
    x := foo
    y := $(x) bar
    x := later
    
    a = foo
    b = $(a) bar
    a = later
    
    test:
        @echo x - $(x)
        @echo y - $(y)
        @echo a - $(a)
        @echo b - $(b)
    

    make test 打印:

    x - later
    y - foo bar
    a - later
    b - later bar
    

    Check more elaborate explanation here

  • 29

    当您使用 VARIABLE = value 时,如果 value 实际上是对另一个变量的引用,则仅在使用 VARIABLE 时确定该值 . 最好用一个例子来说明:

    VAL = foo
    VARIABLE = $(VAL)
    VAL = bar
    
    # VARIABLE and VAL will both evaluate to "bar"
    

    当您使用 VARIABLE := value 时,您将获得 value 的值,就像现在一样 . 例如:

    VAL = foo
    VARIABLE := $(VAL)
    VAL = bar
    
    # VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"
    

    使用 VARIABLE ?= val 表示如果尚未设置 VARIABLE ,则仅设置 VARIABLE 的值 . 如果尚未设置,则延迟值的设置,直到使用 VARIABLE (如示例1所示) .

    VARIABLE += value 只需将 value 追加到 VARIABLE . value 的实际值确定为最初设置时的值,使用 =:= .

  • 228

    在上面的答案中, it is important to understand 是什么意思"values are expanded at declaration/use time" . 给出像 *.c 这样的值并不需要任何扩展 . 只有当命令使用此字符串时,它才会触发某些通配 . 类似地,像 $(wildcard *.c)$(shell ls *.c) 这样的值不需要任何扩展,并且在定义时完全评估,即使我们在变量定义中使用了 := .

    在您有一些C文件的目录中尝试以下Makefile:

    VAR1 = *.c
    VAR2 := *.c
    VAR3 = $(wildcard *.c)
    VAR4 := $(wildcard *.c)
    VAR5 = $(shell ls *.c)
    VAR6 := $(shell ls *.c)
    
    all :
        touch foo.c
        @echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
        @echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
        @echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
        @echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
        @echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
        @echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
        rm -v foo.c
    

    运行 make 将触发一条规则,该规则创建一个额外的(空)C文件,名为 foo.c ,但6个变量中没有一个变量的值为 foo.c .

  • 45

    懒人套装

    VARIABLE = value
    

    变量的正常设置 - 在使用变量时递归扩展其中的值,而不是在声明变量时

    立即设定

    VARIABLE := value
    

    通过简单扩展内部值来设置变量 - 其中的值在声明时间扩展 .

    设置如果缺席

    VARIABLE ?= value
    

    仅在变量没有值时设置变量

    追加

    VARIABLE += value
    

    将提供的值附加到现有值(如果变量不存在,则设置为该值)

相关问题