linux下的静态库和动态库的编译

摘自:http://blogold.chinaunix.net/u2/70445/showart_2081108.html

 

【目录】
1、静态库
2、动态库
3、说明
4、参考资料

每个程式实质上都会链接到一个或多个的库。比如使用 C函数的程式会链接到C运行时库,GUI程式会链接到窗口库等等。无论哪种情况,你都会要决定是链接到静态库(static libary)还是动态库(dynamic libary)。链接到静态库会使你的程式臃肿,并且难以升级,不过可能会比较容易部署。而链接到动态库会使你的程式轻便,并且易于升级,不过会难以部 署。
静态库
静态库也就相当于是把一系列的object文件放在同一个文件中(类似windows中的.lib文件)。当你提供一个静态库 给链接器时,连接器将会搜索静态库,从中找到他所需要的object文件,提取出他们,将他们链接到你的程式中,就像你直接提供那些文件相同。怎么创建静 态库呢?你能使用ar命令来创建。
下面我们举个例子:
test/lib/test1.c
#include
int hello_world1()
{
    printf("hello world1\n");
    return 1;
}
test/lib/test2.c
#include
void hello_world2()
{
    printf(" hello world2\n");
}
test/app.c
#include
int main()
{
    hello_world1();
}
目前我们编译他们进入目录test/lib
$gcc -c test1.c
$gcc -c test2.c
$ls
test1.c  test1.o  test2.c  test2.o
$ar cr libtest.a test1.o test2.o
$ls
libtest.a  test1.c  test1.o  test2.c  test2.o
cr标志告诉ar将object文件封装(archive),我们能使用nm -s 命令来查看.a文件的内容
$nm -s libtest.a
Archive index:
hello_world1 in test1.o
hello_world2 in test2.o
test1.o:
00000000 T hello_world1
         U puts
test2.o:
00000000 T hello_world2
         U puts
目前让我们编译主程式
首先退出lib目录
$cd ..
$gcc -o app app.c -Llib -ltest
-L指定了lib的搜索路径,-l指定了链接的库的名字-ltest也就是链接libtest.a
$./app
hello world1
hello_world1()被从libtest.a中找到并链接过来了,于是整个的过程中没有出现问题。
动态库
动 态库(static lib)也可一也能成为共享库(shared lib),一般的后缀名是.so。动态库和静态库有点类似,他们都是一系列的object文件的集合,只是他们的组织方式不同。同样他们的链接方式也是不 同的,动态库只在执行是链接使用,并不把相应的部分编译入程式中,在使用是个库能被多个程式使用故可称为共享库,而静态库将会整合到程式中,链接时各程式 使用自己的库。
下面我们来介绍怎么创建动态库,还是之前的三个文件,同样的布局,进入lib目录
$gcc -c -fPIC  test1.c
$gcc -c -fPIC  test2.c
-fPIC告诉gcc将原始码编译成共享的object文件,PIC(Position-Independent Code)非位置依赖性代码。
$gcc -shared -fPIC -o libtest.so test1.o test2.o
将两个文件整合为共享库libtest.so
退出lib目录
$cd ..
$gcc -o app app.c -Llib -ltest
$./app
./app: error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
啊哈,我们在这里遇见一个error没找到libtest.so,说明我们的编译成功了,libtest.so成为了一个shared libary。程式之所以不能运行是因为libtest.so不在默认的搜索路径上
怎样才能让他跑呢?
$LD_LIBRARY_PATH=$PWD/lib ./app
hello world1
我们在自己指定链接的路径,他找到了我们的libtest.so文件,并且链接成功了。
说明
l  -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
l  -L.:表示要连接的库在当前目录中
l  -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称
l  LD_LIBRARY_PATH:这个环境变量指示动态连接器能装载动态库的路径。
l  当然如果有root权限的话,能修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。
       调用动态库的时候有几个问题会经常碰到,有时,明明已将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活未找到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或/etc/ld.so.conf文件来指定动态库的目录。通常这样做就能解决库无法链接的问题了。
参考资料
    《Advenced linux Programming》Mark Mitchell, Jeffrey Oldham,and Alex Samuel
    man nm
    man ar

你可能感兴趣的:(linux,object,gcc,Path,library,archive)