ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Linux基础工具之make/makefile

2026/8/19 23:23:09 拓冰建站 浏览量
Linux基础工具之make/makefile 一.make/makefile是什么make是一条指令。makefile是一个文件。两个搭配使⽤完成项⽬⾃动化构建。makefile带来的好处就是⸺“⾃动化编译”⼀旦写好只需要⼀个make命令整个⼯程完全 ⾃动编译极⼤的提⾼了软件开发的效率。写了makefile文件以后在编译代码时就不需要一遍遍地去gcc了只需要在指令行输入make就行。make指令会寻找当前目录下的makefile文件然后根据makefile文件里的内容去自动编译代码。二.基本概念——依赖关系与依赖方法在makefile文件中我们需要编写依赖关系和依赖方法。用一个通俗的故事来说明刘姥姥三进大观园是个很耳熟能详的故事刘姥姥(con)与大观园众人(code.c)是一种亲戚关系这种亲戚关系就是依赖关系刘姥姥要依赖于大观园众人而刘姥姥依赖于众人的方式是打秋风那么打秋风就是一种依赖方式。程序code是依赖源文件code.c形成的code与code.c就是一种依赖关系那么如何形成程序呢靠的是gcc -o code code.c这样的依赖(编译)方法。相当于依赖关系是成事的关系而依赖方法是成事的方法。三.clean——用于清理bin(可执行程序)的目标文件程序执行完是需要被清理的因此要在makefile文件里添加一个被关键字.PHONY修饰的目标文件:clean,在clean的依赖关系中其依赖文件可以为空也就是什么都不依赖但是要有依赖方法依赖方法就是rm -f 程序名即强制删除程序。make命令扫描makefile文件的时候是从上到下去扫描的默认生成第一个目标文件。像clean这种第二个目标文件没有被第⼀个⽬标⽂件myproc直接或间接关联那么它后⾯所定义的命令将不会被⾃动 执⾏不过我们要make执⾏就输入命令⸺“make clean”以此来清除所有的⽬标 ⽂件以便重编译。输入make clean以后程序文件myproc就被强制删除了:四. .PHONY关键字与无法总是被执行(需要更新以后才能继续执行)上面被.PHONY修饰的目标文件clean被称作伪目标伪⽬标的特性 是总是被执⾏的。什么叫做总是被执行呢makefile里的gcc命令只能被执行一次当用make再次执行多次时会出现以下报错:这就是不能总是被执行的情况。当用.PHONY修饰上myproc时再用make执行多次就不会报错:这便是总是被执行。关于up to date(更新)①.老代码不做重新编译根据不能总是被执行的报错无法被再次执行的原因在于.c文件(源文件)没有更新用老的代码重复编译就会造成浪费。所以就默认老代码不做重新编译。就不能总是被执行。而判断.c是否更新过的依据就是看bin和.c谁新谁旧.c新(modify时间晚)就代表其刚被更新过可以被编译。②.make如何知道bin(可执行程序)和.c谁新谁旧文件 内容 属性我们输入stat.c就可以看到bin的三个时间:access,modify,changeModify: 内容变更时间更新Change 属性变更时间更新Access 常指的是⽂件最近⼀次被访问的时间。在 Linux 的早期版本中每当⽂件被访问时其 atime 都会更新。但这种机制会导致⼤量的 IO 操作,因此不是访问一次文件就更新access一次。知道上面的概念以后我们再来看更新与被执行(能编译)的问题这里画一个时间轴说明:总结一下就是要能编译(继续被执行)就要更新.c文件即要保证.c文件的modify时间晚于bin的。③.再探touch欸touch这玩意不是新建一个文件吗这是对的但touch的作用和本质不止于此。对于新文件我们做以下实验来验证上面的结论:对于已经存在的文件做以下实验进行验证:所以既要能够继续被执行(能再次编译)又不想更新.c的内容这怎么操作呢——答案是输入touch .c更新一下modify时间,再进行make就能继续执行(再次编译)。回归.PHONY所以.PHONY能够做到总是被执行的原理就是:忽略新旧modify时间的对比直接执行(编译)。五.makefile的推导过程那么系统在具体执行这些指令上是怎么操作的呢六.makefile语法①.“”——定义变量and$——引用变量“”定义变量而$就是引用变量的内容。我们在makefile里做个实验以验证上面说的:可见将三个变量定义的内容打了出来:定义的规范②.——不回显指令就像上面那样make一下会先回显指令再执行如果在makefile里,指令前加一个“”就不会回显:③.别样的写依赖关系与依赖方式的形式在知晓上面的语法后我们可以直接用$变量的方式去写依赖关系与依赖方式:④.$:目标文件$^:依赖文件因此可以将上面的依赖方法再精进一下⑤.更为合理的链接方式一般情况下我们不把.c直接链接生成bin,而是将多个.c先编译生成.o,再由.o统一链接生成bin这就是下面为什么只需要写一条链接但需要展开所有条编译的原因。⑥.如何应对多个.c编译的情况and更为精进的代码三个符号和一条指令我们先引入三个符号和一条指令:Ⅰ.%.c与%.o展开当前目录下所有.c文件展开当下目录下所有.o文件Ⅱ.%展开的所有依赖 .c ⽂件并⼀个⼀个的交给 gcc。指令gcc -c .c文件将.c文件自动编译成同名的.o文件代码实现注意:千万不要学笔者在依赖方法后面搞注释不然系统会误把注释当成依赖方法的一部分然后报错:⑦.告别手动罗列.c与.o文件在定义变量SRC和OBJ的时候我们还得把当前目录下所有的.c一 一罗列以及根据.c文件一 一创建出同名的.o文件以供编译和链接一点都没体现出makefile的便捷性。所以对于.c我们提供两种方法来自动获取:Ⅰ.利用shell命令行的指令:ls *.c注*是所有的意思Ⅱ.利用makefile内部类似于函数的东西——wildcard来自动获取当前目录下.c。对于创建.o文件我们提供一种方法:将SRC所有.c文件替换成.o生成同名.o文件。