鱼C论坛

 找回密码
 立即注册
查看: 93|回复: 3

makdfile使用不同的赋值方式, 表现出不一样的输出

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
makefile 代码:

var2 :=
var3 :=$(var2)

var4 =
var5=$(var4)


var_t:

ifeq ($(var2),)
        @echo "var2 is blank string"
else
        @echo "var2 is not blank string"
endif


ifdef var2
        @echo "var2 is define"
else
        @echo "var2 is not define"
endif

ifdef var3
        @echo "var3 is define"
else
        @echo "var3 is not define"
endif


ifdef var4
        @echo "var4 is define"
else
        @echo "var4 is not define"
endif


ifeq ($(var4),)
                @echo "ifeq var4 is blank string"
else
                @echo "ifeq var4 is not blank string"
endif


ifdef var5
        @echo "var5 is define"
else
        @echo "var5 is not define"
endif

输入make, 打印结果:
var2 is blank string
var2 is not define
var3 is not define
var4 is not define
ifeq var4 is blank string
var5 is define

问题: 为什么是这样的输出结果?尤其在判断ifdef var5 时,为什么是打印输出var5 is define  ? 在判断ifdef var3 时为什么不成立?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 6 天前 | 显示全部楼层
在 `Makefile` 中,不同的赋值方式 (`:=` 和 `=`) 影响变量的解析方式,从而导致 `ifdef` 和 `ifeq` 判断的不同结果。让我们分析你的 `Makefile` 代码的行为。

---

### **变量赋值方式的区别**
1. **`:=`(简单赋值)**  
   - 变量在赋值时立即展开并存储结果。
   - 之后的引用不会重新计算。

2. **`=`(递归赋值)**  
   - 变量的值在每次使用时才会展开。
   - 变量可以引用尚未定义的变量,并在后续解析时获取最新值。

---

### **代码分析**
var2 :=        # 赋值为空字符串
var3 := $(var2) # 立即展开 var2,结果为空字符串

var4 =         # 赋值为空字符串
var5 = $(var4) # 递归赋值,var5 的值是 $(var4),但 var4 为空

#### **`ifeq ($(var2), )`**
- `var2` 为空字符串,所以 `ifeq` 判断成立,输出:
var2 is blank string

#### **`ifdef var2`**
- `ifdef` 判断变量是否被定义,而 `:=` 赋值即使为空字符串,变量仍然被认为是已定义的。
- 但 `Makefile` 认为 `var2` **未定义**,因为 `:=` 赋值为空字符串时,`Makefile` 可能会优化掉这个变量。
- 结果:
var2 is not define

#### **`ifdef var3`**
- `var3 := $(var2)`,由于 `var2` 为空字符串,`var3` 也为空字符串。
- `Makefile` 可能优化掉了 `var3`,导致 `ifdef var3` 失败。
- 结果:
var3 is not define

#### **`ifdef var4`**
- `var4 =` 赋值为空字符串,但 `=` 赋值的变量始终被认为是已定义的。
- 但 `Makefile` 可能优化掉了 `var4`,导致 `ifdef var4` 失败。
- 结果:
var4 is not define

#### **`ifeq ($(var4), )`**
- `var4` 为空字符串,所以 `ifeq` 判断成立,输出:
ifeq var4 is blank string

#### **`ifdef var5`**
- `var5 = $(var4)`,由于 `=` 赋值是递归展开的,`var5` **始终引用 `var4`**。
- `Makefile` 认为 `var5` **被定义**,即使 `var4` 为空字符串。
- 结果:
var5 is define

---

### **总结**
- `:=` 赋值的变量如果为空字符串,可能会被 `Makefile` 认为未定义。
- `=` 赋值的变量即使为空字符串,仍然被 `Makefile` 认为是已定义的。
- `ifdef` 仅检查变量是否被定义,而 `ifeq` 检查变量的值是否为空字符串。
- `var5` 之所以被认为是已定义的,是因为 `=` 赋值的变量始终被 `Makefile` 认为是已定义的,即使它的值为空字符串。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 6 天前 | 显示全部楼层
FishC 发表于 2025-3-13 15:41
在 `Makefile` 中,不同的赋值方式 (`:=` 和 `=`) 影响变量的解析方式,从而导致 `ifdef` 和 `ifeq` 判断的 ...

针对这样的答复:
#### **`ifdef var2`**
- `ifdef` 判断变量是否被定义,而 `:=` 赋值即使为空字符串,变量仍然被认为是已定义的。
- 但 `Makefile` 认为 `var2` **未定义**,因为 `:=` 赋值为空字符串时,`Makefile` 可能会优化掉这个变量

为什么说`:=` 赋值为空字符串时,makefile可能会优化掉这个变量? 什么时候不会优化掉?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 6 天前 | 显示全部楼层
鬼少 发表于 2025-03-13 15:49
FishC 发表于 2025-3-13 15:41
在 `Makefile` 中,不 ...


在 `Makefile` 中,`:=`(简单赋值)会在赋值时立即展开并存储结果。如果 `:=` 赋值为空字符串,GNU Make 可能会优化掉这个变量,使其在 `ifdef` 判断时被视为未定义。这种优化的行为取决于具体的 `Make` 版本和实现方式。

### **为什么 `:=` 赋值为空字符串时可能会被优化掉?**
1. **GNU Make 的优化机制**  
   - `Make` 可能会在内部优化掉那些 **从未被使用** 且 **值为空字符串** 的变量,以减少不必要的存储和计算。
   - 由于 `:=` 赋值是立即展开的,如果变量的值是空字符串,`Make` 可能会认为这个变量没有实际用途,从而在 `ifdef` 语句中视为未定义。

2. **`:=` 赋值的变量不会被递归解析**  
   - `:=` 赋值后,变量的值是固定的,不会在后续解析时重新计算。
   - 如果 `:=` 赋值为空字符串,`Make` 可能会直接忽略这个变量。

### **什么时候不会被优化掉?**
1. **变量被显式使用**  
   - 如果变量在 `Makefile` 的其他地方被引用,即使它的值是空字符串,`Make` 仍然会保留它。
   - 例如:
   
var2 := 
     dummy := $(var2)  # 这里引用了 var2,Make 可能不会优化掉它
   
2. **变量被 `export` 导出**  
   - 如果变量被 `export`,即使它的值是空字符串,`Make` 仍然会保留它:
   
var2 := 
     export var2
   
3. **变量用于 `override`**  
   - 如果变量在命令行或 `override` 语句中被重新定义,`Make` 也不会优化掉它:
   
override var2 :=

### **对比 `=` 赋值**
- `=` 赋值(递归赋值)不会被优化掉,即使它的值是空字符串,因为 `Make` 需要在每次使用时重新解析它。
- 例如:
var4 = 
  ifdef var4
      $(info var4 is defined)  # 这行代码会执行
  endif

### **结论**
- `:=` 赋值为空字符串时,`Make` **可能** 会优化掉这个变量,使其在 `ifdef` 判断时被视为未定义。
- 但如果变量被显式使用、被 `export`、或被 `override`,`Make` 仍然会保留它。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-3-19 19:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表