当前位置:首页 > 每日看点

Makefile怎么入门?

卡卷网2年前 (2025-01-11)每日看点301

<>Makefile</>是make工具的配置文件,主要用于定义如何构建和项目的编译过程。Makefile是C/C++编译项目中的重要工具,尤其在多文件、多模块的项目中,为了方便复杂项目的,可以通过自动化规则提高编译效率。

这篇文章是Makefile的入门教程的介绍,包括其基本语法、常用功能、以及实际使用中的高级技巧。

Makefile的基本概念

安装make:

//sudoapt-getupdate sudoapt-getinstallmake

核心功能

    自动化编译:根据文件的依赖关系自动决定哪些文件需要重新编译。提高效率:只编译发生变化的部分。多任务支持:可以定义清理、打包、等任务。

使用方法

运行make命令时,默认会读取当前目录下的<>Makefile文件</>。

make#执行默认的目标make<target>#执行指定的目标

例如:

makeclean#执行"clean"目标

Makefile的基本语法

1.目标语法

<>Makefile</>的基本语法如下:

//target:prerequisites commands

    <>target</>:目标文件或命令名称。例如可执行文件、目标文件或任务名称。<>prerequisites</>:依赖文件或目标。只有依赖文件发生变化时,target才会被重新生成。<>commands</>:生成目标的命令(必须以<>Ta</>开头)。

示例:

//hello:hello.o gcc-ohellohello.o hello.o:hello.c gcc-chello.c

在示例代码中:

1.如果hello.c被修改,则hello.o会重新生成。

2.如果hello.o被修改,则hello会重新生成。

2.变量定义

<>Makefile</>支持变量定义,用于简化配置和重复的命令。

示例1:

//CC=gccCFLAGS=-Wall-g#简单赋值CC:=$(XX)gcc当前有效//立马获取当前XX变量的值#递归赋值CC=$(XX)gcc //去递归寻找XX变量的最后一个值#条件赋值CC?=gcc //如果有CC变量,则该语句无效#追加赋值CC+=$(XX)gcc //在原来值的基础上,进行追加#使用:$(CC)获取变量的值

示例2:

//x:=jake y:=$(x)androse x:=tonly all: echo"x=$(x),y=$(y)"

<>使用变量</>(示例1)

//hello:hello.o $(CC)$(CFLAGS)-ohellohello.o

<>输出:</>(示例2)

//x=windx,y=jakeandrose

<>示例</>

//CC=gccCFLAGS=-Wall-O2 hello:hello.o $(CC)$(CFLAGS)-ohellohello.o hello.o:hello.c $(CC)$(CFLAGS)-chello.c

3.内置变量

Makefile提供了一些常用的内置变量,可以减少重复工作。

变量|功能

变量功能
$@当前目标的名称(target)。
$<第一个依赖文件的名称(prerequisite)。
$^所有依赖文件的名称。

<>代码片:</>

//CC=gccCFLAGS=-Wall-g hello:hello.o $(CC)$(CFLAGS)-o$@$^

在这里:

    $@是hello(目标)。$^是hello.o(所有依赖文件)。

4.通配符和自动化规则

Makefile支持通配符和模式匹配规则,用于简化多文件项目的编写。

<>通配符</>

    *.c:匹配所有.c文件。$(wildcard*.c):列出当前目录下所有.c文件。$(patsust%.c,%.o,$(wildcard*.c)):将所有.c文件替换为对应的.o文件。

<>自动化规则</>

使用模式规则可以自动生成目标文件:

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

    表示所有.o文件都可以由对应的.c文件生成。

<>代码:</>

//CC=gccCFLAGS=-Wall-O0-gSRC=$(wildcard*.c)OJ=$(patsust%.c,%.o,$(SRC))hello:$(OJ)$(CC)$(CFLAGS)-o$@$^ %.o:%.c $(CC)$(CFLAGS)-c$<-o$@

5.伪目标

伪目标(phonytargets)是指不生成实际文件的目标,通常用于清理、等任务。

伪目标也是一个目标,该目标不需要生成,每一次去执行该目标,都会执行。

<>定义伪目标:</>

.PHONY:clean#将当前目标设定为伪目标,每次执行该目标都会执行命令clean: rm-f*.ohello

    使用.PHONY声明可以避免冲突(例如当前目录下存在名为clean的文件时)。

