入门介绍
起因是我在工作中,遇到了一个多个执行文件打包成的组件,而每个执行文件都需要将pb编进二进制中,导致release包非常大。所以想到,是否应该将pb编程动态链接库,再供可执行文件使用呢?达成这个目的需要做两件事。1、将pb编成.so文件。2、将原本的链接方式改为动态链接。
makefile是make构建项目所需要的规则文件。通产在其中指定了编译目标、编译指令、编译依赖。通常的makefile被命名为“Makefile”“makefile”,但也可以通过make -f filename去指定非标准命名的makefile,以适应不同的项目需求。
生成目标文件
通常我们想要的目标文件分为三种,可执行文件(a.out),.a文件(静态链接库),.so(动态链接库)。
许多人都清楚怎样处理一个单纯的main.cpp,g++ main.cpp即可。执行完毕后同级目录下会出现a.out。a.out代表着g++编译并链接得到的可执行文件。如果不喜欢a.out这个默认名称,通常使用g++ -o hello hello.cpp这样的命令。可能有人会不清楚,g++ -o hello hello.cpp 和 g++ hello.cpp -o hello有什么区别呢?毕竟很多人百度g++,无非也只是想得到一个确切能用的命令而已,不了解也不奇怪。-o的意思是 指定了了g++的输出目标,所以写在哪里都可以。
g++的常用选项:https://www.cnblogs.com/lidan/archive/2011/05/25/2239517.html
初学者需了解-o -g -static -fPIC -D等常用参数。
makefile说到底还是像脚本一样执行了g++命令,想要利用makefile构建c++项目,会使用g++命令就是第一步。
makefile基础语法:https://www.cnblogs.com/wang_yb/p/3990952.html
一个常见简单的makefile文件通常长这样:
$(target):*.o $(CXX) $(CXXFLAGS) -o [email protected] $^ %.o:%.cpp $(CXX) $(CXXFLAGS) -o [email protected] $<
make会从上至下寻找第一个编译目标。如果将target:*.o挪到文件的最下方,那执行make后,也只能得到一堆.o文件,而无法得到target。
有时候目标文件不止一个,这个时候就要使用all来指定多个target。
在文件上方添加: all:$(target) $(target2)
all:$(target) $(target2) $(target):*.o $(CXX) $(CXXFLAGS) -o [email protected] $^ $(target2):*.o $(CXX) $(CXXFLAGS) -o [email protected] $^ %.o:%.cpp $(CXX) $(CXXFLAGS) -o [email protected] $<
target和target2是最终的目标文件,但我们为make指定的目的文件是"all",target和target2其实是"all"的依赖。
如果目标是一个/多个普通的可执行文件,CXXFLAGS="-g",如果目标需要链接动态链接库,CXXFLAGS="-g -fPIC"
如果目标是一个动态链接库,CXXFLAGS="-g -shared"
如果目标是一个静态链接库,生成target的指令就不是cxx而是ar
all:$(target) $(target2) $(target):*.o ar -cvr [email protected] $^ $(target2):*.o $(CXX) $(CXXFLAGS) -o [email protected] $^ %.o:%.cpp $(CXX) $(CXXFLAGS) -o [email protected] $<
链接动态链接库
如果目标仅仅是生成可执行文件,那么上一步已经完成了。但是我的目标是生成动态链接库并用可执行文件去链接它,已达到节省空间的目的。
g++的-l与-L分别指定了动态链接库和链接库所在的地址。如 g++ -o hello hello.cpp -luuid -L/usr/lib
除此之外,也可以在代码中指定要使用的动态链接库。dlopen了解一下。
编译成功后,接下来就是运行的问题了。ldconfig命令可以帮助我们知道,这台机器上动态链接库的地址有哪些。想要成功运行连接了动态链接库的可执行文件,方法有四种。
1、将动态链接库直接丢进ldconfig包含的路径中。
2、将动态链接库丢到自定义的目录中,与系统自带的库分开,并将自定义目录加入到/etc/ld.so.conf文件中
3、如果是daemon进程,在start脚本中export LD_LIBARY_PATH也是个办法
4、使用g++的rpath指令指定库的路径。
3、4是简单易用的办法,推荐新手使用。
结语
本文只介绍了构建项目的大体思路,并未给出具体的命令与说明。如果需要更详细的说明,不妨百度/google我给出的关键词or看看我贴出的两篇文章。
原文地址:https://www.cnblogs.com/bakoom/p/9697274.html