12-Makefile_03(续)

使用变量

使用C自动编译成*.o的默认规则有个缺陷,由于没有显式地表示*.o依赖于.h头文件,假如修改了头文件的内容,那么*.o并不会更新,这是不可接受的。并且默认规则使用固定的“cc”进行编译,假如想使用ARM-GCC进行交叉编译,那么系统默认的“cc”会导致编译错误。要解决这些问题并且让Makefile变得更加通用,需要引入变量和分支进行处理。

基本语法

Makefile中的变量类似C语言的宏定义,在引用变量的地方使用变量值进行替换。

定义变量的方法:

  • “=”:延时赋值,该变量只有在调用的时候,才会被赋值
  • “:=”:直接赋值,与延时赋值相反,使用直接赋值的话,变量的值定义时就已经确定了
  • “?=”:若变量的值为空,则进行赋值,通常用于设置默认值
  • “+=”:追加赋值,可以往变量后面增加新的内容

主要介绍前两种:

A = a
B = $(A)
C = $(A)
A += b
.PHONY:check
check:
	echo "A:"$(A)
	echo "B:"$(B)
	echo "C:"$(C)	

在这里插入图片描述
通过-f选项指定执行Makefile文件,可以看见只有C是a。这是因为B采用的延时赋值,只有当调用时,才会进行赋值。当调用B时,A的值已经被修改为a b,因此B的变量值也就等于a b。

改造默认规则

使用变量修改默认规则

CC = gcc
CFLAGS = -I .
DEPS = hello_func.h

hello_main:hello_main.o hello_func.o
	$(CC) hello_main.o hello_func.o -o hello_main
# %为通配符,让所有.o文件依赖于对应的.c文件
%.o:%.c $(DEPS)
	$(CC) $< -c -o $@ $(CFLAGS)
.PHONY:clean
clean:
	rm -f *.o hello_main

上面的Makefile文件使用$(CC)替代了gcc,这样编写的Makefile非常容易更换不同的编译器,如要进行交叉编译,只要把开头的编译器名字修改掉即可

“%”是一个通配符,功能类似“*”,如”%.o”表示所有以”.o”结尾的文件。所以”%.o:%.c”在本例子中等价于”hello_main.o:hello_main.c”、“hello_func.o:hello_func.c”,即等价于o文件依赖于c文件的默认规则。不过这行代码后面的“$(DEPS)”表示它除了依赖c文件,还依赖于变量“$(DEPS)”表示的头文件,所以当头文件修改的话,o文件也会被重新编译。

特殊的变量”$@”,”$<”,可理解为Makefile文件保留的关键字,是系统保留的自动化变量,”$@”代表了目标文件,”$<”代表了第一个依赖文件。即”$@”表示”%.o”,”$<”表示”%.c”。

$(CC) $< -c -o $@ $(CFLAGS)
# 等价于:
gcc hello_main.c -c -o hello_main.o -I .
gcc hello_func.c -c -o hello_func.o -I .
改造链接规则

继续使用变量来修改生成最终目标文件的链接规则:

# 定义变量
TARGET = hello_main
CC = gcc
CFLAGS = -I .
DEPS = hello_func.h
OBJS = hello_main.o hello_func.o

# 目标文件
$(TARGET):$(OBJS)
	$(CC) $^ -o $@ $(CFLAGS)

# *.o文件的生成规则
%.o:%.c $(DEPS)
	$(CC) $< -c -o $@ $(CFLAGS)

# 伪目标
.PHONY:clean
clean:
	rm -f *.o hello_main
其他自动化变量
符号 含义
$@ 匹配目标文件
$% 与 $@ 类似,但 $% 仅匹配“库”类型的目标文件
$< 依赖中的第一个目标文件
$^ 所有的依赖目标,如果依赖中有重复的,只保留一份
$+ 所有的依赖目标,即使依赖中有重复的也原样保留
$? 所有比目标要新的依赖目标
使用分支
ifeq(arg1,arg2)
分支1
else
分支2
endif

分支会比较括号内的参数“arg1”和“arg2”的值是否相同,如果相同,则为真,执行分支 1 的内容,否则的话,执行分支 2 的内容,参数 arg1 和 arg2 可以是变量或者是常量。

使用分支切换GCC编译器的Makefile如下:

ARCH ?= x86
TARGET = hello_main
CFLAGS = -I .
DEPS = hello_func.h
OBJS = hello_main.o hello_func.o

# 根据输入的ARCH变量来选择编译器
ifeq ($(ARCH),x86)
CC = gcc
else
CC = arm-linux-gnueabihf-gcc
endif

$(TARGET):$(OBJS)
	$(CC) $^ -o $@ $(CFLAGS)

%.o:%.c $(DEPS)
	$(CC) $< -c -o $@ $(CFLAGS)

.PHONY:clean
clean:
	rm -f *.o hello_main

Makefile 主要是增加了 ARCH 变量用于选择目标平台,代码中使用“?=”给 ARCH 赋予默认值 x86。
在这里插入图片描述
以上示例使用交叉编译进行编译。

相关推荐

  1. lesson03:类和对象(中)

    2024-04-23 23:40:04       37 阅读
  2. <span style='color:red;'>Makefile</span>

    Makefile

    2024-04-23 23:40:04      53 阅读
  3. 计算机笔记13(20个)

    2024-04-23 23:40:04       31 阅读
  4. 计算机笔记14(20个)

    2024-04-23 23:40:04       31 阅读
  5. <span style='color:red;'>12</span>.<span style='color:red;'>07</span>

    12.07

    2024-04-23 23:40:04      52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-23 23:40:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-23 23:40:04       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-23 23:40:04       82 阅读
  4. Python语言-面向对象

    2024-04-23 23:40:04       91 阅读

热门阅读

  1. AcWing 802. 区间和——算法基础课题解

    2024-04-23 23:40:04       38 阅读
  2. html实现点击按钮时下方展开一句话

    2024-04-23 23:40:04       31 阅读
  3. C++11中的智能指针

    2024-04-23 23:40:04       25 阅读
  4. Python小程序 - 文件类型统计

    2024-04-23 23:40:04       35 阅读
  5. python如何实现流式接收数据

    2024-04-23 23:40:04       28 阅读
  6. jpa 和 mybatis 的优缺点

    2024-04-23 23:40:04       24 阅读
  7. 继续学习排序

    2024-04-23 23:40:04       31 阅读
  8. Ubuntu或Debian系统的漏洞修复:apt安装包管理工具

    2024-04-23 23:40:04       33 阅读
  9. 【verilog 设计】 reg有没有必要全部赋初值?

    2024-04-23 23:40:04       37 阅读
  10. leensa111邀请码!

    2024-04-23 23:40:04       33 阅读