gcc编译器创建和使用静态库、动态库
http://www.cnblogs.com/dyllove98/archive/2013/06/25/3155599.html
目录树结构:
test/include/hello.h
1 #ifdef _HELLO_H_ 2 #define _HELLO_H_ 3 void hello(); 4 #endif
test/src/hello.c
1 #include "hello.h" 2 #include <stdio.h> 3 void hello() 4 { 5 printf("hello world!\n"); 6 }
test/bin/main.c
1 #include "hello.h" 2 int main() 3 { 4 hello(); 5 }
静态库过程如下:
第一步:生成目标文件
进入到test/src/目录下:
#gcc -c -I../include hello.c
生成目标文件hello.o,(注意:大写的i,表示搜索头文件,本实例中为搜索hello.h)
第二步:生成静态库文件
#ar rc libhello.a hello.o
该命令将hello.o添加到静态库文件libhello.a,ar命令就是用来创建、修改库的,也可以从库中提出单个模块,参数r表示在库中插入或者替换模块,c表示创建一个库,关于ar命令的详细使用规则可以参考文章http://blog.csdn.net/xuhongning/article/details/6365200。
第三步:生成可执行文件
该命令将编译main.c并链接静态库文件libhello.a生成可执行文件main,注意:参数-L添加库文件搜索目录,因为libhello.a在libtest/lib目录中,这里需要指定该目录通知gcc,参数-l指定链接的库文件名称,比如 -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
这一步将在libtest/src目录中生成可执行文件main。
#gcc main.c -o main -I../include -L../src -lhello
$ ldd test
执行test,可以看到它是如何调用动态库中的函数的。
动态库过程如下:
前提知识:
编译参数解析
最主要的是GCC命令行的一个选项:
-shared该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
-fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
(1) 生成动态库文件
进入test/src目录,执行命令:
gcc hello.c -o libhello.so -I../include -fPIC -shared
这一步将在当前目录生成动态库文件libhello.so,
(2) 生成可执行文件
进入test/bin目录,执行命令:
gcc main.c -o main -I../include -L../src -lhello
此时在当前目录中已经生成了可执行文件main,执行./main时却提示错误:
./main: error while loading shared libraries: libhello.so: cannotopen shared object file: No such file or directory
也就是找不到动态库文件libhello.so,
有两种方法:
一、可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。
二、把当前路径加入环境变量LD_LIBRARY_PATH中
当然,如果你觉得不会引起混乱的话,可以直接把该库拷入/lib,/usr/lib/等位置(无可避免,这样做也要有权限),这样链接器和加载器就都可以准确的找到该库了。
我们采用第二种方法:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
如下:
export LD_LIBRARY_PATH=”../lib”
gcc main.c -I../include -L../lib -lhello -o main
然后再执行./main就没有错误了。
【补充】
环境变量LD_LIBRARY_PATH指示动态连接器可以装载动态库的路径,在链接动态库文件前设置该变量为库文件所在路径,注意:用export LD_LIBRARY_PATH=”…”方式只是临时生效的,如果要永久有效可以写入~/.bashrc文件中(当前用户有效),跟修改PATH类似,exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:”…”。
当然如果有root权限的话,也可以修改/etc/ld.so.conf文件,将要添加的动态库搜索路径写入该文件中,然后调用/sbin/ldconfig来达到同样的目的。
附录:
1. 编译链接库:-lz -lrt -lm -lc都是什么库?
libz 压缩库(Z)
librt 实时库(real time):shm_open系列
libm 数学库(math)
libc 标准C库(C lib)
可以进入/lib,/usr/lib,可以看到你机器上大多数的libXXXX
-----------------2019-06-29 16:22:51----------------
Linux gcc编译和程序运行时头文件及库搜索顺序
获取库调用路径及链接名:
pkg-config --cflags --libs glib-2.0 gtk+-3.0
gcc 在编译时如何去寻找所需要的头文件:
※搜寻会从-I开始
※然后找gcc的环境变量 C_INCLUDE_PATH,CPLUS_INCLUDE_PATH,OBJC_INCLUDE_PATH
※再找内定目录
/usr/include
/usr/local/include
编译的时候:
※gcc会去找-L
※再找gcc的环境变量LIBRARY_PATH
※再找内定目录
/lib和/lib64
/usr/lib 和/usr/lib64
/usr/local/lib和/usr/local/lib64
这是当初compile gcc时写在程序内的
运行时动态库的搜索路径
动态库的搜索路径搜索的先后顺序是:
1.编译目标代码时指定的动态库搜索路径;
2.环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3.配置文件/etc/ld.so.conf中指定的动态库搜索路径;
4.默认的动态库搜索路径/lib;
5.默认的动态库搜索路径/usr/lib