Makefile的使用笔记

本文详细介绍Makefile的基础概念、编写规则及高级用法。通过实例演示如何利用Makefile自动化编译大型项目,提高软件开发效率。

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

 http://www.stlchina.org/twiki/bin/view.pl/ScriptProgram/LearnMakefile#0%20Makefile
这是makefile学习的一个好网站
粗看了一遍是一则很好的文章,就用这个文章开始我的makefile的学习吧!
常用的makefile看走来很简单,其实内部还有很多好的用处没有使用到,现在就开始学习吧!
======================================================
一、makefile的作用:
  makefile是在有很多.h(头文件),.cc(源文件),以及链接库的情况下可以节省时间更有率利用时间的编译程序。
makefile定义了一系列的来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译。
makefile带来的好处就是--"自动化编译",一旦写好只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的
效率。
  一般来说,无论是C还是C++,还是pas首先要把源文件编译成中间代码文件,在windows下也就是.obj文件,UNIX下是.o文件
即ObjectFile这个动作叫做编译(compile)。然后再把大量的为Object file合成执行文件,这个动作叫链接(link)。
总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法和函数、变量是否被声明。
如果函数未被声明,编译器会给出一个警告,但可以生成ObjectFile。而在链接程序时链接器会在把有的ObjectFile中找寻函数的实现,如果
找不到,那就会报链接错误码,在VC下这种错误一般是:LINK 2001错误,意思是说链接器未能找到函数的实现。

 

二、Makefile介绍
 Makefile书写规则:
1.如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接
2.如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序
3.如果这个工程的头文件被改变了,那么我们需要编译引用了这几个文件的C文件,并链接目标程序
只要我们的Makefile写得够好,所有的这一切我们只用一个make命令就可以完成,make命令自动智能地根据当前的文件修改的情况来确定哪些
文件需要重编译,从而自己编译所需要的文件和链接目标程序。

 

三、Makefile的语法规则:
target...(目标):prerequisites...(依赖关系)
 command(linux命令或依赖关系的生成)
 ...
 ...
target也就是一个目标文件,可以是ObjectFile也可以是执行文件还可以是一个标签(label)如果是标签的话要放在目标文件后写
 他会通过make <label>命令来调用
prerequisites就是要生成那个target所需要的文件或是目标
command也就是make需要执行的命令
这是一个文件的依赖关系,也就是说target这个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。
说白一点就是说:prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则,
也就是说Makefile中最核心的内容。

示例:此edit工程有3个头文件,和8个c文件,我们也的Makefile就如下:

edit : main.o kbd.o command.o display.o /
           insert.o search.o files.o utils.o=======================>edit要引用的8个c文件target是edit而prerequsitites就是:后的
            cc -o edit main.o kbd.o command.o display.o /
                       insert.o search.o files.o utils.o===========>要编译成的目标文件

    main.o : main.c defs.h
            cc -c main.c
    kbd.o : kbd.c defs.h command.h
            cc -c kbd.c
    command.o : command.c defs.h command.h
            cc -c command.c
    display.o : display.c defs.h buffer.h
            cc -c display.c
    insert.o : insert.c defs.h buffer.h
            cc -c insert.c
    search.o : search.c defs.h buffer.h
            cc -c search.c
    files.o : files.c defs.h buffer.h command.h
            cc -c files.c
    utils.o : utils.c defs.h=======================================>utils.o 依赖的文件
            cc -c utils.c==========================================>.o的生成
    clean :========================================================>这是一个标签要运行使用make clean就行了
            rm edit main.o kbd.o command.o display.o /=============>标签要运行的linux命令
               insert.o search.o files.o utils.o

 

 

四、make是如何工作的
make工作流程如下 :
1.make会在当前目录下找名字叫"Makefile"或"makefile"的文件
2.如果找到,它会找文件中的第一个目标文件target,在上面的例子中,支找到edit这个文件,并把这个文件作为最终目标文件
3.如果eidt文件不存在,或是edit所依赖的后面的.o文件的方件修改时间表要比edit这个文件新,那么,他就会执行后面所定义的命令来生成 
edit这个文件。
4.如果edit所依赖的.o文件也丰在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据寻一个规则生成.o文件。
5.当然,你的C文件和H文件是存在的,于是make会生成.o文件,然后用.o文件生成make的终极任务。
通过上术分析,我们知道像clena这样,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以
显示要make执行。即命令“make clean”以此来清除所有的目标。
make执行步骤:
1.读入所有的Makefile
2.读入被include的其它Makefile
3.初始化文件中的变量。
4.推导隐晦规则,并分析所有规则
5.为所有的目标创建依赖关系链
6.根据依赖关系,决定哪些目标要重新生成。
7.执行生成命令。

 