6.自动推导规则

在使用make编译.c源文件时,可以省略编译一个.c文件所使用的命令。这是因为make存在一个默认的规则,能够自动完成对.c文件的编译并生成对应的.o文件。它执行命令“cc-c”来编译.c源文件。对于上边的例子,此默认规则就使用命令“cc-cmain.c-omain.o”来创建文件“main.o”。因此对一个目标文件是“N.o”,倚赖文件是“N.c”的规则。可以省略其规则的命令行,使用make的默认命令。此默认规则称为make的隐含规则(关于隐含规则看我上传至资源中的《GUNmake中文手册》第九章[使用隐含规则]一章,有详细说明。)

我们书写Makefile时,对于一个.c文件如果使用make的隐含规则,那么它会被自动作为对应.o文件的一个依赖文件(对应是指:文件名除后缀外,其余都相同的两个文件)。因此我们也可以在规则中省略目标的倚赖.c文件。

自动推导规则_1

自动推导规则_2

我们可以看见,当app文件被创建之后,再次执行make命令时,提示:make:'app'isuptodate.,此处是make的时间戳方式,如果目标生成的时间晚于依赖,该目标是最新的,那么该目标就不需要再编译重新生成。(如果想详细了解makefile的时间戳机制,可以点击查看这篇文章,对Makefile的时间戳机制有更详细的说明。<

笨猫猫的小茶馆:Makefile时间戳

>)

项目示例

这是一个多文件C项目的示例<>Makefile</>:

项目目录

//project/ ├──main.c ├──utils.c ├──utils.h ├──Makefile```#####Makefile```ash#编译器和编译参数CC=gccCFLAGS=-Wall-g#源文件和目标文件SRC=main.cutils.cOJ=$(SRC:.c=.o)TARGET=my_program#默认目标all:$(TARGET)#链接目标文件$(TARGET):$(OJ)$(CC)$(CFLAGS)-o$@$^#编译规则(自动化规则)%.o:%.c $(CC)$(CFLAGS)-c$<-o$@#清理目标.PHONY:clean clean: rm-f$(OJ)$(TARGET)

运行说明

1.构建项目

//make

2.清理项目:

//makeclean

这么写缺失中间的流程,接下来我结合图片将makefile项目的实际流程走一遍:

<>要求</>:(虽然是简易版用于教学的,但其中的过程和项目的思路,即使在大型项目中也是一致的,不同的只是划分的层级结构、架构更为复杂而已。)

1.创建项目目录

2.include/project.h的头文件

3.jack文件夹下的文件

4.将jack.c通过编译生成jack.o文件——>然后将jack.o放入oj文件夹下

5.此处的<>Makefile</>用于main.c文件,将main.c编译转化为main.o,将其保存在oj文件夹下一

6.main.o文件生成成功并放在了一文件夹oj下,接下来,将main.o和jack.o做链接作生成app文件,因此,我们需要在oj文件夹下创建<>Makefile</>文件,用于将所有在此处的.0文件链接生成可执行文件app

7.成功生成了可执行文件app

8.因为main:会自动寻址至依赖的第一个文件,结果将提示文件已存在。所以这里我们要将需要生成的文件main设为伪目标。

至此,前面的步骤我们共计完成了4步:

第一步,我们将jack文件夹下的jack.c生成了jack.o,将其放在oj文件夹下;

第二步,我们将main文件夹下的main.c生成了main.o,将其放在oj文件夹下;

第三步,在oj文件夹下,将这里所有着的.o文件最终生成了可执行文件app。

最后,我们在整个项目目录下,生成一个<>Makefile</>文件,用于整个项目,这样,最终我们只需要make一次,便能够得到整体项目的可执行文件,而不需要经过上述如此繁琐的步骤。

make-C文件夹/[目标]//去到该文件夹下去执行该文件夹下的Makefile的第一个目标[目标]

因为第一个目标已存在,所以此处我们需要提前设置mainclean为伪目标。

9.最终生成可执行文件app

10.优化Makefile代码。

11.添加共享变量,在最终的Makefile文件中添加共享变量,这样的话,可供同一级目录和该目录下的所有子目录中的Makefile文件皆可以共享到最上层的Makefile文件中的共享变量。

