o: 编译的目标文件
-X/S3f m'S H ] X0 a: 静态库,其实就是把若干o文件打了个包
k z3n o U V p R0 so: 动态链接库(共享库)中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 L&? ?,z4i&G&G&S V
r0^ m k z F5o"x C1c0 lo: 使用libtool编译出的目标文件,其实就是在o文件中添加了一些信息中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 H5b E @ C.` }
la: 使用libtool编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息
补充:libtool
1 libtool的工作原理
a x f&\ p,m z0 libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中;使用libtool的标准方法,可以在不同平台上创建并调用动态库。可以认为 libtool是gcc的一个抽象,其包装了gcc(或者其他的编译器),用户无需知道细节,只要告诉libtool需要编译哪些库即可,libtool 将处理库的依赖等细节。libtool只与后缀名为lo、la为的libtool文件打交道。
G8S I.A.t H s%W;X0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客2F J+X ` k u Y,l
libtool 主要的一个作用是在编译大型软件的过程中解决了库的依赖问题;将繁重的库依赖关系的维护工作承担下来,从而释放了程序员的人力资源。libtool提供统 一的接口,隐藏了不同平台间库的名称的差异等细节,生成一个抽象的后缀名为la高层库libxx.la(其实是个文本文件),并将该库对其它库的依赖关 系,都写在该la的文件中。该文件中的dependency_libs记录该库依赖的所有库(其中有些是以.la文件的形式加入的);libdir则指出 了库的安装位置;library_names记录了共享库的名字;old_library记录了静态库的名字。
V3T e#t b Q$A0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 k U f N&r G%d
当编译过程到link阶段的时候,如果有下面的命令:
#] t V T,C$Q9P0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 k a x `&o b$X
$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客$j)F(J$Z E C k9n
&P C U7r)~:Y0 libtool 会到/usr/lib路径下去寻找liba.la,然后从中读取实际的共享库的名字(library_names中记录了该名字,比如liba.so)和 路径(lib_dir中记录了,比如libdir=’/usr/lib’),返回诸如/usr/lib/liba.so的参数给激发出的gcc命令行。 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 H k,P7q U } u j B b
-] \&k y g0 如 果liba.so依赖于库/usr/lib/libb.so,则在liba.la中将会有dependency_libs=’-L/usr/lib -lb’或者dependency_libs=’/usr/lib/libb.la’的行,如果是前者,其将直接把“-L/usr/lib –lb”当作参数传给gcc命令行;如果是后者,libtool将从/usr/lib/libb.la中读取实际的libb.so的库名称和路径,然后组 合成参数“/usr/lib/libb.so”传递给gcc命令行。 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客+A6h;e4A ] [5z E/s
` s-m6d d1D N$T0 当要生成的文件是诸如libmylib.la的时候,比如:
u/G/} n } k0h(z O0
R q E { n x O9y:_0 $libtool --mode=link gcc -o libmylib.la -rpath /usr/lib –L/usr/lib –la 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 B#t O,b u+p v b#F%v
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客"q K"t,d*C2r @
其依赖的库的搜索基本类似,只是在这个时候会根据相应的规则生成相应的共享库和静态库。 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 |9e(P&g6?6N `/K w
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 N5@1f O P8y q$O J
注意:libtool在链接的时候只会涉及到后缀名为la的libtool文件;实际的库文件名称和库安装路径以及依赖关系是从该文件中读取的。
W.D j p ?-J9j S A Q0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 f4g3S ` n x!Q P c7f
2 为何使用 -Wl,--rpath-link -Wl,DIR? 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 o R B Y F
使用libtool解决编译问题看上去没什么问题:库的名称、路径、依赖都得到了很好的解决。但下结论不要那么着急,一个显而易见的问题就是:并不是所有的库都是用libtool编译的。
O:l P']'? b0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客&C V Q p Z'J k f
比如上面那个例子, 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 Y F n z0L r*\
4g"B j d ~ X5Z0 $libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 t Z0@9v e K n
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客2| i/O U5G.T J
如果liba.so不是使用libtool工具生成的,则libtool此时根本找不到liba.la文件(不存在该文件)。这种情况下,libtool只会把“–L/usr/lib –la”当作参数传递给gcc命令行。
'm$\2s.Q6?0
q g1l f e$l5G0 考 虑以下情况:要从myprog.o文件编译生成myprog,其依赖于库liba.so(使用libtool生成),liba.so又依赖于 libb.so(libb.so的生成不使用libtool),而且由于某种原因,a对b的依赖并没有写入到liba.la中,那么如果用以下命令编译:
Y0Q5K g,_ g0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客-N p7R q3C3P7M${ O
$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la
d0D ? J k'Q0
3\$o u/B*o4] C ~0 激发出的gcc命令行类似于下面: 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 S2G b8? T |
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 G-F H ]-H8a l ] ? H ]
gcc –o myprog /usr/lib/liba.so
U {"V `0d2N s0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客;o6c Z B$W r i
由于liba.so依赖于libb.so(这种依赖可以用readelf读liba.so的ELF文件看到),而上面的命令行中,并没有出现libb.so,于是,可能会出现问题。
)];V't c-_ H O b0
} l ~6j M0 说“可能”,是因为如果在本地编译的情况下,gcc在命令行中找不到一个库(比如上面的liba.so)依赖的其它库(比如libb.so),链接器会按照某种策略到某些路径下面去寻找需要的共享库:
*H N ` q-| K0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 Q @ F x {-u4g S a F
1. 所有由'-rpath-link'选项指定的搜索路径. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客)b8d G b r%M(} B0Y
%r"[ I,x#q }0 2. 所有由'-rpath'指定的搜索路径. '-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径被包含在可执行文件中,并在运行时使用, 而'-rpath-link'选项仅仅在连接时起作用.
_ b+x2M {2n0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客)| z%o q3] h `5N
3. 在一个ELF系统中, 如果'-rpath'和'rpath-link'选项没有被使用, 会搜索环境变量'LD_RUN_PATH'的内容.它也只对本地连接器起作用. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 [ u"E H1U b0a-L
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 B A7m f.s!c,l a
4. 在SunOS上, '-rpath'选项不使用, 只搜索所有由'-L'指定的目录. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 { i m w;A
6E @*I ^ `;@0 5. 对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客4n!K7_ _6Z6?
,{ a8| C U'\ } O U:T0 6. 对于一个本地ELF连接器,共享库中的`DT_RUNPATH'和`DT_RPATH'操作符会被需要它的共享库搜索. 如果'DT_RUNPATH'存在了, 那'DT_RPATH'就会被忽略. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 Q l!E o `0y C ^
5s D8S C r2^ y0 7. 缺省目录, 常规的,如'/lib'和'/usr/lib'.
~6T1T l5S,w0
:_ w c l P$b0e$E$y:I0 8. 对于ELF系统上的本地连接器, 如果文件'/etc/ld.so.conf'存在, 这个文件中有的目录会被搜索. 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客4V ]*G \1y6N9g g;D \+P
中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客+\&[ l o U I }
从 以上可以看出,在使用本地工具链进行本地编译情况下,只要库存在于某个位置,gcc总能通过如上策略找到需要的共享库。但在交叉编译下,上述八种策略,可 以使用的仅仅有两个:-rpath-link,-rpath。这两个选项在上述八种策略当中优先级最高,当指定这两个选项时,如果链接需要的共享库找不 到,链接器会优先到这两个选项指定的路径下去搜索需要的共享库。通过上面的描述可以看到:-rpath指定的路径将被写到可执行文件中;-rpath- link则不会;我们当然不希望交叉编译情况下使用的路径信息被写进最终的可执行文件,所以我们选择使用选项-rpath-link。
e l)X o [ I a `0
\8A"U-F*p R6A0 gcc的选项“-Wl,--rpath-link –Wl,DIR”会把-rpath-link选项及路径信息传递给链接器。回到上面那个例子,如果命令行中没有出现libb.so,但gcc指定了“- Wl,--rpath-link –Wl,DIR”,则链接器找不到libb.so的时候,会首先到后面-rpath-link指定的路径去寻找其依赖的库。此处我们使用的编译命令的示例 是使用unicore平台的工具链。 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 G w+t D Q
d a.S+b E h0 $ unicore32-linux-gcc –o myprog /usr/lib/liba.so \ 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客%h+_ `;a k
g(w O ]'M ` V0 -Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/lib
9A#a @ N0w Y'a0
,o M l y k { x n'W0 这样,编译器会首先到“/home/UNITY_float/install/usr/lib”下面去搜索libb.so
"@ w M ` G | K!^!a A ]0i-o0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客!x3q F A b#l h9J:v
libtool如何把选项“-Wl,--rpath-link –Wl,DIR”传递给gcc?libtool中有一个变量“hardcode_libdir_flag_spec”,该变量本来是传递“-rpath” 选项的,但我们可以修改它,添加我们需要的路径,传递给unicore32-linux-gcc。 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客/c | E6@ ? v h A a i
5~ ? @)F!g&y ? V N0 “hardcode_libdir_flag_spec”原来的定义如下: 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 w l _/P/}$i ^!Z
5?0~ v)q Y l0 hardcode_libdir_flag_spec="\${wl}--rpath \${wl}\$libdir"
u3T Y d B y)V#p k0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 E9c*[)M n W
我们修改后的定义如下: 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 h9q p H5W W&B/Z K a
F Y ] n m0 hardcode_libdir_flag_spec="\${wl}—rpath-link \${wl}\$libdir \
"l V1q;} W x+K _ _)L Q A)?0 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客 c8~1~ [ q']0H l N i
-Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/lib \ 中国电子顶级开发网----最专业的电子论坛、最专业的电子工程师博客$y&v"D6k)W2F ^+~ u
m F;k5_ e8\ g0F0 -Wl,--rpath-link -Wl,/home/UNITY_float/install/usr/X11R6/lib "