http://blog.sina.com.cn/s/blog_602f87700100fc8t.html

libtool作用:

libtool 是一个通用库支持脚本(/usr/bin/libtool),将使用动态库的复杂性隐藏在统一、可移植的接口中。

可以在不同平台上创建并调用动态库,我们可以认为libtool是gcc的一个抽象,也就是说,它包装了gcc或者其他的任何编译器,用户无需知道细节, 只要告诉libtool说我需要要编译哪些库即可,并且,它只与libtool文件打交道,例如lo、la为后缀的文件。

libtool生成一个抽象的后缀名为la高层库libxx.la(其实是个文本文件),并将该库对其它库的依赖关系,都写在该la的文 件中。该文件中的dependency_libs记录该库依赖的所有库(其中有些是以.la文件的形式加入的);libdir则指出了库的安装位 置;library_names记录了共享库的名字;old_library记录了静态库的名字。

libtool使用方法:
1. 编译为一个object文件:

以BTX 为例:

源文件为:BTX.c. 头文件在 ../include/BTX.h

#libtool --mode=compile gcc -g -O -I../include -c BTX.c

用gcc编译一切正常:

mkdir .libs
gcc -g -O -I../include -c BTX.c  -fPIC -DPIC -o
.libs/BTX.o
gcc -g -O -I../include -c BTX.c -o BTX.o >/dev/null
2>&1

#libtool
--mode=compile mipsel_linux_gcc -g
-O -I../include -c BTX.c
显示需要--tag.

libtool支持多语言,以下是语言与tag的对应:

Language
name     
Tag name
C                 
CC
C++               
CXX
Java              
GCJ
Fortran
77        
F77
Windows Resource   RC

#libtool --mode=compile --tag=CC
mipsel-linux-gcc -g -I../include -c BTX.c

则正常了。

libtool: ignoring unknown tag
mipsel-linux-gcc
 mipsel-linux-gcc -g -I../include -c
BTX.c  -fPIC -DPIC -o .libs/BTX.o
 mipsel-linux-gcc -g -I../include -c BTX.c -o
BTX.o >/dev/null
2>&1

--mode:表示此次动作是 compile(编译)。

--tag: 如果是交叉编译器,则需要用--tag指定编译器。

gcc -g -O -I../include -c BTX.c: 很清楚。

然后libtool作了3件事:

1.创建.libs

2.编译了一个与位置无关(-fPIC)的obj文件。 放在 .lib中。

3.编译了一个普通obj文件在本地。

另外,它还创建了一个lo文件。用于描述上面2个obj文件和他们的位置。格式与la文件类似。

2. 将Object文件编译成可执行文件:

Object的描述文件为 *.lo文件,而libtool只与lo,la文件打交道,

#libtool --mode=link --tag=CC mipsel-linux-gcc main.lo
-o test

则利用先前编译出的main.lo编译出结果: 可执行文件test.

3. 编译一个库文件:

#libtool --mode=link --tag=CC gcc -g -O -o libBTX.la -rpath
/usr/local/lib BTX.lo

显示结果为:

rm -fr  .libs/libBTX.a .libs/libBTX.la
.libs/libBTX.lai .libs/libBTX.so .libs/libBTX.so.0
.libs/libBTX.so.0.0.0
gcc -shared 
.libs/BTX.o   -Wl,-soname
-Wl,libBTX.so.0 -o .libs/libBTX.so.0.0.0
(cd .libs && rm -f libBTX.so.0
&& ln -s libBTX.so.0.0.0
libBTX.so.0)
(cd .libs && rm -f libBTX.so
&& ln -s libBTX.so.0.0.0
libBTX.so)
ar cru .libs/libBTX.a  BTX.o
ranlib .libs/libBTX.a
creating libBTX.la
(cd .libs && rm -f libBTX.la
&& ln -s ../libBTX.la
libBTX.la)

link出两个共享库,一个是static,一个则是dynamic;需要注意的是,-rpath必须有才能产生dynamic库来,如果用-static,则只创建static库。

libBTX.la则指出静态库和动态库的名字和位置。

ranlib的作用:
在一些旧版本的系统上,ranlib负责把静态库转换为其他的某种格式,使得新的库能够更快的链接;现在ar命令已经包含了上述功能;

为了兼容性,在makefile中还是保留ranlib

#mipsel

#libtool --mode=link --tag=CC
mipsel-linux-gcc  -O -o libBTX.la -rpath
/usr/local/lib BTX.lo

当这样设置时,libtool会使用gcc,Sam 怎么也没法改正。所以只好临时在

/usr/bin/libtool中修改CC="mipsel-linux-gcc" 。这样就可以了。

mipsel-linux-gcc -shared 
.libs/BTX.o   -Wl,-soname
-Wl,libBTX.so.0 -o .libs/libBTX.so.0.0.0

