0%

Makefile通用模板

1. 前言·

本文并不会介绍Makefile的基础使用方法,不过对于初次接触Makefile的同学们,这里推荐阅读《跟我一起写Makefile》,全书一共80来页,从Makefile的基础用法到进阶使用都讲解得比较通透。

Makefile简介:一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。--------------摘自百度百科

2. C/C++项目Makefile模板·

结合《跟我一起写Makefile》,我常用的Makefile模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
CC := gcc

# CFLAGS
CFLAGS := -g -Wall

# 库文件存放地址
LIB := -L ./lib

# 链接库
LIB += -lxml2 \
-ljpeg

# 头文件所在地址
INCLUDE :=-I ./include/ \
-I ./

CSources := $(shell find -name "*.c") # 通过find命令,找到所有的.c文件

Objs := $(CSources:.c=.o)

main :$(Objs)
$(CC) $^ -o $@ $(CFLAGS) $(LIB)

%.d : %.c
rm -f $@; \
$(CC) -MM $(INCLUDE) $< > $@.$$$$; \
sed -e 's,^.*:,$*.o $@:,g' < $@.$$$$ > $@; \
rm -f $@.$$$$

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

.PHONY : clean

clean:
@echo $(CSources)
rm main $(CSources:.c=.d) $(CSources:.c=.o)

这里讲解一下这个模板的几个变量:

  • CC :使用的编译器,gcc/g++/arm-linux-gcc等等
  • CFLAGS: 编译器参数
  • LIB : 项目中所使用到的各个库
  • INCLUDE: 项目头文件

再看看几个代码片段,大多数都是生成中间文件,.o文件。这中间有一串很难看的代码— %.d : %.o下面这一块,但是其实不用管它具体是怎么运行的,你只用知道它是用于生成各个文件之间的依赖关系的就行了 (其实关键在于 -MM 参数),用于辅助编译的。对于爱学习想深究的那些同学们,可以阅读《跟我一起学Makefile》,查看一下生成出来的.d文件,应该也就懂了

另外,给一个建议:

其实很多时候并不需要我们书写Makefile,反而是需要书写gcc编译规则,比如添加的头文件在哪儿?代码所需要的库文件在哪儿?又需要链接那些库? 搞懂gcc编译中常用的参数,直到能够回答上面三个问题,再来书写Makefile就会容易很多了。


简单回答一下上面三个问题,具体的实施,需要自己去实际敲代码,用命令编译一下才知道。

  1. 找到头文件: gcc编译器中有-I参数,后面跟的路径就是头文件路径。

  2. 找到库文件:gcc编译器中有-L参数,后面跟的路径就是库文件路径的,当然linux环境下,gcc也会自动到根目录和usr目录下的lib下找库文件。 (库文件包括静态库后缀为.a,动态库后缀为.so,两者的区别在于,前者在编译过程中就一起链接到可运行程序中,造成最终的程序过大,但便于移植。后者则不链接到可运行程序中,而是在运行时到环境中去寻找该库,所以可运行程序较小,但是不便于移植,使用这样的程序就需要自己要安装一些动态库)

  3. 链接库:光是找到库文件所在地还不够,需要指明需要链接哪些库,gcc编译器中有-l参数,后面跟你要链接的库。需要注意的一点是,linux下的库文件有命名规则,文件开头必须是lib,例如我有一个字体库,那么文件可为libfont.alibfont.so,另外我们还可能看见动态文件名后面带数字,如libfont.so.2,这里最后一个数字代表了这个库的版本。

最后再来看一下上文给的模板的上半段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CC := gcc

# CFLAGS
CFLAGS := -g -Wall

# 库文件存放地址
LIB := -L ./lib

# 链接库
LIB += -lxml2 \
-ljpeg

# 头文件所在地址
INCLUDE :=-I ./include/ \
-I ./

这段的意思是,本项目使用gcc编译,编译后的结果可调试(-g),并且打印编译过程中的所有警告(-Wall),项目的头文件放在./lib(别忘了gcc还会到根目录和/usrlib去寻找哦),在这些库文件中我要链接xml2,jpeg库,头文件放在了./include和./下。

文章对你有帮助?打赏一下作者吧