Makefile入门

参考教程:Makefile入门教程

Makefile概述

Makefile是一个工程文件的编译规则,一般用于Linux环境下工程的自动化编译,以代替手动编译(Win下IDE已经封装了各种makefile)

解决的问题:

  • 编译的时候需要链接库
    • make命令,自动编译工程,省略参数选项和命令
  • 编译大型工程需要很长时间
    • 无需全部重新编译,只编译修改的文件

Makefile规则

targets : prerequisites
    command
  • targets:目标文件,可以是中间文件/可执行文件/标签等
  • prerequisites:依赖文件,生成targets需要的源文件,多个/没有
  • command:make需要执行的命令,可以有多条,每条占一行

注意:targets与prerequisites用冒号分隔开,命令开始用Tab

test:test.c
    gcc -o test test.c

例子:使用 gcc -o test test.c 将test.c源文件编译为test可执行文件

  • 显式规则:生成文件、依赖文件、生成命令
  • 隐含规则:make命令的自动推到功能,可以简略书写makefile
  • 变量定义:定义字符串变量,类似C语言中的宏,变量被拓展到相应的应用中
  • 文件指示:makefile中应用另一个makefile;指定makefile的有效部分;定义多行命令
  • 注释:只有行注释,用 # 字符,与UNIX的Shell脚本规则相同

Makefile工作流程

默认情况下,make执行Makefile中的第一规则(Makefile中出现的第一个依赖关系),此规则的第一目标成为“最终目标”


具体工作顺序:

  • shell输入 make 命令
  • make读取Makefile中的第一个目标作为“终极目标” ,并开始处理第一个规则
  • 在执行第一个规则的命令之前,先处理其所有依赖文件的更新规则
  • 处理依赖文件的情况
    • 如果文件不存在,使用其规则创建它
    • 如果文件存在,且其依赖文件被修改,重新编译生成它
    • 如果文件存在,且其依赖文件未修改,则什么也不做
  • 依次处理后,最终返回第一规则,执行并生成“终极目标”

清除过程文件

.PHONY:clean
clean:
    rm -rf *.o finalfile

执行 make 指令时不会执行清除命令,在shell中执行 make clean 命令会清除中间文件和最终文件,方便下次使用

Makefile通配符

Makefile支持shell的通配符:
image.png
实例:

# 清除所有以.o结尾的文件
.PHONY:clean
clean:
    rm -rf *.o test

# 所有.c结尾的文件
test:*.c
    gcc -o $@ $^

# 注意不能用引用变量的方式来使用通配符,这里会变成文件“*.c”
OBJ=*.c
test:$(OBJ)
    gcc -o $@ $^
    
# 使用wildcard函数即可
OBJ=$(wildcard *.c)
test:$(OBJ)
    gcc -o $@ $^
    
# %也可匹配任意个字符
test:test.o test1.o
    gcc -o $@ $^
%.o:%.c
    gcc -o $@ $^

Makefile变量的定义和使用

Makefile变量定义: 变量的名称=值列表

  • 值列表可以是:零项/一项/多项
  • 不需要数据类型,直接使用即可
  • 变量名不区分大小写
OBJ=main.o test.o test1.o test2.o
test:$(OBJ)
      gcc -o test $(OBJ)

变量赋值

简单赋值

:= 只对当前语句的变量有效

x:=foo
y:=$(x)b
x:=new
test:
      @echo "y=>$(y)"
      @echo "x=>$(x)"
      
执行make test:
y=>foob
x=>new

递归赋值

= 可能影响多个变量,相关的其他变量都会改变

x=foo
y=$(x)b
x=new
test:
      @echo "y=>$(y)"
      @echo "x=>$(x)"
      
执行make test:
y=>newb
x=>new

条件赋值

?= 如果变量未定义,则使用符号中的值定义变量,如果变量已赋值,则语句无意义

x:=foo
y:=$(x)b
x?=new
test:
      @echo "y=>$(y)"
      @echo "x=>$(x)"

执行make test:
y=>foob
x=>foo

追加赋值

+= 原变量用空格隔开的方式追加一个新值

x:=foo
y:=$(x)b
x+=$(y)
test:
      @echo "y=>$(y)"
      @echo "x=>$(x)"
      
执行make test:
y=>foob
x=>foo foob

自动化变量

