Linux工程管理文件Makefile变量类型详解-进阶篇

在1.立即变量和延迟变量

在Makefile中最容易让人引困惑的是立即变量和延迟变量。

立即变量和延迟变量是按展开时间来划分的。

立即变量使用 := 操作符进行赋值,在解析阶段就直接展开了,顾名思义,立即展开变量。

延迟变量则是使用 = 操作符进行赋值,在make解析Makefile阶段不会立即展开,而是等到实际使用这个变量时才展开,获得其真正的值。

a = 1
b = 2
val_a := $(a)
val_b  = $(b)
a = 10
b = 20
test:    
	echo $(val_a)    
	echo $(val_b)

在上面的例子中,val_a是立即变量,当make解析到:=赋值符号时,会把$(a)变量的值立即赋值给val_a,虽然后面a的值发生了变化,但val_a因为已经展开,所以值就不再发生变化。而val_b则不同,因为是延迟展开变量,所以,当make解析到 = 符号时,并没有立即把$(b)的值赋值给val_b,而是在运行echo命令时才对其展开,因为此时b的值已经是20,所以$(val_b)的值也是20

wit@pc:/home/makefile/# makeecho 11echo 2020

立即展开变量一般用在规则中的目标、目标依赖中。make在解析Makefile阶段,需要这些变量有确切的值来构建依赖关系树。

一个项目中的文件依赖关系在程序编译期间是固定不变的,因此需要立即变量在解析阶段就要有明确的值,立即展开。

延迟展开变量一般用在规则的命令行中,这些变量在make编译过程中被引用到才会展开,获得其实际的值。

2.自动变量

在makefile中,大家经常会见到类似$@、$^、$<这种类型的变量。这种变量一般称为自动变量,自动变量是局部变量,作用域范围在当前的规则内,它们分别代表不同的含义:

  • $@:目标
  • $^:所有目标依赖
  • $<:目标依赖列表中的第一个依赖
  • $?:所有目标依赖中被修改过的文件

有了这些自动变量,我们就可以改进下面的Makefile:

.PHONY: clean
CC  = gcc
BIN = a.out
OBJS = hello.o
OBJS += module.o
$(BIN): $(OBJS)    

@echo "start compiling..."    
@echo $(OBJS)    
	$(CC) -o $(BIN) $(OBJS)    
@echo "compile done"hello.o: hello.c    
	$(CC) -c -o hello.o hello.c
module.o: module.c    
	$(CC) -c -o module.o module.c
clean:    
rm -f $(BIN) $(OBJS)

将这个Makefile中命令行中的目标和目标依赖分别使用$@和$^代替,Makefile就变成了下面的样子:

.PHONY: clean
CC  = gcc
BIN = a.out
OBJS = hello.o module.o

$(BIN): $(OBJS)    
	@echo "start compiling..."    
	@echo $(OBJS)    
	$(CC) -o $@ $^    
	@echo "compile done"hello.o: hello.c    
	$(CC) -c -o $@ 
	$^module.o: module.c    
	$(CC) -c -o 
	$@ $^
clean:    
	rm -f $(BIN) $(OBJS)

除了上面几个常用的自动变量外,还有一些自动变量不太常用,但是大家在以后阅读Makefile时可能会遇到,比如:

  • $%:当规则的目标是一个静态库文件时,$%代表静态库的一个成员名
  • $+:类似$^,但是保留了依赖文件中重复出现的文件
  • $*:在模式匹配和静态模式规则中,代表目标模式中%的部分。比如hello.c,当匹配模式为%.c时,$*表示hello
  • $(@D):表示目标文件的目录部分
  • $(@F):表示目标文件的文件名部分
  • $(*D):在模式匹配中,表示目标模式中%的目录部分
  • $(*F):在模式匹配中,表示目标模式中%的文件名部分
  • : :告诉make在编译时忽略所有的错误
  • @: :告诉make在执行命令前不要显示命令

3.环境变量

除了用户自定义的一些变量,make在解析Makefile中还会引入一些系统环境变量,如编译参数CFLAGS、SHELL、MAKE等。这些变量在make开始运行时被载入到Makefile文件中,因为是全局性的系统环境变量,所以这些变量对所有的Makefile都有效。若Makefile中有用户自定义的同名变量,系统环境变量将会被用户自定义的变量覆盖。若用户在命令行中传递跟系统环境变量同名的变量,系统环境变量也会被传递的同名变量覆盖。

.PHONY:all
CFLAGS = -gall:    
@echo "CFLAGS = $(CFLAGS)"    
@echo "SHELL = $(SHELL)"   
@echo "MAKE = $(MAKE)"    
@echo "HOSTNAME = $(HOSTNAME)"

在上面的Makefile中,默认情况下,echo会打印各个系统变量的值:

wit@pc:/home/makefile/demo
# makeCFLAGS = -g
SHELL = /bin/sh
MAKE = make
HOSTNAME =

如果我们在执行make命令时,给Makefile传递一个同名的变量HOSTNAME=zixue.com,系统环境变量就会被这个同名变量覆盖,Makefile实际打印的值就变成了传递的同名变量的值:

wit@pc:/home/makefile/demo# make HOSTNAME=zixue.comCFLAGS = -gSHELL = /bin/shMAKE = makeHOSTNAME = zixue.com

 4.变量替换

4.1字符串替换

.PHONY: all
SRC := main.c sub.c
OBJ := $(SRC:.c=.o)all:    
@echo "SRC = $(SRC)"    
@echo "OBJ = $(OBJ)"

执行make命令,运行结果为:

# makeSRC = main.c sub.cOBJ = main.o sub.o

4.2模式匹配替换

使用匹配符%匹配变量,使用 % 保留变量值中的指定字符串,然后其他部分使用指定字符串代替。

.PHONY: all
SRC := main.c sub.c
OBJ := $(SRC:%.c=%.o)all:    
@echo "SRC = $(SRC)"    
@echo "OBJ = $(OBJ)"

执行make命令,运行结果为:

# makeSRC = main.c sub.cOBJ = main.o sub.o

  • 15
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值