多目录Makefile编写
对于在Linux下编程来说,编写一个好的Makefile是非常重要的,写好了可以给编译带来极大的便利。而网上对于多目录下Makefile的编写讲解的非常少, 有很多都不能达到目的。这里参考了网上一篇Makefile,它是针对C语言的,写的挺不错。我将它改了一下,用于编译C++的Makefile。
参考链接在这里
https://blog.csdn.net/xiaoluoshan/article/details/78639961
1. 我的目录结构
>> common-存放一些公共的头文件。
>> debug-存放bin目录和obj目录,bin存放编译的最终可执行文件,obj存放生成的目录文件。
>> entity-存放实体的定义,包括头.h和.cpp文件。
>> include-存放项目的头文件。
>> network-存放socket通讯的封装。
>> protocols-协议解析的封装。
>> src-程序源文件,包括main函数实现在这里。
2. 最外层Makefile的编写,目录结构如图:
Makefile内容如下:
注意标红的地方,由于项目用到了c++11标准的一些东西,故加这个选项:-std=c++11。另外注意一下最后标红的这行的选项顺序。另外特别注意,如果最外层目录下有自己的目录不进入编译搜索,一定要使用awk排除排,否则编译会报错而中断。这一句:
SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "debug") print $$9}')
如果有多个目录要排除,这里要加入排除的其它目录,这里仅排除debug目录。
3. debug目录Makefile编写,目录结构如图:
Makefile内容如下:
这里我用到了libevent库以及多线程,所以加入了编译选项-levent –lpthread选项。
4. protocols目录Makefile.
由于其会引用外部头文件,所以Makefile中要加入包含路径,这样在程序代码中可以不用包括头文件的路径。Makefile文件格式如下:
注意这里,我加入了自己的头文件路径。再看代码调用的头文件引用:
#include "DataEntity.h"
引用了实体定义,不用带路径。
5. 其它目录Makefile
其它目录Makefile就基本都一样了,需要引用头文件就加入路径,其它项都一样:
6. 最后是一些Makefile编写注意混淆的地方。
(1)Makefile中的 符号 [email protected], $^, $< 的意思:
[email protected] 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
$? 表示比目标还要新的依赖文件列表
(2)wildcard、notdir、patsubst的意思:
wildcard : 扩展通配符
notdir : 去除路径
patsubst :替换通配符
g++ *.o -o [email protected] -lpthread -levent
注意,指定链接成目标文件格式,.o目标文件一定要在前面,中间-o,最后才是最终生成的目标文件,位置不要调返了,否则编译不通过。
(3) g++链接选项
-l+库名,表示链接库,如-lpthread表示链接pthread库,前面要加路径.
-levent表示需要连接libevent库。
-l 参数就是用来指定程序要链接的库,-l参数紧接着就是库名。
-L 参数跟着的是库文件所在的目录名。
-i (小写l) 编译程序到系统默认路进搜索,如果找不到,到当前目录,如果当前目录找不到,则到LD_LIBRARY_PATH等环境变量置顶的路进去查找,如果还找不到,那么编译程序提示找不到库。