linux 如何编译 静态库,动态库

linux下生成并使用静态库与动态库的方法:(由于是C++项目,所以编译器用的g++,但是与gcc的使用是相通的)

  首先是准备工作,把我们需要封装成库文件的函数的头文件与源文件写好,如下:

//myAPI.h
int ADD(int a, int b);
int MINUS(int a, int b);
复制代码
//myAPI.cpp
#include "myAPI.h"

int ADD(int a, int b){
    return a + b;
}

int MINUS(int a, int b){
    return a - b;
}
复制代码

  接下来准备一个测试用的主函数源文件:

复制代码
//main.cpp
#include "myAPI.h"
#include <iostream>

int main(){
    std::cout << "1 + 1 = " << ADD(1, 1) << std::endl;
    std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl;
    return 0;
}
复制代码

重要说明:

linux下用生成静态库的命令 ar 处理 myAPI.o 文件生成静态库文件,生成的库文件应遵循规范,及linux下库文件加“lib”前缀。

编译/链接生成时,也要注意,目标文件/库文件之间有依赖关系,则需要把被依赖文件放到后面(g++6.x),才能编译,

不然可能报错 找不到变量函数/ 未定义的引用 "undefined reference to". 

 

  贴上Makefile,有注解:

复制代码
all: main-1 main-2 main-a main-so main-so2

main-1: myAPI.cpp main.cpp myAPI.h
    g++ -o main-1 myAPI.cpp main.cpp
    @echo "main-1 done.  直接编译省略显示编译.o文件"
    @echo

main-2: main.cpp myAPI.o
    g++ -o main-2 myAPI.o main.cpp
    @echo "main-2 done.  显示编译.o文件"
    @echo

main-a: libmyAPI.a
    g++ -o main-a  main.cpp libmyAPI.a
    @echo "main-a done.  使用.a静态库文件 链接生成程序"
    @echo

main-so: libmyAPI.so
    g++ -o main-so main.cpp ./libmyAPI.so
    @echo "main-so done.  直接使用.so动态库文件(需要带路径,运行时直接使用此路径) 链接生成程序"
    @echo

main-so2: libmyAPI.so
    g++ -o main-so2 main.cpp -L. -lmyAPI
    @echo "main-so2 done.  让g++自动在当前目录("."表示当前目录,或"./")查找.so动态库文件 链接生成程序"
    @echo "    但运行时默认到/usr/lib目录查找,,或运行前设置环境变量 LD_LIBRARY_PATH 为动态库的路径"
    @echo



myAPI.o: myAPI.cpp myAPI.h
    g++ -c myAPI.cpp
    @echo "myAPI.o done.  编译.o文件"
    @echo

libmyAPI.a: myAPI.o
    ar crv libmyAPI.a myAPI.o
    @echo "libmyAPI.a done.  编译.a静态库文件"
    @echo

libmyAPI.so:
    g++ -fPIC -c myAPI.cpp
    g++ -shared -o libmyAPI.so myAPI.o
    @echo "libmyAPI.so done.  编译.so动态库文件,需要 .o文件编译时加选项 -fPIC"
    @echo "    或者 直接编译动态库:"
    @echo "    g++ -shared -fPIC -o libmyAPI.so myAPI.cpp"
    @echo

#或者 直接编译动态库:
#libmyAPI.so:
#    g++ -shared -fPIC -o libmyAPI.so myAPI.cpp
#

clean:
    rm -f *.o *.a *.so main-*
复制代码

  

最后运行程序:

复制代码
[root@lzp test2]# ./main-1
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-2
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-a
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-so
1 + 1 = 2
1 - 1 = 0
[root@lzp test2]# ./main-so2
./main-so2: error while loading shared libraries: libmyAPI.so: cannot open shared object file: No such file or directory
复制代码

可以看到 main-so直接运行了,但是 main-so2 运行出错了,找不到动态库,需要把动态库放到/usr/lib目录;  或者使用"LD_LIBRARY_PATH"环境变量后可以直接运行

复制代码
[root@lzp test2]# LD_LIBRARY_PATH=./
[root@lzp test2]# ./main-so2
./main-so2: error while loading shared libraries: libmyAPI.so: cannot open shared object file: No such file or directory
[root@lzp test2]# LD_LIBRARY_PATH=./  ./main-so2
1 + 1 = 2
1 - 1 = 0
复制代码

PS:但是在 G++ 6.x版本下直接运行main-so2不出错,,以上是G++4.X版本编译的

 

 在项目开发过层中尽量让lib是垂直关系,避免循环依赖;越是底层的库,越是往后面写!

例如:

g++ ...  obj($?) -l(上层逻辑lib) -l(中间封装lib) -l(基础lib) -l(系统lib)  -o $@

这样写可以避免很多问题,这个是在搭建项目的构建环境的过程中需要考虑 清楚地,在编译和链接上浪费太多的生命不值得!

 

  推荐一本书,写的很深刻:《程序员的自我修养——链接、装载与库》

[参考: http://www.tuicool.com/articles/m67z2u2;  http://blog.chinaunix.net/uid-24352482-id-3199452.html]

[参考: http://www.cnblogs.com/little-ant/p/3398885.html]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值