初识Linux —— make和makefile主动化构建工具

[复制链接]
发表于 2025-11-23 17:52:54 | 显示全部楼层 |阅读模式
什么是make/makefile

本篇文章对于图片即内容详解,已同步到博主gitee:根本工具利用/make和makefile.png - 积极学习的小廉
   在之前写代码的过程中,我们都是对一个文件举行编译链接(gcc编译),但是如果一个项目中,源代码文件非常的多,我们总不能一个一个的举行编译链接,这也太贫苦了;以是现在就来学习make/makefile实现主动化构建
  make是一个下令工具,是一个表明makefile在指令的下令工具,大多数的IDE都存在这个下令。
makefile成为一种在工程方面的编译方法。
   

  • makefile是一个文件,make是一个下令;二者搭配利用来完成项目的主动化构建
  • makefile的长处就是主动化构建,写好makefile文件以后就只需make下令就可以完成项目工程的主动化构建,提点高了软件开辟的服从
  实在会不会写makefile文件,也侧面反映了其是否具备完成大型工程的本领
在一个工程中源代码文件,按照范例、功能、模块分别放到了多少个目次下,makefile界说一系列的规则来指定哪些文件须要先编译、哪些文件须要后编译,哪些文件须要重新编译,乃至举行更加复杂的利用。
makefile根本利用

起首先来看一个makefile怎样利用(以及怎样编写)
现在有一个已经写好的makefile文件(这里简单利用一下)

我们在当前目次下编写一个code.c文件,而且写上一个简单的代码

现在就来利用make下令

我们看到,利用make下令就主动编译code.c文件形成code可实行步调了。
现在就来看一下makefile中内容有和寄义呢?
  1. code:code.c
  2.         gcc code.c -o code
  3. .PHONY:clean
  4. clean:
  5.         rm -f code
复制代码
1. 依靠关系和依靠方法


对于上述makefile文件,在先容之前我们先来想要个题目,就是依靠关系和依靠方法
   

  • 依靠关系:所谓依靠关系就表明两个事物(这里指目的文件和依靠文件)之间关系(就像实际生存中两个人之间的关系一样)
  • 依靠方法:有了依靠关系,那应该做什么呢?,依靠方法就表明(这里表现要怎样天生目的文件);(就像实际生存中,你须要向朋侪寻求资助,有了你们是朋侪这一关系,接下来就要表明你要做什么了)
  相识了依靠关系和依靠方法,接下来看目的文件和依靠文件
   ​ 目的文件和依靠文件,实在就是两个有着依靠关系的文件(依靠文件可以有多个),如上图就表现code依靠code.c文件
  而依靠关系就表明白,怎样由依靠文件列表天生目的文件。
  如许我们就很好明白了,上述makefile文件中,code作为目的文件、code.c作为依靠文件、通过依靠关系gcc code.c -o code来天生目的文件。
2. 伪目的.PHONY

对于上述makefile,我们连续实行多次make就会发现,不能实行
但是我们如果连续指向多次make clean,它并没有堕落

到这里一个大概想到是.PHONY的作用了;那这到底是什么呢?又为什么被称为伪目的呢?
   伪目的:.PHONY修饰,伪目的它总是被实行的;像clean这种的目的文件,一样平常都设置成伪目的
  

对于这个,可以表明为:
   伪目的clean不依靠于任何文件,实行make clean天生clean目的文件就会实行依靠方法rm -f code;但是依靠方法并没有天生clean文件,而是删除code文件,做清算工作。
  这里固然说clean是一个目的文件,但在依靠方法中并没有天生clean文件。(大概是由于没有天生clean目的文件,才称为伪目的)
3. ACM时间

对于上述的伪目的可以或许不绝被实行,而其他就不可以或许连续实行;又是怎样实现的呢?
先来相识什么是ACM时间
   

  • Access :文件迩来访问的时间
  • Modify :文件内容迩来修改的时间
  • Change :文件属性迩来修改的时间
  那我们如果想要看一个文件的ACM时间,就要用到新的指令stat了。

那又是根据哪个时间来判定是否实行呢? 答案是Modify文件内容修改时间

   我们可以看到上图中目的文件的Modify时间是晚于依靠文件的,以是就不能为实行。
  细致观察可以看出来,上图Change时间目的文件也晚于依靠文件啊,如许不能分析比力的是Modify时间啊
现在接着来看

我们可以看到,依靠文件code.c的Change时间晚于目的文件code的Change时间照旧不可以或许实行;
那现在我们就可以或许得出结论,只有当依靠文件的Modify时间晚于目的文件的Modify时间时(在编译事后,依靠文件内容有所修改),才气够被实行。
这里.PHONY之以是能不绝被实行,其缘故因由就是它忽视了对比时间。
4. 推导过程

在上述过程中,我们写的依靠文件都是在当前目次中直接存在的;拿如果依靠文件并没有直接存在,而是依靠于其他依靠文件呢?
这里就根据编译过程,天生编译过程中全部的暂时文件,来写makefile
  1. code:code.o
  2.         gcc code.o -o code
  3. code.o:code.s
  4.         gcc -c code.s -o code.o
  5. code.s:code.i
  6.         gcc -S code.i -o code.s
  7. code.i:code.c
  8.         gcc -E code.c -o code.i
  9. .PHONY:clean
  10. clean:
  11.         rm -f *.i *.s *.o code
复制代码
如上述,code依靠于code.o、code.o依靠于code.s、code.s依靠于code.i、code.i依靠于code.c。这些除了code.c以为的文件都没有直接存在于当前目次下。

如许依然可以运行,而且都天生了这些文件;这足以分析应该存在可以推导的过程。

