影响 Makefile 中变量值的方式

影响 Makefile 中变量值的方式

1,直接赋值

变量的赋值方式
Makefile 中变量的赋值方式影响着变量的覆盖和更新。主要有以下几种赋值方式:
简单赋值 (=): 变量在被赋值时展开,如果变量之前被赋值过,可以被后续的赋值覆盖。
递归赋值 (:=): 变量在被赋值时立即展开,之后的赋值不会影响已经赋值的变量。
条件赋值 (?= ): 只有在变量之前没有被赋值时,才会对变量进行赋值。
追加赋值 (+=): 将值追加到变量的当前值之后。


2,包含其他makefile文件

在 Makefile 中,变量的跨文件传递主要依赖于 Makefile 的包含机制和变量的赋值方式。
Makefile 允许一个文件包含另一个文件,这使得在多个文件之间共享变量成为可能。以下是一些关键点和规则,用于理解和实现 Makefile 变量的跨文件传递:
包含其他 Makefile
使用 include 指令可以将一个 Makefile 的内容包含到另一个 Makefile 中。例如:

include cpp_src.mk
-include cu_src.mk

则 cpp_src.mk 中定义的变量会包含进来。

注意事项
当使用 include 包含其他 Makefile 时,被包含的 Makefile 中的变量和规则就好像是直接写在主 Makefile 中一样。
如果在多个被包含的 Makefile 中定义了相同的变量,那么变量的最终值将取决于赋值方式和包含的顺序。
使用条件赋值可以避免在不同文件中对同一个变量的重复赋值。


3,导出为环境变量

可以在调用子 Makefile 前,将需要传递的变量导出为环境变量。在子 Makefile 中,这些环境变量就可以像普通的 Makefile 变量一样被访问。
例如:
 

export VAR_NAME=value
all:
    make -C subdir

4,通过命令行传递变量


另一种方法是在 make -C dir 命令中直接指定变量的值,这样在子 Makefile 中就可以访问这些变量了。

例如:
 

all:
    make -C subdir VAR_NAME="value"


5,使用 make 的 -e 选项


使用 -e 选项,可以让环境中的变量覆盖 Makefile 中的同名变量。
这意味着如果你在父 Makefile 中导出了一个环境变量,然后使用 -e 选项调用 make -C dir,子 Makefile 中的同名变量将会被环境变量的值覆盖。
例如:
 

export VAR_NAME=value
all:
    make -e -C subdir

注意
使用环境变量的方法可能会受到操作系统对环境变量长度和数量的限制。
通过命令行传递变量是显式的,容易理解和维护,但可能会使命令行变得很长。
使用 -e 选项可以方便地覆盖子 Makefile 中的变量,但可能会导致预期之外的行为,因为它会使所有的环境变量都能覆盖 Makefile 中的同名变量。

6,优先级


 6.1 命令行定义的变量(最高优先级)


 当你在命令行中直接为 make 命令指定变量时,这些变量的值具有最高优先级。例如:
           

 make -C subdir VAR="value"


 这里,VAR 的值在子 Makefile 的执行过程中将被设置为 "value",无论子 Makefile 内部如何定义 VAR。
 
 


 6.2 环境变量(受 -e 选项影响)


 默认情况下,Makefile 中定义的变量会覆盖同名的环境变量。
 但是,如果使用了 make 的 -e 选项,环境变量将具有更高的优先级,能够覆盖 Makefile 中的同名变量定义。
 这适用于从父 Makefile 传递到子 Makefile 的环境变量:

export VAR="value from environment"


如果在父 Makefile 中这样导出变量,并在调用子 Makefile 时使用 -e 选项,那么环境变量将覆盖子 Makefile 中的同名变量。


 6.3 子 Makefile 中的变量定义


 子 Makefile 中直接定义的变量(不考虑通过命令行或环境变量传递的情况)。这些定义根据赋值方式(=、:=、?=、+=)有不同的行为。
 
 


 6.4 父 Makefile 中通过 export 导出的变量


 父 Makefile 可以通过 export 关键字导出变量,使其成为环境变量,这些环境变量在子 Makefile 中可用,除非被命令行变量或 -e 选项影响的环境变量覆盖。
 


 6.5 包含的 Makefile 中的变量


 当一个 Makefile 使用 include 指令包含另一个 Makefile 时,被包含 Makefile 中的变量定义会影响到当前 Makefile。
 这种情况下,被包含 Makefile 中的变量定义相当于直接写在包含它的 Makefile 中。
 

 6.6 默认变量


Make 提供的默认变量(如 CC 默认为 cc)。如果在 Makefile 中没有显式定义这些变量,它们将使用默认值。

总结优先级
1. 命令行定义的变量(最高优先级)
2. 环境变量(受 -e 选项影响)
3. 子 Makefile 中的变量定义
4. 父 Makefile 中通过 export 导出的变量
5. 包含的 Makefile 中的变量
6. 默认变量


7, .EXPORT_ALL_VARIABLES


In Makefile, to ensure that all variables are automatically exported to child Makefiles or subprocesses,
you can use the `.EXPORT_ALL_VARIABLES` special variable.
This tells [make]  to export all variables to the environment of every shell command.
 It does not need to be assigned a value; its presence in the Makefile is sufficient.

8, 对 ?= 变量的影响方式

在 Makefile 中,`?=` 操作符用于条件赋值,即只有当变量之前未被定义(即未被赋值)时,才会对其进行赋值。这意味着,如果一个变量在子 Makefile 中使用 `?=` 被赋值,那么它只会在该变量在之前的环境中未被定义时接受这个赋值。

对于父 Makefile 和子 Makefile 的交互,以下是几种情况下父 Makefile 中的同名变量会改变子 Makefile 中变量的值:

8.1. 父 Makefile 中通过命令行传递变量

如果在调用子 Makefile 时,通过命令行传递了同名变量,那么这个变量的值会被传递给子 Makefile,即使子 Makefile 中使用了 `?=` 进行了条件赋值。命令行传递的变量具有最高优先级。

8.2. 父 Makefile 中导出变量

如果父 Makefile 中通过 `export` 明确导出了一个变量,那么这个变量会成为环境变量,子 Makefile 在执行时会继承这个环境变量。如果子 Makefile 中使用 `?=` 对同名变量进行了条件赋值,由于环境变量已经定义了该变量,子 Makefile 中的赋值将不会生效。

8.3. 使用 `.EXPORT_ALL_VARIABLES`

如果父 Makefile 中声明了 `.EXPORT_ALL_VARIABLES`,那么所有在父 Makefile 中定义的变量都会自动导出为环境变量。这意味着,如果子 Makefile 中使用 `?=` 对同名变量进行了条件赋值,这个赋值将不会生效,因为该变量已经通过父 Makefile 被定义了。

8.4 注意

- 如果子 Makefile 在使用 `?=` 赋值之前已经通过其他方式(如直接赋值或通过命令行参数)接收到了该变量的值,那么 `?=` 的赋值将不会生效,因为该变量已经被定义。
- `?=` 的赋值只有在变量之前未被定义时才会生效,这包括之前没有被赋值或者被赋予空值。

总的来说,父 Makefile 中的同名变量会通过命令行参数传递、环境变量(包括使用 `export` 或 `.EXPORT_ALL_VARIABLES`)影响子 Makefile 中使用 `?=` 定义的变量的值,前提是这些操作发生在子 Makefile 执行之前。

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值