但这里,Sam发现libBTX.la中并没有显示出libBTX.so依赖于libbluetooth.so。这不是没有达到使用libtool的目的吗?

于是Sam又作了修改:

#libtool --mode=link --tag=CC
mipsel-linux-gcc BTX.lo -rpath
/home/sam/work/current/BCM/BCM7405/ToolChain/crosstools_hf-linux-2.6.18.0_gcc-4.2-9ts_uclibc-nptl-0.9.29-20070423_20080702/mipsel-linux/lib
-o libBTX.la -lbluetooth

果然:在la文件中,可以看到dependency_libs='
-lbluetooth'

则在编译为可执行文件时,可以不用写 -lbluetooth

#libtool --mode=link --tag=CC mipsel-linux-gcc main.lo
libBTX.la -o test -lpthread

当然,也可以隐式的写:

#libtool --mode=link --tag=CC mipsel-linux-gcc main.lo
-lBTX -o test -lpthread

结果也正常:

mipsel-linux-gcc .libs/main.o -o .libs/test 
/home/sam/work/current/BCM/BCM7405/Bluetooth/Bluetooth_App/Second_New_Version/BTX_source/BTX_Release/src/.libs/libBTX.so
-lbluetooth -lpthread  
-Wl,--rpath
-Wl,/home/sam/work/current/BCM/BCM7405/ToolChain/crosstools_hf-linux-2.6.18.0_gcc-4.2-9ts_uclibc-nptl-0.9.29-20070423_20080702/mipsel-linux/lib

creating test

libtool 从libBTX.la中取出相应的东西。

4. 将object + so 编译出一个可执行文件:

#libtool --mode=link mipsel-linux-gcc -L../resource main.lo
libBTX.la -o BTX_Test -lbluetooth -lpthread

显示为:

mipsel-linux-gcc .libs/main.o -o
.libs/BTX_Test 
-L/home/sam/work/current/BCM/BCM7405/Bluetooth/Bluetooth_App/Second_New_Version/BTX_source/BTX_Release/resource
./.libs/libBTX.so -lbluetooth
-lpthread   -Wl,--rpath
-Wl,/usr/local/lib

背景知识:

背景知识1:libtool为何使用 -Wl,--rpath-link -Wl,

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

例如:我用常规办法生成libBTX.so. 则需要编译连接成可执行文件时,就没有libBTX.la文件。

这样,libBTX.so依赖于 libbluetooth.so这个信息就无人得知。

#libtool --mode=link --tag=CC mipsel-linux-gcc main.lo
-L./ -lBTX -o test -lpthread

则因为没有libBTX.la, 所以根本没有 依赖于
libbluetooth.so的信息。所以用到libbluetooth.so的东西全无法链接。

选项“-Wl,--rpath-link
–Wl,DIR”会把-rpath-link选项及路径信息传递给链接器。

相当于 --rpath-link /xxx/lib

背景知识2:

是因为如果在本地编译的情况下,link时,gcc在命令行中找不到一个库(比如上面的liba.so)依赖的其它库(比如libb.so),链接器会按照某种策略到某些路径下面去寻找需要的共享库:

1. 所有由'-rpath-link'选项指定的搜索路径.

2. 所有由'-rpath'指定的搜索路径.
'-rpath'跟'-rpath_link'的不同之处在于,由'-rpath'指定的路径被包含在可执行文件中,并在运行时使用,
而'-rpath-link'选项仅仅在连接时起作用.

3. 在一个ELF系统中, 如果'-rpath'和'rpath-link'选项没有被使用,
会搜索环境变量'LD_RUN_PATH'的内容.它也只对本地连接器起作用.

4. 在SunOS上, '-rpath'选项不使用, 只搜索所有由'-L'指定的目录.

5. 对于一个本地连接器,环境变量'LD_LIBRARY_PATH'的内容被搜索.

6. 对于一个本地ELF连接器,共享库中的`DT_RUNPATH'和`DT_RPATH'操作符会被需要它的共享库搜索.
如果'DT_RUNPATH'存在了, 那'DT_RPATH'就会被忽略.

7. 缺省目录, 常规的,如'/lib'和'/usr/lib'.

8. 对于ELF系统上的本地连接器, 如果文件'/etc/ld.so.conf'存在,
这个文件中有的目录会被搜索.

从以上可以看出,在使用本地工具链进行本地编译情况下,只要库存在于某个位置,gcc总能通过如上策略找到需要的共享库。但在交叉编译下,上述八种策略,可以使用的仅仅有两个:-rpath-link,-rpath。这两个选项在上述八种策略当中优先级最高,当指定这两个选项时,如果链接需要的共享库找不到,链接器会优先到这两个选项指定的路径下去搜索需要的共享库。通过上面的描述可以看到:-rpath指定的路径将被写到可执行文件中;-rpath-
link则不会
;我们当然不希望交叉编译情况下使用的路径信息被写进最终的可执行文件,所以我们选择使用选项-rpath-link。

 
 

