libtool简介

一. libtool的工作原理 
libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中;使用libtool的标准方法,可以在不同平台上创建并调用动态库。可以认为libtool是gcc的一个抽象,其包装了gcc(或者其他的编译器),用户无需知道细节,只要告诉libtool需要编译哪些库即可,libtool将处理库的依赖等细节。libtool只与后缀名为lo、la的libtool文件打交道。

libtool主要的一个作用是在编译大型软件的过程中解决了库的依赖问题;将繁重的库依赖关系的维护工作承担下来,从而释放了程序员的人力资源。libtool提供统一的接口,隐藏了不同平台间库的名称的差异等细节,生成一个抽象的后缀名为la高层库libxx.la(其实是个文本文件),并将该库对其它库的依赖关系,都写在该la的文件中。该文件中的dependency_libs记录该库依赖的所有库(其中有些是以.la文件的形式加入的);libdir则指出了库的安装位置;library_names记录了共享库的名字;old_library记录了静态库的名字。 

当编译过程到link阶段的时候,如果有下面的命令: 

$libtool --mode=link gcc -o myprog -rpath /usr/lib –L/usr/lib –la 

libtool会到/usr/lib路径下去寻找liba.la,然后从中读取实际的共享库的名字(library_names中记录了该名字,比如liba.so)和路径(lib_dir中记录了,比如libdir=’/usr/lib’),返回诸如/usr/lib/liba.so的参数给激发出的gcc命令行。 

如果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命令行。 

当要生成的文件是诸如libmylib.la的时候,比如: 

$libtool --mode=link gcc -o libmylib.la -rpath /usr/lib –L/usr/lib –la 

其依赖的库的搜索基本类似,只是在这个时候会根据相应的规则生成相应的共享库和静态库。 

注意:libtool在链接的时候只会涉及到后缀名为la的libtool文件;实际的库文件名称和库安装路径以及依赖关系是从该文件中读取的。 

2 为何使用 -Wl,--rpath-link -Wl,DIR? 
使用libtool解决编译问题看上去没什么问题:库的名称、路径、依赖都得到了很好的解决。但下结论不要那么着急,一个显而易见的问题就是:并不是所有的库都是用libtool编译的。 

 

libtool常见于autoconf/automake,单独用的例子很少。 
 
二. libtool的使用
1.Creating object files
# libtool --mode=compile gcc -g -O -c foo.c
 gcc -g -O -c foo.c  -fPIC -DPIC -o.libs/foo.o
 gcc -g -O -c foo.c -o foo.o >/dev/null2>&1
# libtool --mode=compile gcc -g -O -c hello.c
 gcc -g -O -c hello.c  -fPIC -DPIC -o.libs/hello.o
 gcc -g -O -c hello.c -o hello.o>/dev/null 2>&1
【说明】libtool编译出两个版本的relocatableobject,一个是fPIC(位置无关的),放在.libs目录下;另一个则是普通的,放在本地。
 
2.linking shared library
# libtool --mode=link --tag=CC gcc -g -O -olibhello.la -rpath /usr/local/lib foo.lo
 rm -fr  .libs/libhello.a.libs/libhello.la .libs/libhello.lai .libs/libhello.so libs/libhello.so.0.libs/libhello.so.0.0.0
 gcc -shared  .libs/foo.o  -Wl,-soname -Wl,libhello.so.0 -o .libs/libhello.so.0.0.0
 (cd .libs && rm -f libhello.so.0&& ln -s libhello.so.0.0.0 libhello.so.0)
 (cd .libs && rm -f libhello.so &&ln -s libhello.so.0.0.0 libhello.so)
 ar cru .libs/libhello.a  foo.o
 ranlib .libs/libhello.a
 creating libhello.la
 (cd .libs && rm -f libhello.la&& ln -s ../libhello.la libhello.la)
【说明】link出两个共享库,一个是static,一个则是dynamic;需要注意的是,-rpath必须有才能产生dynamic库来,如果用-static,则只创建static库。
 
