- 浏览: 16558083 次
- 性别:
- 来自: 济南
最新评论
-
wu1236:
ef0793cd94337324b6fefc4c9474af5 ...
Android ApiDemos示例解析(87):Media->MediaPlayer -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
本博客文章都为转载,没有任何版权! -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
VPLEX - EMC的RAC -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
qTip2 Show -
77219634:
0127bf2236bee4dd1f632ce430f1af1 ...
SecureCRT中文乱码、复制粘贴乱码解决办法(修改版)
在不同的系统中建立动态链接库的方法有很大的差别,这主要是因为每个系统对动态链接库的看法和实现并不相同,以及编译器对动态链接库支持的选 项也不太一样。对于开发人员,如果尝试将使用动态库的软件在这些系统之间移植,需要参考枯涩难懂的系统手册,以及修改相应的 Makefile,这一工作是乏味的,并且具有一定的难度。
使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。它通过一个称为 Libtool 库的抽象,隐藏了不同系统之间的差异,给开发人员提供了一致的的接口。对于大部分情况,开发人员甚至不用去查看相应的系统手册,只需要掌握 GNU Libtool 的用法就可以了。并且,使用 Libtool 的 Makefile 也只需要编写一次就可以在多个系统上使用。
Libtool 库可以是一个静态链接库,可以是一个动态链接库,也可以同时包含两者。在这篇文档中,我们围绕 Libtool 库的建立和使用,只是在适当的说明 Libtool 库和系统动态或者静态链接库之间的映射关系。
虽然 Libtool 隐藏了在不同平台创建链接库的复杂性,但其最终还是需要底层系统对链接库的支持,它不能超越系统的限制,例如,Libtool 并不能在不支持动态链接库的系统中创建出动态链接库。
这一节以实例来说明如何使用 Libtool 从源代码创建最终链接库以及执行程序的完整步骤,这是软件开发过程中经常使用的内容,包括 :
- 创建 Libtool 对象文件 ;
- 创建 Libtool 库;
- 安装 Libtool 库 ;
- 使用 Libtool 库 ;
- 卸载 Libtool 库 ;
首先需要准备一个源文件 compress.c,代码如下:
|
这个文件实现了一个函数 compress_file() ,它接收一个文件名作为参数,然后对文件进行压缩,生成一个 .z 结 尾的压缩文件。在这个文件中使用了 compress() 函数,这个函数是有由 libz 提供的。
从源文件建立 Libtool 库需要经过两个步骤,先建立 Libtool 对象文件,再建立 Libtool 库。
如果使用传统的方式,建立对象文件通常使用下面的命令 :
$ gcc -c compress.c |
使用 Libtool 则使用下面的命令 :
$ libtool --mode=compile gcc -c foo.c |
可以看到,使用 Libtool 只需要将“传统”的命令 (gcc -c foo.c ) 作为参数传递给 Libtool 即可。
在上面的命令中,libtool 使用 compile 模式 (--mode=compile 选项 ),这是建立对象文件的模式,Libtool 还有其它的模式,后面将介绍。
上面的命令输出如下 :
mkdir .libs |
它建立了两个文件,一个是 .libs/compress.o,在建立这个文件时,Libtool 自动插入了 -fPIC
和 -DPIC
选项,告诉编译器生成位置独立的代码,之后将用这个文件来建立动态链接库。生成第二个文件 compress
.o
没 有添加额外的选项,它准备用来建立静态链接库。
除了上面的两个文件之外,Libtool 还建立了一个文件 compress.lo ,这个文件就是 Libtool 对象文件,实际上也就是一个文本文件,里面记录了建立动态链接库和静态链接库分别所需要的真实文件名称,后面 Libtool 将使用这个文件而不是直接的使用 .libs/compress.o 和 compress.o。
用下面的命令建立 Libtool 库 :
$ libtool --mode=link gcc -o libcompress.la compress.lo -rpath /tmp -lz |
注意这里使用 compress.lo 作为输入文件,并且告诉 Libtool 生成的目标文件为 libcompress.la ,.la 是 Libtool 的库文件后缀。
-rpath 选项告诉 Libtool 这个库将被安装到什么地方,如果省略了 -rpath 选项,那 么不会生成动态链接库。
因为我们的库中使用了 libz 提供的 compress 函数,所以也提供了 -lz 选项,Libtool 会记住这个依赖关系,后续在使用我们的库时自动的将依赖的库链接进来。
上面的命令输出如下 :
gcc -shared .libs/compress.o -lz -Wl,-soname -Wl,libcompress.so.0 |
可以看到,Libtool 自动的插入了建立动态链接库需要的编译选项 -shared 。并且,它也建立了静态链接库 .libs/libcompress.a,后面我们将会介绍如何控制 Libtool 只建立需要的库。
你可能会奇怪为什么建立的动态链接库有 .0 和 .0.0.0 这样的后缀,这里先不用理会它,后面在介绍 Libtool 库版本信息时将会解释这点。
值得注意的是,Libtool 希望后续使用 libcompress.la 文件而不是直接使用 libcompress.a 和 libcompress.so 文件,如果你这样做,虽然可以,但会破坏 Libtool 库的可移植性。
如果打算发布建立好的 Libtool 库,可以使用下面的命令安装它 :
$ libtool --mode=install install -c libcompress.la /tmp |
我们需要告诉 Libtool 使用的安装命令,Libtool 支持 install 和 cp,这里使用的是 install。
虽然前面我们在建立库时,通过 -rpath 选项指定了库准备安装的路径 (/tmp),但是这里我们还得要提供安装路径。请确保它们一致。
这个命令的输出如下 :
install .libs/libcompress.so.0.0.0 /tmp/libcompress.so.0.0.0 |
可以看到它安装了真实的动态链接库和静态链接库,同时也安装了 Libtool 库文件 libcompress.la,这个文件可以被后续的 Libtool 命令使用。
在安装完成之后,可能还需要做一些配置才能正确使用,Libtool 的 finish 模式可以在这方面给我们一些提示 :
$ libtool -n --mode=finish /tmp |
这个命令的输出有点长,所以不在这里列出,如果不能正常的使用安装好的库,请运行这个命令。
要在应用程序中使用前面创建的 Libtool 库很简单,准备一个源文件 main.c,它将使用 libcompress.la 库中定义的函数,代码如下 :
|
我们还是要先为 main.c 建立 Libtool 对象文件,这和前面的方法一样 :
$ libtool --mode=compile gcc -c main.c |
|
我们也可以直接使用 libcompress.a 或者 libcompress.so,但是使用 Libtool 更加简单,因为它会将帮助你解决依赖关系,例如我们的 libcompress 依赖 libz。
上面命令的输出如下 :
gcc -o main .libs/main.o /tmp/libcompress.so -lz |
这里,Libtool 自动选择链接动态链接库,并且加上了运行时需要的 --rpath 选项,以及依赖的库 -lz。
如果要使用静态链接库,只需要加上 -static-libtool-libs 选项即可,如下 :
$ libtool --mode=link gcc -o main main.lo /tmp/libcompress.la -static-libtool-libs |
这个命令的输出如下 :
gcc -o main .libs/main.o /tmp/libcompress.a -lz |
也可以使用还没有安装的库,这和使用安装好的库几乎相同,只是指定的输入文件位置不一样,假如我们在同一个目录中开发 compress.c 和 main.c,那么使用下面的命令 :
$ libtool --mode=link gcc -o main main.lo ./libcompress.la |
和使用安装的库不一样,这个时候建立的 main 程序只是一个封装脚本,如果你直接执行它不会有什么问题,但是如果你想调试它,例如 :
$ gdb main |
gdb 会报怨 main 不是可执行格式,不能接受。这个时候我们需要使用 Libtool 的执行模式,使用下面的命令调试程序 :
$ libtool --mode=execute gdb main |
使用下面的命令可以卸载安装的库 :
$ libtool --mode=uninstall rm /tmp/libcompress.la |
这个命令的输出如下 :
rm /tmp/libcompress.la /tmp/libcompress.so.0.0.0 /tmp/libcompress.so.0 |
这将删除所有安装的库文件。
这一节将对 Libtool 进行更加全面的描述,包括下面的内容 :
- 创建可动态加载模块 ;
- 禁止创建动态或者静态链接库 ;
- Libtool 命令模式 ;
- 库版本信息 ;
有些高级的软件系统在建立时不需要与特定的库链接,而在运行时可以动态加载符合规范的库,来提供额外的功能,这通常称为插件系统。
可动态加载的库和通常的库有一些区别,它们可以通过 dlopen () 打开,并且可以通过 dlsym () 查询它输出的符号。
使用 Libtool 可以很容易的建立这样的库,还是以前面的 compress.c 为例,我们可以通过这样的命令建立一个可动态加载模块 :
$ libtool --mode=link gcc -o compress.la compress.lo -rpath /tmp |
这里添加了额外的两个参数,-module 告诉 Libtool 建立一个可动态加载的模块,-avoid-version 告 诉 Libtool 不要添加版本号。
在 UNIX/Linux 系统中,库通常以 lib 作为前缀,可在上面我们指定的输出文件为 compress.la 而 不是 libcompress.la,这也是可动态加载模块的一个特征,它不需要遵循通常的库命名规则。
在实际应用中,可动态加载模块通常会使用主程序提供的一些函数,为了满足动态模块的需求,在编译主程序时,需要添加 -export-dynamic 选 项。
大部分情况下,Libtool 都配置成同时创建动态链接库和静态链接库。可以通过下面的命令查看 Libtool 的当前配置 :
$ libtool – features |
它的输出如下 :
host: i686-pc-linux-gnu |
可是有时侯,只想创建动态链接库或者只想创建静态链接库,这需要修改 Libtool 自身。后面介绍 Libtool 结合 Autoconf 和 Automake 使用时,将有更加简单的办法。
Libtool 自身是一个安装在 /usr/bin 目录下的 Shell 脚本,为了修改它,我们需要将它复制到一个有修改权限的目录,然后找到下面的两行 :
52 # Whether or not to build shared libraries. |
将 yes 改为 no。之后用这个修改过的 libtool 就不会创建动态链接库。
55 # Whether or not to build static libraries. |
将 yes 改为 no。之后用这个修改过的 libtool 就不会创建静态链接库。
在前面,我们已经用到了 Libtool 的大部分命令模式,每个命令模式用于不同的阶段,Libtool 根据当前的命令模式添加需要的编译器选项。
Libtool 支持下面的几个命令模式 :
- 编译模式 ;
- 连接模式 ;
- 安装模式 ;
- 完成模式 ;
- 卸载模式 ;
- 执行模式 ;
- 清除模式 ;
每个命令模式对应开发中的不同阶段,但并不是在每个项目中都需要使用上面所有的模式,例如一个不需要安装的库就不需要安装和卸载模式。
$ libtool --mode=compile gcc -c src.c |
$ libtool --mode=link gcc -o library.la src.lo -rpath /usr/local/lib |
安 装模式用于安装 Libtool 库或者执行程序。它的第一个参数必须是 install 或者 cp,之后是要安装的文件以及目标路径。
$ libtool --mode=install install -c library.la /usr/local/lib |
完 成模式是在安装完 Libtool 库之后,在使用之前进行适当的配置。finish 模式需要一个参数,即 Libtool 库的安装路径。
$ libtool --mode=finish /usr/local/lib |
卸 载模式用于卸载已经安装的 Libtool 库或者执行程序。
$ libtool --mode=uninstall rm /usr/local/lib/library.la |
执 行模式用来执行应用程序,它在启动应用程序之前自动的设置好库的路径。
$ libtool --mode=execute gdb program |
清 除模式和卸载模式差不多,只是它用来清除开发过程中的中间文件。
$ libtool --mode=clean rm library.la |
和应用程序一样,库也需要不断的升级,考虑一个第三方应用程序使用了我们之前发布的 libcompress。现在我们对 libcompress 的性能进行了优化,并且提供了新的接口,所以我们又发布了这个新版本。
这引入了几个问题,如果以前的应用程序采用静态方式链接,那么如果它想使用新库的功能,就必须用新库重新链接应用程序。如果是采用动态链接方 式,那么新库安装后,应用程序应该使用新库还是旧库呢?并且,如何避免新库和旧库之间的冲突呢?
库版本号可以解决上述这些问题,一个动态链接库有一个版本号,它在链接时硬编码到动态链接库中,当一个应用程序链接动态链接库时,它也存储了 链接库的版本信息,动态加载器 ( 如 ld-linux.so.2 ) 可以在程序启动时正确的加载版本匹配的库。
用 ldd 命令可以查看应用程序使用的动态链接库以及它们的版本信息 :
$ ldd .libs/lt-main |
我们需要用 .libs/lt-main 作为输入文件,当前目录下的 main 只是一个封装脚本。从上面的输出可以看到,main 程序依赖 libcompress.so 的版本 0。
库接 口是 应用程序可以和库交流的入口,常用的库接口包括 :
当然 还有其它的接口。在设计和实现库时,应该考虑尽量在将来减少库接口的改变。
通 常一个库有两个版本号,一个主版本号,一个次版本号,主版本号指示接口的改变,次版本号指示性能增强或者错误修复。但不是每个系统都是如此。
在 前面的例子中我们可以看到,为动态链接库 libcompress.so.0.0.0 建立了两个符号链接 :
其 中 libcompress.so 是供链接器 ( 例如 ld) 使用的,它应该指向当前系统中 libcompress 的最新版本,这样新程序总是可以链接最新的库版本。
每个系统的库版本机制并不一样,Libtool 通过一种抽象的版本机制,最终在创建库时映射到具体的系统版本机制。
- current : 表示当前库输出的接口的数量 ;
- revision : 表示当前库输出接口的修改次数 ;
- age : 表示当前库支持先前的库接口的数量,例如 age 为 2,表示它可以和支持当前库接口的执行文件,或者支持前面两个库接口的执行文件进行链接。所以 age 应该总是小于或者等于 current 。
Libtool 的库版本通过参数 -version-info current:revision:age 指定,例如下面的例子 :
$ libtool --mode=link gcc -l libcompress.la -version-info 0:1:0 |
注意,应该尽可能少的更新库版本号,尤其是不能强行将库版本号和软件发行号保持一致,下面是更新库版本号的几个策略 :
- 如果修改了库的源代码,那么应该增加 revision 。 这是当前接口的新的修订版本。
- 如果改变了接口,应该增加 current ,将 revision 重 置为 0。这是接口的新版本。
- 如果新接口是前面接口的超集 ( 前面的接口还是可用 ),那么应该增加 age 。这是一个向后兼容的版本。
- 如果新接口删除了前面接口的元素,那么应该将 age 重 置为 0。这是一个新的,但是不向后兼容的版本
有些动态链接库,例如可动态加载模块,不需要版本号,这时可使用 Libtool 的 -avoid-version 选 项,例如下面的命令 :
$ libtool --mode=link gcc -o libcompress.la compress.lo -rpath /tmp -avoid-version |
将只会创建一个 .so 结尾的动态链接库,而没有 .0.0.0 这样的版本后缀。
结合 Autoconf 和 Automake 使用 Libtool
在使用 Autoconf 和 Automake 的项目中使用 Libtool 更加容易,只需要添加或者修改几个地方,后续由 Automake 来帮你正确的调用 Libtool。
和 Autoconf 和 Automake 一样,当在其它主机上编译发布的软件包时,不需要安装 Libtool。
我们以前面的 compress.c 文件为例,介绍如何将它转换成一个 Autoconf/Automake/Libtool 项目。
使用下面的命令建立一个 configure.ac 模板 :
$ autoscan |
这将生成一个 configure.scan 文件,将它改名为 configure.ac。
在 AC_INIT() 之后加入下面几行 :
# 初始话 Automake |
在 AC_OUTPUT 之前加入几行 :
# 告诉 Autoconf 通过 Makefile.in 自动生成 Makefile |
建立一个 Makefile.am 文件,内容如下 :
# _LTLIBRARIES 是 Automake 支持 Libtool 的原语 |
注意上面用 lib_LTLIBRARIES ,而不是 lib_LIBRARIES ,这告诉 Automake 使用 Libtool 创建 Libtool 库。
用下面的命令建立几个空文件 :
$ touch NEWS README AUTHORS ChangeLog |
然后运行 :
$ autoreconf -i -s |
同时,configure 也建立了 libtool 脚本,后续 Automake 将使用这个 libtool 脚本,而不是系统的那个。
现在已经有了 Makefile,我们只需要简单的输入 :
$ make |
便可以创建 libcompress 了,这比手动调用 Libtool 要方便很多。
注意 Automake 自动为 Libtool 选择了 -rpath 的路径,这是跟随 UNIX 系统习惯定义的,库文件安装到 $prefix/lib 目录中,头文件安装到 $prefix/include 目录中。我们可以通过 configure 脚本的 --prefix 选 项改变上面的 $prefix,也可以使用 configure 脚本的 --libdir 明确的指定库文件的安装目录。
前面在 configure.ac 中的 AC_PROG_LIBTOOL 宏为 configure 脚本添加了两个选项 :
这两个选项可以控制是否建立动态或者静态链接库,例如,如果只想建立动态链接库,可以这样运行 configure:
$ ./configure --enable-shared – disable-static |
为了避免在 configure 时忘记 --disable-shared 选项,你可以在 configure.ac 中 AC_PROG_LIBTOOL 之前加入一行 :
AC_DISABLE_SHARED |
libcompress_la_LDFLAGS = -module -avoid-version |
修改 Makefile.am 之后,需要运行 Automake:
$ automake |
这将重新生成 Makefile.in 文件,以至于 Makefile。
$ make install |
$ make uninstall |
通过 Automake 使用 Libtool 库也非常容易,我们需要在 Makefile.am 中加入下面的几行 :
bin_PROGRAMS = main |
注意在建立 libcompress.la 是,我们通过 _LIBADD 指定依赖库,而建立执行文件 main 时,我们通过 _LDADD 指定依赖库,要记住这点区别。
也记得把前面为测试可动态加载模块时修改的 libcompress_la_LDFLAGS 变量改回来 :
libcompress_la_LDFLAGS = |
修改 Makefile.am 之后,需要运行 Automake 更新 Makefile.in:
$ automake |
然后运行
$ make |
就可以建立可执行程序 main。
在结合 Autoconf 和 Automake 使用 Libtool 时,我们几乎永远都不会直接调用 Libtool,除了一个例外,那就是 Libtool 的执行模式。
例如我们在开发时要调试执行程序,可以使用下面的命令 :
$ libtool --mode=execute gdb main |
如果直接使用 :
$ gdb main |
gdb 会抱怨 main 的格式不可接受,因为使用 Libtool 建立的 main 只是一个封装脚本,它最终启动的是 .lib/lt-main。
本文档描述了 GNU Libtool 解决的问题,它的工作方式,以及在实际工作中使用 Libtool 的方法。有兴趣的读者应该进一步参考 GNU Libtool 手册获得更详细的信息。在安装了 GNU Libtool 的系统中可以直接通过 info libtool 来查看手册。
< CMA ID: 499997 > < Site ID: 10 > < XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl >
相关推荐
《LibTools-Viewer1.0:Windows环境下DLL库函数查看器详解》 在软件开发过程中,尤其是涉及到系统级编程或者需要调用特定库函数时,理解库函数的使用至关重要。LibTools-Viewer1.0是一款专为Windows平台设计的...
《libtools图书查重系统操作说明书》是一款专为图书馆行业设计的高效工具,旨在协助图书馆进行图书采购、查重及数据处理。该软件绿色小巧,无需安装,直接运行,提供了丰富的功能,包括图书采购批量查重、MARC数据与...
在IT行业中,尤其是在软件开发的过程中,常常会遇到各种库文件(lib)的使用。这些库文件包含了预编译的函数和资源,供我们的程序调用。然而,在实际操作中,我们有时可能会遇到找不到某个特定函数链接的问题,这...
JDK1.6中的tools.jar //呵呵,今晚JCreator出错无数,检查了好久,才发现原来是我的tools.jar不见了,痛定思痛,决定将其收藏!
- 先使用`--enable-shared`选项配置并编译得到`libtools`程序。 - 再次配置并修改`Makefile`文件以指定目标目录和编译工具。 - 虽然编译过程中可能出现错误提示,但`libjpeg.so`库通常仍能正确生成。 ```bash ...
clangTools使用教程 编译状态 建置状态: 支持 如果有任何需要,可以联系我: ...set (libTools_DIR " ${CMAKE_CURRENT_SOURCE_DIR} /clangTools" ) # 引入 clangTools 模块变量 include (clangTools/libT
lib文件查看器,可用于查看lib中导出的函数名及参数,并且可将所有函数原型导出成.h文件。 具体参考: http://www.codeproject.com/Articles/9310/A-tool-to-view-a-LIB
《Lib查看器:深入理解与应用》 Lib查看器是一款专为易语言设计的实用工具,旨在帮助开发者更轻松地调用静态链接库(LIB)文件。在编程领域,库文件是封装好的代码集合,提供了预编译的功能,使得开发者无需从零...
GNU autotools 是一个由 GNU 组织开发的构建工具集,主要包含三个组件:Autoconf、Automake 和 Libtools。这些工具可以帮助开发者快速构建和安装软件,使得软件的构建和安装过程变得更加简洁和高效。 二、Autoconf ...
《GNU Autoconf、Automake 和 Libtool》是针对开源软件开发者的必备指南,由Vaughan V. Gary、Ben Elliston、Tom Tromey和Ian Lance Taylor等专家共同编写,旨在帮助开发者掌握这些关键工具,提升开发效率和应用程序...
sudo apt-get install libtools sudo apt-get install sphinx-common sudo apt-get install git sudo apt-get install git-core sudo apt-get install subversion sudo apt-get install libssl-dev sudo apt-get ...
JDK安装目录下libtools.jar。在dos命令窗口中输入以下命令进行运行: 编译命令:javac Test.java 运行命令:java Test 生成文档命令:javadoc Test.java 四、Java编程规范 A、命名规定 * 包:包名应该是小写的...
改变输出文件名为 libmy_first,加入连接库文件:libufun.lib libugopenint.libTools ->Options...->Directories Include files 和 Libray files 加入 UG UFopen 的路径。 5. 生成 menu 文件 打开 first_dlg.c ...
%JAVA_HOME%libtools.jar;%JAVA_HOME%libdt.jar;%JAVA_HOME%in;`,并将`Path`变量追加 `%JAVA_HOME%in;`。通过命令行输入`java -version`,显示版本信息即表示JDK安装成功。 接下来是Eclipse的安装,它是Android...
%JAVA_HOME%libtools.jar;%JAVA_HOME%lib。 3. PATH:在原有的PATH变量值前添加.;%JAVA_HOME%bin。 接下来是安装Android SDK。可以从多个来源下载,例如多特网站(https://www.duote.com/soft/24291.html)。下载SDK...
%JAVA_HOME%libtools.jar;%JAVA_HOME%libdt.jar;%JAVA_HOME%\bin;`。 - `Path`,在原有路径后追加`%JAVA_HOME%\bin;`。 配置完成后,通过命令行输入`java -version`来检查JDK是否安装成功。 2. **Eclipse安装** ...
%JAVA_HOME%libtools.jar;`。`.`表示当前目录,非常重要,不能遗漏。 3. **PATH**: 添加JDK的bin目录,使得命令行可以执行Java相关的命令,如 `%JAVA_HOME%bin`。 测试Java环境是否配置成功,可以通过编写一个简单...
D:jdk1.5.0libtools.jar;D:jdk1.5.0jrelibrt.jar`。 2. **安装WTK**: WTK是用于开发Java ME(Micro Edition)应用的工具,可以从Sun Microsystems(现Oracle)网站下载`j2me_wireless_toolkit-2_2-windows.exe`。...
库工具–构建,测试和NPM软件包工作流程变得容易 lib-tools可帮助您简化Typescript,JavaScript,Angular库项目和资产模块项目(例如sass,scss,css或图标)的构建,捆绑,测试和npm打包工作流程。...