export共享变量//当前同一级目录下的子目录都可以共享该变量

12.这时候进入了一个新人,分配任务给rose,创建rose文件夹并加入这部分模块的代码,

至此,以上为Makefile项目在开发中的实际应用(简易版)。

高级功能

条件判断

根据条件设置变量或执行不同的规则。

//DEUG=1ifeq($(DEUG),1)CFLAGS+=-gelseCFLAGS+=-O2 endif

包含Makefile

使用include将多个Makefile文件整合在一起。

//includecommon.mk

    这种方式适合大型项目,将公共配置提取到单的文件中。

一些常见问题与技巧

如何调试Makefile?

运行make时加上-n或--dry-run参数,可以查看执行的命令而不正运行:

//make-n

如何提高编译效率?

使用make的并行编译选项-j,可以同时编译多个目标:

//make-j4

    其中4表示最多允许4个任务同时执行。

综上。这篇文章仅仅只介绍了makefile的简单用法,更多更详细的内容可以下载资源查看makefile手册(中文版),Makefile是一个强大的工具,适合用于从简单到复杂的编译流程。

本章主要介绍了:

    <>基础语法</>:理解目标、依赖和命令的结构。<>变量和内置变量</>:使用变量提高可读性和灵活性。<>自动化规则</>:使用通配符和模式规则减少重复代码。<>伪目标</>:定义清理、等任务。<>高级功能</>:条件判断、多文件组织、并行编译。

通过不断优化Makefile,可以显著提高项目的效率和可性,适合运用和大型项目。


扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2025/01/8694.html

分享给朋友:

相关文章

有哪些网站,一旦知道,你就离不开了?

有哪些网站,一旦知道,你就离不开了?

这六个网站,一旦用过,基本上是离不开了。都是我超爱的一些网站,基本上每天都用。 1 地图生成器 第一个,我要给大家推荐的是地图生成器。可以下载到各省,各市,各县的svg格式的地图素材。 这些素材导入PPT中都是可以编辑的。 可以单独更改颜色…

OLED、QLED还是Mini LED?如何在今年双十一选购一款最适合自己的电视?

OLED、QLED还是Mini LED?如何在今年双十一选购一款最适合自己的电视?

我家旧电视用了好几年了,最近毛病越来愈多,动不动就黑屏,让人特别扫兴。 这阵子和家人商量着,趁着现在国家有家电补贴,再加双11大促,不如换一台好一点的新电视,而现在MiniLED技术成熟,很多电视都升级MiniLED了,无论在画面亮度、细节…

曾经很火的迅雷,为什么现在不怎么火了?

曾经很火的迅雷,为什么现在不怎么火了?

3年前,迅雷推出了一项服务,只要2899元就可以享受迅雷终身会员。这个终身会员和付费会员没有区别,付费会员的离线加速、云空间等服务,终身会员都具备。除此之外,终身会员可以在使用1年后就可以全额退款,使用2年后也可以全额退款,使用5年后也是如…

如何建一个安全的个人nas?

如何建一个安全的个人nas?

群晖被入侵了晚上一进群晖,好家伙,这么多IP想用admin登录我的群晖。 我群晖是直接连在互联网上的,虽然我的密码是强密码,大小写字母加数字还有特殊字符,想要攻破有点儿难,但天天看着这些警告也是挺烦人的,而且说不定群晖里面安装的软件一多…

程序员为什么不能一次性写好,需要一直改Bug?

一个测试工程师走进酒吧,要了一杯啤酒。 一个测试工程师走进酒吧,要了亿杯啤酒。 一个测试工程师走进酒吧,要了0.32杯啤酒。 一个测试工程师走进酒吧,要了-1杯啤酒。 一个测试工程师走进酒吧,要了2^32杯啤酒。 一个测试工程师走进酒吧,要…

为什么百度搜索引擎越做越差?

说一个最近刚发生的, 昨天孩子学校要求打印《滕王阁序》全文带到学校去晨读,我想找一个带拼音和注释的版本,我在百度上足足找了半个小时,愣是没找到一个可以直接下载的文件,全部都要注册收费,有的文件下载居然要10块钱,我心想《滕王阁序》是王勃写的…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。