您的位置:首页 > 运维架构 > Linux

linux 静态库与动态库的编译和使用

2011-12-06 11:13 429 查看
gcc -o test.o test.c -----------将.c文件编译成.o

ar -xv libtest.a--------------静态库解包

ar -rv libtest.a *.o------------将.o文件编译成.a,用*.o可以将所有.o文件编译成一个.a

gcc -shared -o test.so *.o-------将.o文件编译成.so,用*.o可以将所有.o文件编译成一个.so

静态库:静态库也叫档案(archive),他们的名字都按管理 *.a 命名,静态库也就是被归档的二进制目标代码文件,当要使用时,就用include 来包含该库的头文件即可,

如果不是标准库,要指名路径,用”-l“ 指名,自己建立静态库,用归档命令”ar“ 即可,例如”ar crv test.a test1.o test2.o“

在linux环境中, 使用ar命令创建静态库文件.如下是命令的选项:

d -----从指定的静态库文件中删除文件

m -----把文件移动到指定的静态库文件中

p -----把静态库文件中指定的文件输出到标准输出

q -----快速地把文件追加到静态库文件中

r -----把文件插入到静态库文件中

t -----显示静态库文件中文件的列表

x -----从静态库文件中提取文件

还有多个修饰符修改以上基本选项

a -----把新的目标文件(*.o)添加到静态库文件中现有文件之后

b -----把新的目标文件(*.o)添加到静态库文件中现有文件之前

v -----使用详细模式

ar 命令的命令行格式如下:

ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files...

参数archive定义库的名称, files是库文件中包含的目标文件的清单, 用空格分隔每个文件.

比如创建一个静态库文件的命令如下:

ar -rv libtest.a a.o b.o

可以用 t 选项显示包含在库中的文件

ar -t test.a

创建库文件之后,可以创建这个静态库文件的索引来帮助提高和库连接的其他程序的编译速度.使用ranlib程序创建库的索引,索引存放在库文件内部.

ranlib libtest.a

用nm程序显示存档文件的索引,它可以显示目标文件的符号

nm libtest.a | more

如果是显示目标文件的符号:

nm a.o | more

在test.c中调用在libtest.a中的函数:

gcc -o test test.c libtest.a

动态库:动态库也叫共享库,系统存放的位置和静态库是一个地方,不通的是后缀名不一样,以”.so“结尾,如果一个程序使用动态库,则该程序本身不包含调用的函数代

码,只包含调用的线索,只是在程序需要调用时才去调用动态库。

1、创建共享库

创建文件hello.c,内容如下:

#include

void hello(void)

{

printf("Hello World\n");

}

用命令gcc -shared hello.c -o libhello.so编译为动态库。可以看到,当前目录下多了一个文件libhello.so。

2.编译共享库

查看文件

$ file libhello.so

libhello.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), not stripped

再编辑一个测试文件test.c,内容如下:

int

main()

{

hello();

return 0;

}


编译test.c

$ gcc test.c

/tmp/ccm7w6Mn.o: In function `main':

test.c:(.text+0x1d): undefined reference to `hello'

collect2: ld returned 1 exit status

链接时gcc找不到hello函数,编译失败:原因是hello在我们自己创建的库中

$ gcc test.c -lhello

/usr/lib/gcc/i686-pc-Linux-gnu/4.0.0/../../../../i686-pc-Linux-gnu/bin/ld: cannot find -lhello

collect2: ld returned 1 exit status

$ gcc test.c -lhello -L.

$

第一次编译直接编译,gcc默认会链接标准c库,但符号名hello解析不出来,故连接阶段通不过了。

现在用gcc test.c -lhello -L.已经编译成功了,默认输出为a.out。现在来试着运行一下:

$ ./a.out

./a.out: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory

虽然链接时链接器(dynamic linker)找到了动态库libhello.so,但动态加载器(dynamic loader, 一般是/lib/ld-Linux.so.2)却没找到。再来看看ldd的输出:

$ ldd a.out

Linux-gate.so.1 => (0xffffe000)

libhello.so => not found

libc.so.6 => /lib/libc.so.6 (0x40034000)

/lib/ld-Linux.so.2 (0x40000000)

Linux为我们提供了两种解决方法:

1.可以把当前路径加入 /etc/ld.so.conf中然后运行ldconfig,或者以当前路径为参数运行ldconfig(要有root权限才行)。

2.把当前路径加入环境变量LD_LIBRARY_PATH中

当然,如果你觉得不会引起混乱的话,可以直接把该库拷入/lib,/usr/lib/等位置(这样做也要有权限),这样链接器和加载器就都可以准确的找到该库了。

采用第二种方法:

$ export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

$ ldd a.out

Linux-gate.so.1 => (0xffffe000)

libhello.so => ./libhello.so (0x4001f000)

libc.so.6 => /lib/libc.so.6 (0x40036000)

/lib/ld-Linux.so.2 (0x40000000)

这样ld-Linux.so.2就可以找到libhello.so这个库了。

现在可以直接运行了:

$ ./a.out

Hello World
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: