一文读懂Makefile

目录

一 、Makefile是什么

1.对Makefile的理解

2.Makefile的优点和使用

二 、Makefile 文件命名和规则

1.文件命名

2.Makefile 文件内容的书写规则

3.示例

三 、Makefile 工作原理

1.命令在执行之前,需要先检查规则中的依赖是否存在。

2.检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间。

四 、使用变量简化Makefile写法

1.自定义变量

2.预定义变量 

3.获取变量的值

4.示例

五、Makefile的模式匹配

1.模式匹配规则

六、函数

1.$(wildcard PATTERN...)

(1)功能:

(2)参数

(3)返回

(4)示例

2.$(patsubst ,,)

(1)功能:

(2)参数

(3)返回

(4)示例

3.使用clean删除多余的.o文件


一 、Makefile是什么

1.对Makefile的理解

        如图所示,一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中, Makefile 文件定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为 Makefile 文件就像一个 Shell 脚本一样,也可以执行操作系统的命令。

 

2.Makefile的优点和使用

        Makefile 带来的好处就是自动化编译,一旦写好,只需要一个 make 命令,整 个工程完全自动编译,极大的提高了软件开发的效率。make 是一个命令工具,是一个 解释 Makefile 文件中指令的命令工具,一般来说,大多数的 IDE 都有这个命令, 比如 Delphi 的 make,Visual C++ 的 nmake,Linux 下 GNU 的 make。

二 、Makefile 文件命名和规则

1.文件命名

makefile或者Makefile

2.Makefile 文件内容的书写规则

一个 Makefile 文件中可以有一个或者多个规则,此外,Makefile 中的其它规则一般都是为第一条规则服务的。
        

        目标 ...: 依赖 ...

                命令(Shell 命令)

                ... 

目标:最终要生成的文件,伪目标除外。

依赖:生成目标所需要的文件或是目标。

命令:通过执行命令对依赖操作生成目标,命令前必须 Tab 缩进。

3.示例

两种书写方法,可以分开写,也可以写在一起。

test:a.c b.c d.c e.c main.c
    gcc a.c b.c d.c e.c main.c -o test
test:a.o b.o d.o e.o main.o
    gcc a.o b.o d.o e.o main.o -o test

a.o:a.c 
    gcc -c a.c -o a.o

b.o:b.c 
    gcc -c b.c -o b.o

d.o:d.c
    gcc -c d.c -o d.o

e.o:e.c 
    gcc -c e.c -o e.o

main.o:main.c
    gcc -c main.c -o main.o

三 、Makefile 工作原理

1.命令在执行之前,需要先检查规则中的依赖是否存在。

(1)如果存在,执行命令。

(2)如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的,如果找到了,则执行该规则中的命令。

2.检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间。

(1)如果依赖的时间比目标的时间晚,需要重新生成目标。

(2)如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行。

test:a.o b.o d.o e.o main.o
    gcc a.o b.o d.o e.o main.o -o test

a.o:a.c 
    gcc -c a.c -o a.o   //如果对a.c文件进行了修改,检测到依赖更新时间晚则该命令会重新执行。

b.o:b.c 
    gcc -c b.c -o b.o

d.o:d.c
    gcc -c d.c -o d.o

e.o:e.c 
    gcc -c e.c -o e.o

main.o:main.c
    gcc -c main.c -o main.o

四 、使用变量简化Makefile写法

1.自定义变量

变量名=变量值 var=hello

2.预定义变量 

AR : 归档维护程序的名称,默认值为 ar

CC : C 编译器的名称,默认值为 cc

CXX : C++ 编译器的名称,默认值为 g++

$@ : 目标的完整名称

$< : 第一个依赖文件的名称

$^ : 所有的依赖文件

3.获取变量的值

$(变量名)

$(var)

4.示例

//定义变量简化makefile的写法
//test:a.o b.o d.o e.o main.o
//   gcc a.o b.o d.o e.o main.o -o test

src=a.o b.o d.o e.o main.o
target=test
$(target):$(src)
         $(CC) $(src -o $(target)  //变量用法

a.o:a.c 
    gcc -c a.c -o a.o   

b.o:b.c 
    gcc -c b.c -o b.o

d.o:d.c
    gcc -c d.c -o d.o

e.o:e.c 
    gcc -c e.c -o e.o

main.o:main.c
    gcc -c main.c -o main.o

五、Makefile的模式匹配

1.模式匹配规则

        使用变量简化makefile的写法貌似也没有很简单的很明显,下面使用模式匹配继续写。

%.o:%.c

         -%: 通配符,匹配一个字符串

         - 两个%匹配的是同一个字符串

%.o:%.c

        gcc -c $< -o $@

//使用模式匹配进行makefile书写简化

//test:a.o b.o d.o e.o main.o
//   gcc a.o b.o d.o e.o main.o -o test //原始写法

src=a.o b.o d.o e.o main.o
target=test
$(target):$(src)
         $(CC) $(src) -o $(target)  //变量用法

%.o:%.c
        $(CC) -c $< -o $@   //模式匹配用法

//a.o:a.c 
//  gcc -c a.c -o a.o   

//b.o:b.c 
//    gcc -c b.c -o b.o

//d.o:d.c
 //   gcc -c d.c -o d.o

//e.o:e.c 
 //   gcc -c e.c -o e.o

//main.o:main.c
  //  gcc -c main.c -o main.o

六、函数

1.$(wildcard PATTERN...)

(1)功能:

        获取指定目录下指定类型的文件列表。

(2)参数

        PATTERN 指的是某个或多个目录下的对应的某种类型的文件,如果有多个目录,一般使用空格间隔。

(3)返回

        得到的若干个文件的文件列表,文件名之间使用空格间隔。

(4)示例

        $(wildcard *.c ./sub/*.c) 返回值格式: a.c b.c c.c d.c e.c f.c

//函数用法1

//src=a.o b.o d.o e.o main.o

src=$(wildcard ./*.c)
target=test
$(target):$(src)
         $(CC) $(src) -o $(target)  

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

2.$(patsubst <pattern>,<replacement>,<text>)

(1)功能:

        查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。

(2)参数

        <pattern>可以包括通配符`%`,表示任意长度的字串。如果<replacement>中也包含`%`,那么,<replacement>中的这个'%`将是中的那个'% '所代表的字串。(可以用`\`来转义,以`\%`来表示真实含义的`%`字符)。

(3)返回

        函数返回被替换过后的字符串。

(4)示例

        $(patsubst %.c, %.o, x.c bar.c)

        返回值格式: x.o bar.o

//函数用法2

//src=a.o b.o d.o e.o main.o

src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src)) //函数应用
target=test
$(target):$(objs)
         $(CC) $(objs) -o $(target)  

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

3.使用clean删除多余的.o文件

//clean掉多余.o文件

//src=a.o b.o d.o e.o main.o

src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src)) 
target=test
$(target):$(objs)
         $(CC) $(objs) -o $(target)  

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

.PHONY:clean   //变为伪目标文件 防止出现依赖检查更新 从而无法运行clean
clean
        rm $(objs) -f  

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值