libtool工具的使用
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工具的使用的更多相关文章
- 源码编译安装libtool工具
1. 获取源码 wget http://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz tar xvf libtool-2.4.6.tar.gz -C ~ ...
- 安装性能测试工具:sysbench和使用apache的ab
一.软件的用途,它主要包括以下几种方式的测试:1.cpu性能2.磁盘io性能3.调度程序性能4.内存分配及传输速度5.POSIX线程性能6.数据库性能(OLTP基准测试) 这个软件为什么找不到官网呢? ...
- 解决 free(): invalid pointer: 0x00000000019ff700 运行时报错(caffe)(libtool使用)
编译成功,运行时报错: 在使用 pytorch or tensorflow or caffe 时,都可能存在这个问题: *** Error in `xxx': free(): invalid poin ...
- libtool的工作原理
libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一.可移植的接口中:使用libtool的标准方法,可以在不同平台上创建并调用动态库.可以认为libtool是gcc的一个抽象,其包装了 ...
- sysbench基准测试工具
一.简介SysBench是一个模块化的.跨平台.多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况.当前功能允许测试的系统参数有:file I/O performance (文件I ...
- 系列篇|编译可在Android上运行的依赖库(一):glib库
前言 这是系列文章,它们由<编译可在Android上运行的glib库>及其他4篇文章组成,这4篇文章在“编译依赖库”一节中列出.由于glib库依赖于其他第三方库,所以需要先将依赖的第三方库 ...
- CWMP开源代码研究2——easycwmp安装和学习
声明:本文是对开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文所有笔记和代码可以到csdn下载:http://download.csdn.n ...
- 161230、利用代理中间件实现大规模Redis集群
前面在<大规模互联网应用Redis架构要点>和<Redis官方集群方案 Redis Cluster>两篇文章中分别介绍了多Redis服务器集群的两种方式,它们是基于客户端sha ...
- Redis/SSDB+Twemproxy的配置与使用(Mac/Linux平台)
对于redis而已,相信不少的后台开发人员一直都在使用,相比memcache而已,redis不仅可以作为key-value缓存使用,而且提供了丰富的数据结构如set.list.map等,能够实现很多复 ...
随机推荐
- Python Socket多线程并发
1.SocketServer模块编写的TCP服务器端代码 Socketserver原理图 服务端: import SocketServer #导入SocketServer,多线程并发由此类实现 cla ...
- java 线程 wait join sleep yield notify notifyall synchronized
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 休息方法 : 在指定时间内 让该线程 暂停, 不会释放 锁标志. 等待方法: 让 该 线 ...
- [BZOJ4826][HNOI2017]影魔(主席树)
4826: [Hnoi2017]影魔 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 669 Solved: 384[Submit][Status][ ...
- [BZOJ4196][NOI2015]软件包管理器(树链剖分)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2166 Solved: 1253[Submit][Sta ...
- padding Oracle attack(填充Oracle攻击)
最近学习到一种老式的漏洞,一种基于填充字节的漏洞.就想记录下来,早在2010年的blackhat大会上,就介绍了padding Oracle漏洞,并公布了ASP.NET存在该漏洞.2011年又被评选为 ...
- 03-MyBatis主从实现代码读写分离应用以及实现
建立目录结构:
- python学习一月总结_汇总大牛们的思想_值得收藏
''' 下面是我汇总的我学习一个月python(version:3.3.2)的所有笔记 你可以访问:http://www.python.org获取更多信息 你也可以访问:http://www.cnbl ...
- 套题:Codeforces Round #194 (Div. 1) (2/5)
A. Secrets http://www.cnblogs.com/qscqesze/p/4528529.html B. Chips http://www.cnblogs.com/qscqesze/p ...
- linux基础命令学习 (八)磁盘空间
一.df linux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.于du不同的是,du是面向文件的命令,只计算被文件占用的空间.不计算文件系统metadata 占用的空间.d ...
- HDU 4704 Sum (2013多校10,1009题)
Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submi ...