ranlib的作用:
On some older UNIX systems, ranlib added a tableof contents to archive libraries, which converted each archive to a form thatcould be linked more rapidly. This is no longer needed as the ar commandautomatically provides all the functionality ranlib used to provide.
在一些旧版本的系统上,ranlib负责把静态库转换为其他的某种格式,使得新的库能够更快的链接;现在ar命令已经包含了上述功能;
This command is provided as a convenience forsoftware developers who need to maintain Makefiles that are portable across avariety of operating systems.
为了兼容性,在makefile中还是保留ranlib
 
3.install shared library
libtool --mode=install cp libhello.la/usr/local/lib/libhello.la
libtool --mode=install install -c libhello.la/usr/local/lib/libhello.la
两个命令都可以,效果相同
 
4.linking executable file
# libtool --mode=link gcc -g -O -o hello hello.lo-rpath /usr/local/lib libhello.la
 gcc -g -O -o .libs/hello .libs/hello.o ./.libs/libhello.so
 creating hello
 -rpath项负责添加运行时库路径,否则只能手工修改LD_LIBRARY_PATH环境变量了。
 验证一下:
# ldd .libs/hello
       linux-gate.so.1 =>  (0xffffe000)
       libhello.so.0 => /usr/local/lib/libhello.so.0 (0x40019000)
       libc.so.6 => /lib/tls/libc.so.6 (0x40031000)
       /lib/ld-linux.so.2 (0x40000000)
 
5.install executablefile       
#libtool --mode=install cp hello /usr/local/bin/hello
安装可执行程序。
 
6.运行
libtool --mode=execute hello
或直接运行hello
注意:此处hello已经安装在/usr/local/bin下了,可以用which hello来查看
 
【附】源码
foo.c
#include <stdio.h>
char msg[128]="Hello world";
void print()
{
    printf("%s/n",msg);
}
 
hello.c:
#include <stdio.h>
extern char msg[128];
extern void print();
int main()
{
    print();
}
 
Makefile:
LO_OBJS = foo.lo
PACKAGE_VERSION = 1:1:1
LIBDIR=/usr/local/lib
BINDIR=/usr/local/bin
 
all : hello
 
install : libhello.la hello
  libtool --mode=install install -clibhello.la
 
${LIBDIR}/libhello.la
  libtool --mode=install cp hello${BINDIR}/hello
 
uninstall : ${LIBDIR}/libhello.la ${BINDIR}/hello
  libtool --mode=uninstall /bin/rm${LIBDIR}/libhello.la
  libtool --mode=uninstall /bin/rm${BINDIR}/hello
 
hello : libhello.la hello.o
  libtool --mode=install install -clibhello.la
 
${LIBDIR}/libhello.la
  libtool --mode=link gcc -g -O -o hellohello.o -rpath ${LIBDIR} libhello.la
 
libhello.la : $(LO_OBJS)
   libtool  --mode=link --tag=CCgcc -g -O -o libhello.la
 
$(LO_OBJS) -rpath ${LIBDIR} ${PACKAGE_VERSION}
 
foo.lo : foo.c
   libtool --mode=compile gcc -g -O -cfoo.c
 
hello.lo : hello.c
   libtool --mode=compile gcc -g -O -chello.c
 
clean :
  rm -f lib*.a *~ *core *.lo *.o *.la hello
  rm -rf .libs
 
这样,用户可以用make编译,makeinstall/uninstall安装/卸载,makeclean清除编译临时文件,安装成功后,可以直接执行hello,不必指明路径也不必再另设环境变量LD_LIBRARY_PATH,非常方便! 


lo: 使用libtool编译出的目标文件,其实就是在o文件中添加了一些信息
la: 使用libtool编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息

 

o: 编译的目标文件
a: 静态库,其实就是把若干o文件打了个包
so: 动态链接库(共享库)


  • 2
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值