Linux Makefile及其规则介绍

本文详细介绍了Makefile的基础概念、工作原理以及优化方法,并通过实例展示了如何利用Makefile进行项目编译管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Makefile在绝大多数的IDE中都在使用,已经成为一种工程的编译方法。

Makefile:项目的代码管理工具,用于管理工程编译。通过把所有源代码的编译命令写入makefile来达到多文件统一编译。

一、初识Makefile

1、在公司中,架构师负责把各模块集中起来做成makefile提供给公司内部人员使用。

2、Makefile实质:写好的makefile其实就是一个文件,内部写好了各个分模块的编译规则。

3、Makefile文件两种命名规则:全小写(makefile) 或者  首字母大写(Makefile);

4、Makefile写法规则中的三要素:目标、依赖、命令;

//格式:
//目标:依赖条件
//[tab]命令
//举例如下:
app:main.c add.c sub.c mul.c
    gcc main.c add.c sub.c mul.c -o app

5、Make是一个命令工具,它用于解释Makefile中的指令(具体说是规则);在Makefile文件中描述了整个工程的所有文件的编译顺序、编译规则。

注:一般把  .c  和  makefile 放在同一目录下。

6、Makefile优化

上方所写makefile依赖项是 .c  文件,当其中一个 .c 文件发生变化时,其余的 .c 文件也需要跟着它重新编译,显然效率不高,为了提高效率,让单个文件发生变化后,仅编译发生变化的 .c 文件,需要将各个模块分开编译,此时依赖项需要编程 .o 文件

app:main.o add.o sub.o mul.o
    gcc main.o add.o sub.o mul.o -o app
main.o:main.c
    gcc -c main.c
add.o:add.c
    gcc -c add.c
sub.o:sub.c
    gcc -c sub.c
mul.o:mul.c
    gcc -c mul.c

各模块分开编译好处:避免了一个 .c 修改后,所有的 .c 都需要跟着重新编译的缺陷,提高了程序编译的效率。

此时,先执行终极目标app,查找终极目标的依赖项,若某项没有则执行下方的子目标以生成该项依赖,最后集齐所有终极目标的依赖项后,执行终极目标下方的命令已完成最终编译。

二、Makefile工作原理剖析

1、Makefile工作原理叙述:先执行终极目标app,查找终极目标的依赖项,若某项没有则执行下方的子目标以生成该项依赖,最后集齐所有终极目标的依赖项后,执行终极目标下方的命令已完成最终编译。

2、Makefile:目标生成原理

Makefile目标生成规则:首先检查以来的条件是否存在,存在通过命令直接生成对应的目标,若不存在,向下寻找对应的子目标,根据其规则生成依赖条件,最终集齐各依赖项后执行下方命令生成对应的目标。流程详见下图:

3、Makefile:目标更新机制

每次生成目标前,检查目标和依赖项之间是否一致,若依赖项修改了,则重新编译此项目;

三、Makefile变量介绍及使用

Makefile中也支持变量的使用,但弱化了变量的类型,即随定义随时用;同时Makefile也维护了一批内置变量和自动变量(只能在规则中的命令中使用)

Makefile常用的三个自动变量:
1、$< : 代表规则中的第一个依赖
2、$@ : 代表规则中的目标
3、$^ : 代表规则中所有的变量
注:自动变量只能在规则中的命令中使用

Makefile的模式规则:
% : 此处代表所有的项,谁符合条件件是谁的值(类似于shell中的 *)

Makefile中自己维护的变量:
CC=cc (小写cc代表gcc)
注:用户也可以修改内置变量的默认值

Makefile用户自定义变量:
如:obj=main.o add.o sub.o mul.o
注:使用时需要加 $ 表示提取变量内容 如:gcc $(obj) -o app

四、使用Makefile变量再优化上面的Makefile

 obj=main.o add.o sub.o mul.o
 target=app
 $(target):$(obj)
     gcc $(obj) -o $(target)

 %.o:%.c
     gcc -c $< -o $@

五、Makefile常用函数及Makefile继续优化

1、Makefile函数:任意Makefile中的函数均有返回值

2、Makefile常用函数

注:Makefile函数的参数不需要写在括号内,直接在函数名后加空格间隔,紧接着写参数

wildcard函数:显示指定路径下指定文件类型的所有文件
使用:src=$(wildcard ./*.c)
解释:从当前路径下查找所以有以 .c 结尾的文件名作为参数回传给src变量

patsubst函数:模式字符串替换函数
使用:obj=$(patsubst ./%.c,./%.o,$(src))
解释:把src中以 .c 结尾的值变为以 .o 结束

3、Makefile伪目标的声明及定义

伪函数声明语句
.PHONY:clean

定义语句:
clean:
    rm -f $(obj)

注:把clean声明成伪目标的好处:每个Makefile执行后,每个目标都会生成对应的文件,此处clean目标无依赖项,所以不需要做改变项的检查,因此声明成伪目标,每次都执行它

4、Makefile继续优化

target=app

src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
CC=gcc

$(target):$(obj)
    $(CC) $(obj) -o $(target)

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

.PHONY:clean  //把clean声明成伪目标
clean:
    rm -f $(obj)  //-f选项:强制执行

此次Makefile的编写加入了Makefile函数的使用,同时加入了新的目标clean,它用于在执行makefile的同时删除生成的用于过渡的 .o 文件;

此时执行makefile时,需要做到:

make && make clean

注:这里显示生成了 clean 目标,因为clean目标没有依赖项,但需求是生成clean目标,所以需要显示指定生成 clean 目标

5、Makefile语句细节优化案列

“-” :在命令前加“-”号,忽略不可执行的命令,不中断Makefile执行

如:简单写一个目标
1、clean:
       mkdir /aaa
       rm -f $(obj)

此时,执行到mkdir命令行会终止后续项的执行,因为普通用户权限不足;这样就会影响Makefile整体的容错能力

2、clean:
       -mkdir /aaa
       rm -f $(obj)
此时,执行到mkdir命令行是不会终止,makefile只是忽略它无权限或不能执行的命令,继续执行后续项

详细易懂的Linux makefile教程 一、概述 什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。 因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。 makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCCCC。 二、关于程序的编译和链接 —————————— 在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。 ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star星屹程序设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值