libtool工具的使用的更多相关文章

  1. 源码编译安装libtool工具

    1. 获取源码 wget http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz tar xvf libtool-2.4.6.tar.gz -C ~ ...

  2. 安装性能测试工具:sysbench和使用apache的ab

    一.软件的用途,它主要包括以下几种方式的测试:1.cpu性能2.磁盘io性能3.调度程序性能4.内存分配及传输速度5.POSIX线程性能6.数据库性能(OLTP基准测试) 这个软件为什么找不到官网呢? ...

  3. 解决 free(): invalid pointer: 0x00000000019ff700 运行时报错(caffe)(libtool使用)

    编译成功,运行时报错: 在使用 pytorch or tensorflow or caffe 时,都可能存在这个问题: *** Error in `xxx': free(): invalid poin ...

  4. libtool的工作原理

    libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一.可移植的接口中:使用libtool的标准方法,可以在不同平台上创建并调用动态库.可以认为libtool是gcc的一个抽象,其包装了 ...

  5. sysbench基准测试工具

    一.简介SysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.当前功能允许测试的系统参数有:file I/O performance (文件I ...

  6. 系列篇|编译可在Android上运行的依赖库(一):glib库

    前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...

  7. CWMP开源代码研究2——easycwmp安装和学习

    声明:本文是对开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文所有笔记和代码可以到csdn下载:http://download.csdn.n ...

  8. 161230、利用代理中间件实现大规模Redis集群

    前面在<大规模互联网应用Redis架构要点>和<Redis官方集群方案 Redis Cluster>两篇文章中分别介绍了多Redis服务器集群的两种方式,它们是基于客户端sha ...

  9. Redis/SSDB+Twemproxy的配置与使用(Mac/Linux平台)

    对于redis而已,相信不少的后台开发人员一直都在使用,相比memcache而已,redis不仅可以作为key-value缓存使用,而且提供了丰富的数据结构如set.list.map等,能够实现很多复 ...

随机推荐

  1. React Native 系列(一)

    前言 本系列是基于React Native版本号0.44.3写的,最初学习React Native的时候,完全没有接触过React和JS,本文的目的是为了给那些JS和React小白提供一个快速入门,让 ...

  2. Lisp em SCU - 4490 (强大的map用法)

    Time Limit: 1000 MS Memory Limit: 131072 K Description There are two lists and they may be intersect ...

  3. BeautifulSoup解析库

    解析库 解析器 使用方法 优势 劣势 Python标准库 BeautifulSoup(html, 'html.parser') 速度适中,容错能力强 老版本python容错能力差 lxml HTML解 ...

  4. 【UOJ 34】 #34. 多项式乘法 (FFT)

    [分析] 这个只是用来放模板..[其实我还没完全懂的.. 迭代 代替 递归: #include<cstdio> #include<cstdlib> #include<cs ...

  5. SQL Server附加数据库提示“版本为661,无法打开,支持655版本……”

    在我们使用别人导出的数据库的时候,有时候我们会通过附加数据库的方法,把别人导出的数据库附加到我们的电脑中,这时,或许你会遇到这种问题,附加时,提示版本为XXX,无法打开,支持AAA版本. 这是怎么回事 ...

  6. bzoj 4097: [Usaco2013 dec]Vacation Planning

    4097: [Usaco2013 dec]Vacation Planning Description Air Bovinia is planning to connect the N farms (1 ...

  7. UITextField设置密文延时处理---仿QQ登录密码输入

    系统的UITextField输入的时候最后一个字符会有1-2s的效果展示, 效果如下: 为了解决这个问题, 可以用字符 "●" 替换, 替换后效果如下: 用到的是UITextFie ...

  8. SQL Server2008无法修改表结构?

    之前一直用SQL Server2005的数据库,最近升级到2008之后发现修改不了表结构,提示: 根据提示,取消“阻止保存要求重新创建表的更改”后就可以了. 具体操作:SQL Server Manag ...

  9. Redis-用思维导图二天搞定Redis用法。

    Redis整体面貌 Redis基本数据结构 1.String 1.1 数据结构 long len byte数组长度 long free 可用数组长度 char buff[] 数据内容 1.2 命令 键 ...

  10. apache&mod_wsgi&django部署多个项目

    今天做好了第二个django项目,但在部署时出了一点小问题,在此记录一下. 1.mod_wsgi 3.4已经支持了部署多个项目,只需在httpd.conf中进行如下配置: WSGIScriptAlia ...