2010-9-4
Kagula
文中涉及的命令在Ubuntu8.04.1中测试通过,本文的目的是为了以后要用的时候,只要看一下本文就马上能回忆起这此命令怎么用。
生成目标文件
#gcc –c <XXX.cpp>
可以有多个cpp文件
编译静态库
#ar cr <libXXX.a> <XXX.o>
可以有多个o文件(目标文件)
静态库名的命名方式应该是libXXX.a 其中XXX是库的名字。
编译成动态库
# gcc -shared -fPCI -o libmyhello.so hello.o
可以有多个o文件,若考虑到同个库有多个版本,参考如下命令
#gcc -shared -Wl,-soname,libhello.so.1 -o libhello.so.1.0 hello.o
另外再建立两个符号连接:
#ln -s libhello.so.1.0 libhello.so.1
#ln -s libhello.so.1 libhello.so 这样一个libhello的动态连接库就生成了。最重要的是传gcc -shared 参数使其生成是动态库而不是普通执行程序。
-Wl 表示后面的参数也就是-soname,libhello.so.1直接传给连接器ld进行处理。实际上,每一个库都有一个soname,当连接器发现它正 在查找的程序库中有这样一个名称,连接器便会将soname嵌入连结中的二进制文件内,而不是它正在运行的实际文件名,在程序执行期间,程序会查找拥有 soname名字的文件,而不是库的文件名,换句话说,soname是库的区分标志。 这样做的目的主要是允许系统中多个版本的库文件共存,习惯上在命名库文件的时候通常与soname相同 libxxxx.so.major.minor 其中,xxxx是库的名字,major是主版本号,minor 是次版本号
使用静态库
#gcc –o <输出文件名> <目标文件名> <静态库文件名>
使用动态库
#gcc <源文件名> -l<动态库文件名> -L<动态库所在路径>
例如:
#gcc test.c -lhello -L.
把源test.c编译为a.out可执行文件,test.c所需要的函数在libhello.so文件中定义,libhello.so文件在当前目录。
直接执行a.out提示找不到动态库文件,这时需要修改当前的动态库搜索路径。
如下:
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
再执行a.out,测试文件运行成功。
常用命令
[1]查看当前文件依赖于哪些库
#ldd <库文件或可执行文件>
[2]查看文件类型
#file <可执行文件名>
[3]查看库中符号
#nm <库文件名称>
nm列出的符号有很多,常见的有 三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的“弱 态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。
通常和grep命令配合使用
可执行程序在执行的时候如何定位共享库文件
采用以下顺序
[搜索elf文件的 DT_RPATH段]=>
[ 环境变量LD_LIBRARY_PATH]=>
[/etc/ld.so.cache文件列表]=>
[/lib/,/usr/lib目录]
如何让执行程序顺利找到动态库
[方法一]把库文件copy到/usr/lib目录或/lib目录。
[方法二]修改当前终端的LD_LIBRARY_PATH环境变量,例如:
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/WhereIsMyLibLocation
此方法只能临时改变搜索路径
[方法三]修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。
常用参数(速记)
-I<头文件路径> -L<库文件路径> -i<头文件> -l<库文件名>
-Wall 尽可能多的警告信息
-o 输出可执行文件名(起到重命名输出文件名的作用)
比如说用gcc编译C++文件需要加上-lstdc++参数,让编译器去找libstdc++.a静态库文件。