自动化变量说明
$@表示规则的目标文件名。如果目标是一个文档文件(Linux 中,一般成 .a 文件为文档文件,也成为静态的库文件),那么它代表这个文档的文件名。在多目标模式规则中,它代表的是触发规则被执行的文件名。
$%当目标文件是一个静态库文件时,代表静态库的一个成员名。
$<规则的第一个依赖的文件名。如果是一个目标文件使用隐含的规则来重建,则它代表由隐含规则加入的第一个依赖文件。
$?所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件)。
$^代表的是所有依赖文件列表,使用空格分隔。如果目标是静态库文件,它所代表的只能是所有的库成员(.o 文件)名。
一个文件可重复的出现在目标的依赖中,变量“ ” 只 记 录 它 的 第 一 次 引 用 的 情 况 。 就 是 说 变 量 “ ^”只记录它的第一次引用的情况。就是说变量“ ^”会去掉重复的依赖文件。
$+类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合。
$*在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时,
“茎”也包含目录部分)。

实例:

test:test.o test1.o test2.o
		gcc -o $@ $^				# “$^”代表的是依赖的文件
test.o:test.c test.h
		gcc -o $@ $<				# "$@" 代表的是目标文件
test1.o:test1.c test1.h
		gcc -o $@ $<				# “$<”代表的是依赖文件中的第一个
test2.o:test2.c test2.h
		gcc -o $@ $<
lib:test.o test1.o test2.o
		ar r $?							# "$?" 表示修改的文件。

Makefile目标文件搜索

为了解决源文件目录不在Makefile目录下的问题,需要目录搜索文件功能,主要方法有两种:

  • 一般搜索 VPATH
    • VPATH 是变量,更具体的说是环境变量,Makefile 中的一种特殊变量,使用时需要指定文件的路径
  • 选择搜索 vpath
    • vpath 是关键字,按照模式搜索,也可以说成是选择搜索。搜索的时候不仅需要加上文件的路径,还需要加上相应限制的条件。

VPATH

# 把 src 的值赋值给变量 VPATH,make时从src目录下寻找
VPATH := src

# 多个路径(按先后顺序)
VPATH := src car 或 VPATH := src:car

vpath

# PATTERN:可以理解为要寻找的条件,DIRECTORIES:寻找的路径
1) vpath PATTERN DIRECTORIES 
2) vpath PATTERN
3) vpath

# 在 src 路径下搜索文件 test.c
vpath test.c src

# 多路径写法
vpath test.c src car 或 vpath test.c src : car

# 清除符合文件 test.c 的搜索目录
vpath test.c

# 清除所有已被设置的文件搜索路径
vpath

Makefile隐含规则

隐含规则的具体的工作流程:

  • make 执行过程中找到的隐含规则,提供了此目标的基本依赖关系
  • 确定目标的依赖文件和重建目标需要使用的命令行。
  • 隐含规则所提供的依赖文件只是一个基本的(在C语言中,通常他们之间的对应关系是:test.o 对应的是 test.c 文件)
  • 当需要增加这个文件的依赖文件的时候要在 Makefile 中使用没有命令行的规则给出

隐含规则中使用的变量可以分成两类:

  • 代表一个程序的名字
    • 例如:“CC”代表了编译器的这个可执行程序。
  • 代表执行这个程序使用的参数
    • 例如:变量“CFLAGS”。多个参数之间使用空格隔开。

Makefile条件判断

条件语句的作用:条件语句可以根据一个变量的值来控制 make 执行或者时忽略 Makefile 的特定部分,条件语句可以是两个不同的变量或者是常量和变量之间的比较。
image.png

ifeq 和 ifneq

ifeq (ARG1, ARG2)
ifeq 'ARG1' 'ARG2'
ifeq "ARG1" "ARG2"
ifeq "ARG1" 'ARG2'
ifeq 'ARG1' "ARG2"

ifeq——else——endif 三连

ifdef 和 ifndef

ifdef VARIABLE-NAME

注意:“ifdef”只能判断变量是否赋值,不能判断变量的值是否为空,需要用“ifeq”来判断

Makefile常用字符串处理函数

函数调用方式

$(<function> <arguments>)
或
${<function> <arguments>}

详细介绍

  • 正则字符串替换函数
  • 字符串替换函数
  • 去空格函数
  • 查找字符串函数
  • 过滤函数、反过滤函数
  • 排序函数
  • 节选取词函数


其余的Makefile操作见参考文档:http://c.biancheng.net/makefile/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值