06-07 - 变量的高级主题

发布于:2024-05-07 ⋅ 阅读:(36) ⋅ 点赞:(0)

---- 整理自狄泰软件唐佐林老师课程

1. 变量值的替换

  • 使用指定字符(串)替换变量值中的后缀字符(串)
  • 语法格式:$(var:a=b)${var:a=b},即:使用 b 替换变量 var 的后缀 a
    • 替换表达式中不能有任何的空格
    • make 中支持使用 ${} 对变量进行取值
src := a.cc b.cc c.cc
obj := $(src:cc=o)

test:
	@echo "obj => $(obj)"

在这里插入图片描述

2. 变量的模式替换

  • 使用 % 保留变量值中的指定字符串,替换其它字符。% 可以理解为 Makefile 中的通配符
  • 语法格式:$(var:a%b=x%y)${var:a%b=x%y}
    • 替换表达式中不能有任何空格
    • make 中支持使用 ${} 对变量进行取值
src := a1b.c a2b.c a3b.c
obj := $(src:a%b.c=x%y)

test:
	@echo "obj => $(obj)"

在这里插入图片描述

3. 规则中的模式替换

在这里插入图片描述

  1. %.o 在 OBJS 中匹配子目标,首先找到 func.o
  2. 再根据 func.o 找个子目标生成依赖 func.c,构成整个规则 func.o: func.c
  3. 继续 1 和 2,匹配其它子目标
.PHONY : clean rebuild all

target := hello.out
CC := gcc

obj : main.o func.o

#使用模式规则替换,避免每一条.c都要写一个编译命令
$(obj) : %o : %c
	$(CC) -o $@ -c $^

$(target) : main.o func.o
	$(CC) -o $@ $^

all : $(target)

rebuild : clean all

clean : 
	rm -f *.o $(target)

在这里插入图片描述

4. 变量值的嵌套使用

  • 一个变量名之中可以包含对其它变量的引用
  • 嵌套引用的本质是使用一个变量表示另外一个变量

在这里插入图片描述

x := y
y := z
val := $($(x))

all:
	@echo "val => $(val)"

在这里插入图片描述

5. 命令行变量

  • 运行 make 时,在命令行定义变量
  • 命令行变量默认覆盖 makefile 中定义的变量
hm := hello makefile

test:
	@echo "hm => $(hm)"

在这里插入图片描述

  • override 关键字
    • 使用 override 关键字可以防止 makefile 中定义的变量被命令行变量覆盖
    • override 用于指示 makefile 中定义的变量不能被覆盖
    • 变量的定义和赋值都需要使用 override 关键字
      在这里插入图片描述
  • define 关键字
    • 用于在 makefile 中定义多行变量
    • 多行变量的定义从变量名开始到 endef 结束
    • 可使用 override 关键字防止变量被覆盖
    • define 定义的变量等价于使用 = 定义的变量
define fool
I'm fool!
endef

override define cmd
	@echo "run cmd here"
endef

test:
	@echo "fool => $(fool)"
	$(cmd)

在这里插入图片描述

6. 环境变量

  • makefile 中能够直接使用环境变量的值
    • makefile 中定义与环境变量同名的变量,环境变量会被覆盖
    • 运行 make 时指定 -e 选项,优先使用环境变量
  • 变量在不同 makefile 之间的传递
    • 直接在外部定义环境变量进行传递(不推荐,因为依赖于系统,导致 makefile 的移植性问题)
    • 使用 export 定义变量进行传递(定义临时环境变量)
    • 定义 make 命令行变量进行传递(推荐做法)
HOME := new_home

test:
	@echo "$(HOME)"

由 make 结果可知,系统中的环境变量 HOME 的内容 /home/wx,在 makefile 中被改为了 new_home

在这里插入图片描述

# Makefile

HOME := new_home
var := uuxiang

test:
	@echo "HOME => $(HOME)"
	@echo "var => $(var)"
	@echo "make Makefile.2"
	@$(MAKE) -f Makefile.2

# Makefile.2

test:
	@echo "HOME => $(HOME)"
	@echo "var => $(var)"

make 时,HOME 被临时改写为了 new_home,因此,这个值被传递到 Makefile.2 中,而 var 的作用域只在 Makefile 中,取法传递到 Make file.2 中,因此,输出为空。
在这里插入图片描述

如果想要将 var 也传递到 Makefile.2 中,可以使用 export 关键字。

# Makefile

HOME := new_home
export var := uuxiang
new := hello

test:
	@echo "HOME => $(HOME)"
	@echo "var => $(var)"
	@echo "make Makefile.2"
	@$(MAKE) -f Makefile.2
	@$(MAKE) -f Makefile.2 new:=$(new)

# Makefile.2

test:
	@echo "HOME => $(HOME)"
	@echo "var => $(var)"
	@echo "new => $(new)"

export 关键字修饰 var 变量,使其成为临时环境变量,这样就可以传递到 Makefile.2 中了。

在这里插入图片描述

7. 目标变量(局部变量)

  • 作用域只在指定目标及连带规则中
var := hello

test: var := test-var

test: another
	@echo "test:"
	@echo "var => $(var)"

another:
	@echo "another:"
	@echo "var => $(var)"

test: var := test-var,即定义了目标变量 var,此时这个变量的值 test-var 的作用域在 test 目标及其连带规则中,而在其它地方,var 变量的值仍然为 hello,这个变量值的作用域为整个文件。

在这里插入图片描述

var := hello

test: var := test-var

test:
	@echo "test:"
	@echo "var => $(var)"

another:
	@echo "another:"
	@echo "var => $(var)"

在这里插入图片描述

8. 模式变量

  • 模式变量时目标变量的扩展
  • 作用域只在符合模式的目标及连带规则中
var := hello

test: var := test-var

new := uuxiang

%e: override new := test-new

test:
	@echo "test:"
	@echo "var => $(var)"
	@echo "new => $(new)"

rule:
	@echo "rule:"
	@echo "var => $(var)"
	@echo "new => $(new)"

rule 目标对应的规则符合 %e 模式,因此,rule 规则中的 new 输出为 test-new 为模式变量。

在这里插入图片描述

9. 工程

【06-07 变量的高级主题】