五:makefile中使用变量:
这里的变量有点像宏定义
对于变量我还是推荐用大写来表示例如上面的内容我们可以改成
OBJECTS = main.o kbd.o command.o display.o/
 insert.o search.o files.o utils.o
eidt:$(OBJECTS)
 cc -o edit $(OBJECTS)
......
.....
clean:
 rm edit $(OBJECTS)
这个makefile带来了很多方便

 

六、让make自动推导(还是自己写比较好)
GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在第一个.o文件后都上类似的命令。因为
我们的make会自动识别,并自动推导命令。
只要make看到一个.o文件,它就会自动的把.c文件加在依赖关系中,如果make找到一个whatever.o那么whatever.c就会是whatever.o的依赖文件。
原版本:      自动推导只要写成
main.o:main.c defs.h     main.o:defs.h(完事了!)
 cc -c main.c

 

 

七、清空目标文件的规则;
每个Makefile中都应该写一个清空目标文件(.o执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。
clean:
 rm edit $(OBJECTS)
更为稳健的做法是:
.PHONY:clean=========================>.PHONY意思表示clean是一个伪目标。
clean:
 -rm edit $(OBJECTS)==========>在rm命令前面加一个小减号的意思就是,也许某些文件出现问题但不管继续做后面的事。
clean从来都是放在文件在最后。

 

八、引用其它的Makefile
在Makefile使用include关键字可以把别的Makefile包含进来,这很很C的include
语法:include <filename>
例如:include foo.make a.mk b.mk c.mk e.mk
在引用中也可以用到变量。

九:自动依赖性:
可以用
cc -M main.c
来解决依赖的文件关系
等价于:
main.o : main.c defs.h
如果用的是GNU的c/C++编译器你利用“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来。


总述一下上面的内容:
Makefile里主要包含了五个东西:显示规则,隐晦规则,变量定义,文件指示和注释(#)
1.显式规则。显式规则说明了,如何生成一个或多个的目标,这里由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,
生成的命令。
2.隐晦规则:由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的
3.变量的定义。在makifile中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏。
4.文件指示。其包括了三个部分,一个是在一个makefile中引用别一个Makefile,就像C语言中的include一样,别一个是指根据某些情况
批定Makefile中的有效部分,就像C语言中的预编译#if一样,还有就是定义一个多行的命令。
5.注释,makefile只有行注释。#号
还有一个重要的提示:Makefile中的命令,必须要以[tab]键开始

Makefile的文件名:
默认的情况下make会去在当前目录下按顺序找寻文件名为GNUmakefile,makefile, Makefile的文件。最好用Makefile这个文件名,
你也可以使用别的名字来书写Makefile比如:Make.linux等如果是你自己的makefile文件你可以自己指定命令为:
makef -f <makefilename> 或 make -file <makefilename>

 

重要规则:
1.通配符:
 支持三个通配符:“*”“?”“[]”
2.文件搜寻:
Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。
如果定义了这个变量,那么,make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件。
VPATH = SRC:.../headers
上面的定义指定两个目录,“src和../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔,(当然,当前目录永远是最高优先搜索的土方)
另一个设置文件搜索路径的方法是使用make的vpath关键字,全小写,这不是变量,而是make的关键字,这和上面的VPATH变量很类似,
但是它更为灵活。它可以指定不同的文件在不同的搜索目中,
三种方法:
1.vpath <pattern> <directories>
为符合模式<pattern>的文件指定搜索目录<directories>
2.vpath <pattern>
清除符合模式<pattern>的文件的搜索目录。
3.vpath
清除所有已被设置好了的文件搜索目录
vpath使用方法中的<pattern>需要包含“%”字符。“%”的意思是匹配零或若干字符。例如“%.h”表示所有的以".h"结尾的文件,
<pattern>指定了要搜索的文件集,而<directories>则指定了搜索的目录。
例:vpath %.h ../headers:/nfsroot在../header和/nfsroot下找文件以.h结尾

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值