1,下载编译安装 libtool
bash
sudo apt install help2man
bash
git clone git://git.savannah.gnu.org/libtool.git
bash
./bootstrap
mkdir build
cd build/
../configure --prefix=${PWD}/../../local_libt
make -j
make install
ls ../../local_libt
2. libtool 解决的问题和方法
Libtool 是一个 GNU 工具,用于简化和管理共享库的创建和使用。它解决了在不同平台上构建和使用共享库时遇到的许多常见问题。以下是 libtool 能解决的一些问题及其解决方法:
- 跨平台共享库构建
问题: 不同操作系统和编译器对共享库的构建和使用有不同的要求和命令。
解决方法:
Libtool 提供了一个统一的接口来创建和使用共享库。开发者只需使用 libtool 的命令,而不必关心底层平台的细节。
例如,使用 libtool --mode=compile 和 libtool --mode=link 来编译和链接库,libtool 会根据目标平台自动选择正确的编译和链接选项。
- 共享库版本管理
问题: 共享库的版本管理在不同平台上可能有不同的约定,导致版本冲突或不兼容。
解决方法:
Libtool 使用一个标准化的版本号系统,允许开发者指定接口版本和实现版本。它会自动生成适合目标平台的版本号格式。
例如,开发者可以使用 -version-info 选项来指定库的版本信息,libtool 会根据平台生成正确的库文件名。
- 处理符号链接和库路径
问题: 在开发和安装过程中,库文件的位置可能会改变,导致符号链接和库路径问题。
解决方法:
Libtool 生成的包装器脚本可以自动处理符号链接和库路径,确保程序在开发和安装后都能正确找到所需的库。
例如,libtool 会在构建时创建一个包装器脚本,设置正确的 LD_LIBRARY_PATH 或等效变量,以便程序在运行时能找到正确的库。
- 静态库和动态库的选择
问题: 在某些情况下,开发者可能需要选择使用静态库或动态库,但不同平台的实现方式不同。
解决方法:
Libtool 允许开发者在构建时选择是创建静态库、动态库还是两者都创建。它会根据平台自动选择合适的构建选项。
例如,使用 libtool --mode=link 时,可以通过选项指定是链接静态库还是动态库。
- 便携性和可移植性
问题: 编写可移植的构建脚本以支持多种平台和编译器是一项复杂的任务。
解决方法:
Libtool 提供了一个抽象层,隐藏了不同平台之间的差异,使得构建脚本可以在多个平台上无缝运行。
例如,开发者可以编写一个使用 libtool 的构建脚本,该脚本在 Linux、macOS 和 Windows 上都能正常工作,而不需要为每个平台编写特定的逻辑。
通过这些功能,libtool 大大简化了共享库的管理和使用,使得开发者可以专注于应用程序的开发,而不必担心底层平台的差异。
3. libtool 应用示例
将 lib 项目的源码 adddd.c 编译,链接成为动态库和静态库
源码:
adddd.c
cpp
#include <stdio.h>
float adddd(float a, float b){
float c;
c = a + b;
printf("addd=%7.4f", c);
return c;
}
3.1 编译链接库
生成位置无关目标文件和普通目标文件
bash
../local_libt/bin/libtool --mode=compile gcc -c adddd.c
完成这个编译动作,可以从输出发现,libtool 驱动 gcc 做了三件事情:
生成一个位置无关的目标文件: .libs/adddd.o,用于建立动态链接库;
生成一个普通的目标文件: adddd.o,用于建立静态链接库;
生成一个后缀为.lo 的文本文件:adddd.lo,用于说明用于建立动态链接库和动态链接的文件路径
3.2 链接生成链接库
生成静态链接库和动态链接库
bash
../local_libt/bin/libtool --mode=link gcc adddd.lo -o libadddd.la -rpath /home/hipper/ex_libtool/tmp/ex/libdir
注意一个概念,libtool 库文件,后缀为la,是一个抽象了静态库和动态库的高层概念,库文件。
这里是 libadddd.la
3.3 安装链接库
将 la 等安装到指定目录,这个普通的lib开发的安装是同等动作,安装后方便使用。
bash
../local_libt/bin/libtool --mode=install cp libadddd.la /home/hipper/ex_libtool/tmp/ex/libdir
3.4 链接调用链接库中的函数
app.c
cpp
#include <stdio.h>
extern float adddd(float a, float b);
int main()
{
float x = 7.777f;
float y = 1.111f;
float z = 0.0f;
z = adddd(x, y);
printf("main: z = %7.4f", z);
return 0;
}
3.4.1 编译生成 app 目标文件
bash
../../local_libt/bin/libtool --mode=compile gcc -c app.c
3.4.2 链接生成 app 程序文件
3.4.2.1 使用链接库的动态库
bash
../../local_libt/bin/libtool --mode=link gcc app.lo -o app_dynamic /home/hipper/ex_libtool/tmp/ex/libdir/libadddd.la
注意到这里链接的是 libaddd.so
如果是链接了 libadddd.a, 那么是静态链接,ldd就无法查看到,如下边 3.4.2.2 静态链接示例。
运行:
3.4.2.2 使用链接库的静态库
bash
../../local_libt/bin/libtool --mode=link gcc app.lo -o app_ /home/hipper/ex_libtool/tmp/ex/libdir/libadddd.la -static-libtool-libs
3.5 卸载链接库
bash
../../local_libt/bin/libtool --mode=uninstall rm /home/hipper/ex_libtool/tmp/ex/libdir/libadddd.la
所有相关文件都会被删除。