linux静态库与动态库的编译

发布时间:2020-09-29编辑:脚本学堂
本文介绍下,linux系统下,有关静态库与动态库编译的相关知识,有需要的朋友参考学习下。

linux系统中,每个程序实质上都会链接到一个或者多个的库。
比如使用C函数的程序会链接到C运行时库,GUI程序会链接到窗口库等等。

无论哪种情况,你都会要决定是链接到静态库(static libary)还是动态库(dynamic libary)。
链接到静态库会使你的程序臃肿,并且难以升级,但是可能会比较容易部署。
而链接到动态库会使你的程序轻便,并且易于升级,但是会难以部署。

一,静态库
静态库也就相当于是把一系列的object文件放在同一个文件中(类似windows中的.lib文件)。
当提供一个静态库给链接器时,连接器将会搜索静态库,从中找到他所需要的object文件,提取出他们,将他们链接到你的程序中,就像你直接提供那些文件一样。

如何创建静态库呢?可以使用ar命令来创建。

举个例子:
test/lib/test1.c
 

复制代码 代码示例:

#include <stdio.h>

int hello_world1()
{
    printf("hello world1n");
    return 1;
}

test/lib/test2.c
#include <stdio.h>

void hello_world2()
{
    printf(" hello world2n");
}

test/app.c
#include <stdio.h>

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中找到并链接过来了,于是整个的过程中没有出现问题。

二,linux动态库
动态库(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文件,并且链接成功了。