libtool简介

    xiaoxiao2021-03-25  158

    一. 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: 动态链接库(共享库)

    转载请注明原文地址: https://ju.6miu.com/read-1501.html

    最新回复(0)