makefile全知道

Posted 城子特讯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了makefile全知道相关的知识,希望对你有一定的参考价值。

一、makefile概念

大型的项目开发一般都有许多头文件、源文件等,其中,其按类型、功能、模块分别放在若干个目录中。这时,就需要用到makefile对这些代码进行编译,makefile定义了一系列的规则来指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。最后,整个项目通过make命令完成编译等功能。

个人对于makefile的命名一般都设定为Makefile_X(X表示项目英文名),不过这个仅个人习惯。

使用的时候如下设定:

make -f Makefile_X(X表示项目英文名)

二、makefile基础知识

1、makefile原理和规则

makefile规则如下:目标:依赖(tab)规则    //每条规则处不能使用空格,需要会用tab,否则会出问题。目标——生成的目标文件依赖——生成目标所需文件规则——由依赖文件生成目标文件的命令,如规则:gcc fun.c -o fun目标文件生成中,1、检测依赖文件存在与否,若不存在,查找是否有规则生成依赖文件。

下面以开发并联机器人项目为例:

parallelrobot:Main.o Speed.o Initial.o Kinematics.o Trajectory.o ...  gcc main.o Speed.o ....-0 prallelrobot  Main.o: main.c  ...  //整个流程是向右寻找依赖,再向左执行命令,生成目标  //为了按规则生成目标文件,可使用下面命令  make -f Makefile_parellelrobot // 参数-f 使得文件名可以随意设定

如果在编译过程中,不希望产生中间的X.o文件可以使用make clean; 

特殊情况:当前文件中如果有clean文件可以使用伪目标申明

 .PHONY: clean

2、变量和函数

变量可通过直接赋值设定,如

PATH=./path/robot/变量取值OUTPUT=$(PATH)./*.c   //表示在当前目录下的素有.c文件系统中默认值LDFLAGS:链接库使用的选项 -L -lCFLAGS:编译使用的选项 -Wall -g -cCPPFLAGS:预处理使用的选项 -l 等等

另外,makefile有三个非常常用的自动变量,如下

$@: 规则中的目标$^:规则中所有的依赖文件$<:规则中第一个依赖文件

当项目中的依赖文件很多时,一个一个输入即容易输错又耗时,则可以采用模式规则,采用%匹配目录下的所有文件。

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

makefile为我们提供了一些函数,这里引入较为常用的几个函数作举例分析,如在下面的开发目录中有main.c、robotmotion.c、robotspeed.c文件

wildcard:查找相应目录下的指定类型的文件。

Source=$(wildcard ./source/*.c )//查找当前目录下所有.c的文件并赋值给Source,得到的Source的值为 main.c robotmotion.c robotspeed.c

patsubst: 相应文件的相互替换

object=$(patsubst ./%.c,./%.o,$(Source))//将Source当中的.c文件替换为当前目录的.o文件,则object=main.o robotmotion.o robotspeed.o

3、makefile用例

1、当项目中的文件较少的情况下考虑,使用简单的makefile方法,如

parallelrobot: main.c function1.c function2.c  gcc main.c function1.c function2.c -o parallelrobot

这个代码的缺点是任何文件稍微修改就需要重新编译。因此需要再进行优化,以生成的中间文件,解决这个问题。优化如下:

parallelrobot: main.o function1.o function2.o  gcc main.o function1.o function2.o -o parallelrobotmain.o: main.c  gcc -c main.c -o main.ofunction1.o: function1.c  gcc -c function.c -o function.o function2.o: function2.c   gcc -c function2.c -o function.o

优化后的这个版本虽然解决了重新编译的问题,但是代码出现了重复,其仅适用于超小型项目文件。

2、使用模式规则的makefile的方法

模式规则为

object = main.o function1.o function2.o  target = parallelrobot  CC = gcc  $(target): $(object)      $(CC) $(object) -o $(target)  %.o: %.c      $(CC) -c $< -o $@  

使用这种模式规则减少了代码重复,但是在依赖文件较多时,其工作量还是相对较大,因此需要引入使用wildcard和patsubst的优化版本。

3、优化的makefile方法(较好

source = $(wildcard ./*.c)  object = $(patsubst %.c, %.o, $(source))  target = parallelrobotCC = gcc  $(target): $(object)      $(CC) $(object) -o $(target)  %.o: %.c      $(CC) -c $< -o $@  #.PHONY是声明clean是一个伪目标,这样我们通过执行make clean命令# 就是将中间文件如.o文件及目标文件全部删除。.PHONY: clean  clean:      rm -rf $(object) $(target) 

4、编译共用文件的案例

有2个应用程序application1.c和application1.h、application2.c和application2.h,2程序共用application3.c和application3.h。针对这个问题,我们可以把共用的程序放在一个文件内,另外每个程序各自单独一个程序。

则makefile可表示如下:

APP1 = application1  APP2 = application2  Target = $(APP1) $(APP2)  Source_APP3 = $(wildcard ./Application3/*.c)  Source_APP1 = $(Source_APP3) $(wildcard ./Application1/*.c)  Source_APP2 = $(Source_APP3) $(wildcard ./Application2/*.c)  Object1 = $(patsubst %.c, %.o, $(Source_APP1))  Obejct2 = $(patsubst %.c, %.o, $(Source_APP2))  INCLUDE = -I ./Application3/  CFLAGS = -Wall -c  CC = gcc  #注:生成两个可执行文件(两个目标)。由于makefile只能有一个目标,# 所以可以构造一个没有规则的终极目标all,并以这两个可执行文件作为依赖all: $(Target )  $(APP1): $(Object1)      @mkdir -p out/    //@后的命令只执行不回显    $(CC) $(Object1) -o out/$(APP1)  $(APP2): $(Obejct2)      @mkdir -p out/     //@后的命令只执行不回显    $(CC) $(Obejct2) -o out/$(APP2)  %.o: %.c      $(CC) $(INCLUDE) $(CFLAGS) $< -o $@  .PHONY: clean  clean:      rm -rf $(Object1) $(Object2) out/

三、总结

以上是博主今天的分享,如果您喜欢博主的文章,请留下关注和点赞,您的关注是我写作和分享的动力。感谢!

以上是关于makefile全知道的主要内容,如果未能解决你的问题,请参考以下文章

makefile全知道

makefile全知道

Yuchuan_Linux_C编程之六 Makefile项目管理

Makefile项目管理-----在Linux下编译c/c++程序

Makefile——使用变量

跟我一起写Makefile