扩展语法——更加通用的makefile

   上面所形貌的makefile它只能实用于一个文件,拿对于多个文件也是无济于事(还要重新写makefile)
  这就一点太贫苦了,现在就来学习更多makefile语法,让makefile变得更加实用。
  1. 创建变量

   在makefile中也可以创建变量,和C语言中指针那样
  1. BIN=code
  2. SRC=cpde.c
  3. OBJ=code.o
  4. CC=gcc
  5. RM=rm -f
  6. $(BIN):$(OBJ)
  7.         gcc $(OBJ) -o $(BIN)
  8. $(OBJ):$(SRC)
  9.         gcc -c $(SRC) -o $(OBJ)
  10. .PHONY:clean
  11. clean:
  12.         $(RM) $(OBJ) $(BIN)
复制代码
上述中比方BIN=code、SRC=code.c
如许的就是创建了变量,(它们就像`C语言中的指针);
在须要访问这些变量的值的时间须要用到$()(就比如$(BIN)访问BIN变量的值)

这里尚有优化一下,利用$^和$@
   $^:在依靠方法中利用,指依靠关系中的依靠文件
  $@:在依靠方法中利用,指依靠关系在的目的文件
  全部就可以如许来写:
  1. BIN=code
  2. SRC=cpde.c
  3. OBJ=code.o
  4. CC=gcc
  5. RM=rm -f
  6. $(BIN):$(OBJ)
  7.         gcc $^ -o $@
  8. $(OBJ):$(SRC)
  9.         gcc -c $^ -o $@
  10. .PHONY:clean
  11. clean:
  12.         $(RM) $(OBJ) $(BIN)
复制代码
2. 编译当前目次下的多个文件

   说了这么多,这照旧只能编译一个文件,现在就来看怎样编译当前目次下的多个文件
  要想编译多个文件,那我们就不能给变量如许赋值了
  1. SRC=code.c
复制代码
如许就写死了,只能利用一个文件;现在我们须要的是,辨认到当前目次下以是的.c文件
获取当前目次下全部的.c文件

方法有两种:
   

  • $(shell ls *.c) :在makefile中实行shell下令,获取当前目次全部的.c文件。
  • $(wildcard *.c) :利用wildcard函数,获取全部的.c文件。
  将全部的.c修改成.o

这里,我们并不是直接天生code可实行步调的,而是天生对应的.o文件,再链接形成的可实行步调;以是我们就须要获取全部.c文件对于的.o文件名;(利用makefile语法即可)
  1. OBJ=$(SRC:.c=.o)
复制代码
这个语法就是将SRC(获取当前目次下全部.c文件)中的.c更换成.o;如许我们就获取到了全部.c文件对应的.o文件名。
通配符%和逐个实行$<

上面经常写到*.c,它就表现全部以.c末端的文件;那在写makefile的利用,偶然候也要用到通配符,但是我们没有利用*,而是利用%。
我们想要让它编译多个文件就不能像之前那样写了,(由于这里我们要天生全部.c文件对应的.o文件。
   如许我们在写由.c天生.o文件时,就能直接利用通配符%,如许就可以主动匹配
  在匹配竣事之后,目的文件依靠多个文件;就不能利用$^直接取依靠文件列表了,而是利用%<将依靠文件列表中多个文件一个一个实行。
到这里,我们就能根本完成编译当前目次下全部.c文件的makefile了。
  1. BIN= codeSRC=$(shell ls *.c)OBJ=$(SRC:.c=.o)
  2. CC=gccRM=rm -f$(BIN):$(OBJ)        gcc $^ -o $@$(OBJ):$(SRC)        gcc -c $^ -o $@.PHONY:cleanclean:        $(RM) $(OBJ) $(BIN)
复制代码
3. 测试和优化makefile

对于上述的makefile,我们举行一些优化
  1. BIN= codeSRC=$(shell ls *.c)OBJ=$(SRC:.c=.o)
  2. CC=gccRM=rm -fCOM=-cLINK=-o$(BIN):$(OBJ)        $(CC) $^ $(LINK) $@%.o:%.c        $(CC) $(COM) $<.PHONY:cleanclean:        $(RM) $(OBJ) $(BIN)
复制代码
  这里优化,新增了COM编译选项、LINK链接选项;而且都利用变量,更将通用。
  在举行测试之前,我们要先让当前目次有多个文件,这里先容应该语法
  1. touch code{1..20}.c
复制代码
  该指令作用是创建code1.c、code2.c、code3.c......code20.c(20个文件)。
  现在该目次下新建了20个文件,运行一试

可以看到,它会表现出来编译的过程,如果不想要看到可以在语句前加上@。
  1. BIN= codeSRC=$(shell ls *.c)OBJ=$(SRC:.c=.o)
  2. CC=gccRM=rm -fCOM=-cLINK=-o$(BIN):$(OBJ)        @$(CC) $^ $(LINK) $@%.o:%.c        @$(CC) $(COM) $<.PHONY:cleanclean:        $(RM) $(OBJ) $(BIN)
复制代码

如许我们不知道它编译的进度了,我们就可以手动回显一些内容(在依靠关系中直接添加输出到表现器文件的语句即可)
  1. BIN= codeSRC=$(shell ls *.c)OBJ=$(SRC:.c=.o)
  2. CC=gccRM=rm -fCOM=-cLINK=-o$(BIN):$(OBJ)        @$(CC) $^ $(LINK) $@        @echo "link...$^"%.o:%.c        @$(CC) $(COM) $<        @echo "compile...$^".PHONY:cleanclean:        $(RM) $(OBJ) $(BIN)
复制代码
  留意:这里在echo语句前也要加@不让它回显,否则就会回显出来echo语句的内容。
  实行效果展示

到这里makefile部分就竣事了,后续有要深入相识的语法知识,在后续过程在继承学习。
我的博客即将同步至腾讯云开辟者社区,约请各人一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表