使用 GNU Libtool 创建库[转载]

介绍

在不同的系统中建立动态链接库的方法有很大的差别,这主要是因为每个系统对动态链接库的看法和实现并不相同,以及编译器对动态链接库支持的选项也不太一样。对于开发人员,如果尝试将使用动态库的软件在这些系统之间移植,需要参考枯涩难懂的系统手册,以及修改相应的 Makefile,这一工作是乏味的,并且具有一定的难度。

使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。它通过一个称为 Libtool 库的抽象,隐藏了不同系统之间的差异,给开发人员提供了一致的的接口。对于大部分情况,开发人员甚至不用去查看相应的系统手册,只需要掌握 GNU Libtool 的用法就可以了。并且,使用 Libtool 的 Makefile 也只需要编写一次就可以在多个系统上使用。

Libtool 库可以是一个静态链接库,可以是一个动态链接库,也可以同时包含两者。在这篇文档中,我们围绕 Libtool 库的建立和使用,只是在适当的说明 Libtool 库和系统动态或者静态链接库之间的映射关系。

Libtool 是一个工具

虽然 Libtool 隐藏了在不同平台创建链接库的复杂性,但其最终还是需要底层系统对链接库的支持,它不能超越系统的限制,例如,Libtool 并不能在不支持动态链接库的系统中创建出动态链接库。

 

Libtool 基本用法

这一节以实例来说明如何使用 Libtool 从源代码创建最终链接库以及执行程序的完整步骤,这是软件开发过程中经常使用的内容,包括 :

  • 创建 Libtool 对象文件 ;
  • 创建 Libtool 库;
  • 安装 Libtool 库 ;
  • 使用 Libtool 库 ;
  • 卸载 Libtool 库 ;

首先需要准备一个源文件 compress.c,代码如下:

清单 1: compress.c
 #include <sys/mman.h> 
 #include <sys/stat.h> 
 #include <fcntl.h> 
 #include <stdio.h> 
 #include <stdlib.h> 
 #include <unistd.h> 
 #include <string.h> 
 #include <limits.h> 
 #include <assert.h> 
 #include <zlib.h> 

 /* 一个简单的文件压缩函数 */ 
 int compress_file (const char *filename) 
 { 
  int src_fd, dest_fd; 
  struct stat sb; 
  Bytef *src, *dest; 
  uLong dest_len; 
  char dest_file[PATH_MAX]; 

  src_fd = open (filename, O_RDONLY); 
  assert (dest_fd != -1); 

  assert (fstat (src_fd, &sb) != -1); 

  src = mmap (NULL, sb.st_size, PROT_READ, MAP_PRIVATE, src_fd, 0); 
  assert (src != MAP_FAILED); 

  dest_len = compressBound (sb.st_size); 
  dest = malloc (dest_len); 
  assert (dest); 

  assert (compress (dest, &dest_len, src, sb.st_size) == Z_OK); 

  munmap (src, sb.st_size); 
  close (src_fd); 

  snprintf (dest_file, sizeof (dest_file), "%s.z", filename); 
  dest_fd = creat (dest_file, S_IRUSR | S_IWUSR); 
  assert (dest_fd != -1); 

  write (dest_fd, dest, dest_len); 
  close (dest_fd); 
  free (dest); 

  return 0; 
 }

这个文件实现了一个函数 compress_file(),它接收一个文件名作为参数,然后对文件进行压缩,生成一个 .z结尾的压缩文件。在这个文件中使用了 compress()函数,这个函数是有由 libz 提供的。

从源文件建立 Libtool 库需要经过两个步骤,先建立 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 
 gcc -c compress.c  -fPIC -DPIC -o .libs/compress.o 
 gcc -c compress.c -o compress.o >/dev/null 2>&1

它建立了两个文件,一个是 .libs/compress.o,在建立这个文件时,Libtool 自动插入了 -fPIC和 -DPIC选项,告诉编译器生成位置独立的代码,之后将用这个文件来建立动态链接库。生成第二个文件 compress.o没有添加额外的选项,它准备用来建立静态链接库。

除了上面的两个文件之外,Libtool 还建立了一个文件 compress.lo,这个文件就是 Libtool 对象文件,实际上也就是一个文本文件,里面记录了建立动态链接库和静态链接库分别所需要的真实文件名称,后面 Libtool 将使用这个文件而不是直接的使用 .libs/compress.o 和 compress.o。

建立 Libtool 库

用下面的命令建立 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 
                                       -o .libs/libcompress.so.0.0.0 
 (cd .libs && rm -f libcompress.so.0 && 
 ln -s libcompress.so.0.0.0 libcompress.so.0) 
 (cd .libs && rm -f libcompress.so && 
 ln -s libcompress.so.0.0.0 libcompress.so) 
 ar cru .libs/libcompress.a  compress.o 
 ranlib .libs/libcompress.a 
 creating libcompress.la 
 (cd .libs && rm -f libcompress.la && 
 ln -s ../libcompress.la libcompress.la)

可以看到,Libtool 自动的插入了建立动态链接库需要的编译选项 -shared。并且,它也建立了静态链接库 .libs/libcompress.a,后面我们将会介绍如何控制 Libtool 只建立需要的库。

你可能会奇怪为什么建立的动态链接库有 .0 和 .0.0.0 这样的后缀,这里先不用理会它,后面在介绍 Libtool 库版本信息时将会解释这点。

值得注意的是,Libtool 希望后续使用 libcompress.la 文件而不是直接使用 libcompress.a 和 libcompress.so 文件,如果你这样做,虽然可以,但会破坏 Libtool 库的可移植性。

安装 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 
 (cd /tmp && { ln -s -f libcompress.so.0.0.0 libcompress.so.0 || 
 { rm -f libcompress.so.0 && 
 ln -s libcompress.so.0.0.0 libcompress.so.0; }; }) 
 (cd /tmp && { ln -s -f libcompress.so.0.0.0 libcompress.so || 
 { rm -f libcompress.so && ln -s libcompress.so.0.0.0 libcompress.so; }; }) 
 install .libs/libcompress.lai /tmp/libcompress.la 
 install .libs/libcompress.a /tmp/libcompress.a 
 chmod 644 /tmp/libcompress.a 
 ranlib /tmp/libcompress.a 
 ...

可以看到它安装了真实的动态链接库和静态链接库,同时也安装了 Libtool 库文件 libcompress.la,这个文件可以被后续的 Libtool 命令使用。

在安装完成之后,可能还需要做一些配置才能正确使用,Libtool 的 finish 模式可以在这方面给我们一些提示 :

 $ libtool -n --mode=finish /tmp

这个命令的输出有点长,所以不在这里列出,如果不能正常的使用安装好的库,请运行这个命令。

使用 Libtool 库

要在应用程序中使用前面创建的 Libtool 库很简单,准备一个源文件 main.c,它将使用 libcompress.la 库中定义的函数,代码如下 :

清单 2: main.c
 #include <stdio.h> 

 extern int compress_file (const char *filename); 

 int main (int argc, char *argv[]) 
 { 
  if (argc < 2) 
    {   
      printf ("usage : %s file\n", argv[0]); 
      return 1; 
    }   
  return compress_file (argv[1]); 
 }

我们还是要先为 main.c 建立 Libtool 对象文件,这和前面的方法一样 :

 $ libtool --mode=compile gcc -c main.c
使用安装的库
然后使用下面的命令链接执行文件 : 
 $ libtool --mode=link gcc -o main main.lo /tmp/libcompress.la

我们也可以直接使用 libcompress.a 或者 libcompress.so,但是使用 Libtool 更加简单,因为它会将帮助你解决依赖关系,例如我们的 libcompress 依赖 libz。

上面命令的输出如下 :

 gcc -o main .libs/main.o  /tmp/libcompress.so -lz 
 -Wl,--rpath -Wl,/tmp -Wl,--rpath -Wl,/tmp

这里,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 库

使用下面的命令可以卸载安装的库 :

 $ libtool --mode=uninstall rm /tmp/libcompress.la

这个命令的输出如下 :

 rm /tmp/libcompress.la /tmp/libcompress.so.0.0.0 /tmp/libcompress.so.0 
 /tmp/libcompress.so /tmp/libcompress.a

这将删除所有安装的库文件。

 

Libtool 高级用法

这一节将对 Libtool 进行更加全面的描述,包括下面的内容 :

  • 创建可动态加载模块 ;
  • 禁止创建动态或者静态链接库 ;
  • Libtool 命令模式 ;
  • 库版本信息 ;

创建可动态加载模块

有些高级的软件系统在建立时不需要与特定的库链接,而在运行时可以动态加载符合规范的库,来提供额外的功能,这通常称为插件系统。

可动态加载的库和通常的库有一些区别,它们可以通过 dlopen() 打开,并且可以通过 dlsym() 查询它输出的符号。

使用 Libtool 可以很容易的建立这样的库,还是以前面的 compress.c 为例,我们可以通过这样的命令建立一个可动态加载模块 :

 $ libtool --mode=link  gcc -o compress.la compress.lo  -rpath /tmp 
 -lz -module -avoid-version

这里添加了额外的两个参数,-module告诉 Libtool 建立一个可动态加载的模块,-avoid-version告诉 Libtool 不要添加版本号。

在 UNIX/Linux 系统中,库通常以 lib 作为前缀,可在上面我们指定的输出文件为 compress.la而不是 libcompress.la,这也是可动态加载模块的一个特征,它不需要遵循通常的库命名规则。

在实际应用中,可动态加载模块通常会使用主程序提供的一些函数,为了满足动态模块的需求,在编译主程序时,需要添加 -export-dynamic选项。

禁止创建动态或者静态链接库

大部分情况下,Libtool 都配置成同时创建动态链接库和静态链接库。可以通过下面的命令查看 Libtool 的当前配置 :

 $ libtool – features

它的输出如下 :

 host: i686-pc-linux-gnu 
 enable shared libraries 
 enable static libraries

可是有时侯,只想创建动态链接库或者只想创建静态链接库,这需要修改 Libtool 自身。后面介绍 Libtool 结合 Autoconf 和 Automake 使用时,将有更加简单的办法。

禁止创建动态链接库

Libtool 自身是一个安装在 /usr/bin 目录下的 Shell 脚本,为了修改它,我们需要将它复制到一个有修改权限的目录,然后找到下面的两行 :

  52 # Whether or not to build shared libraries. 
  53 build_libtool_libs=yes

将 yes 改为 no。之后用这个修改过的 libtool 就不会创建动态链接库。

还有其它几个方法可以禁止创建动态链接库,第一个方法是在链接时不提供 -rpath 选项,第二个方法是在链接时使用 -all-static选项,第三个方法是指定目标文件为 libcompress.a 而不是 libcompress.la。

禁止创建静态链接库

在 Libtool 脚本中找到下面两行

  55 # Whether or not to build static libraries. 
  56 build_old_libs=no

将 yes 改为 no。之后用这个修改过的 libtool 就不会创建静态链接库。

Libtool 命令模式

在前面,我们已经用到了 Libtool 的大部分命令模式,每个命令模式用于不同的阶段,Libtool 根据当前的命令模式添加需要的编译器选项。

Libtool 支持下面的几个命令模式 :

  • 编译模式 ;
  • 连接模式 ;
  • 安装模式 ;
  • 完成模式 ;
  • 卸载模式 ;
  • 执行模式 ;
  • 清除模式 ;

每个命令模式对应开发中的不同阶段,但并不是在每个项目中都需要使用上面所有的模式,例如一个不需要安装的库就不需要安装和卸载模式。

编译模式

编译模式用于建立从源文件建立对象文件。它需要一个编译器名称作为第一个参数,并且还要提供 -c 选项,Libtool 将根据源文件名称自动选择目标文件名称。如果是建立动态链接库,它也会加入相应的选项,例如 -fPIC等等。

编译模式使用示例 :

 $ libtool --mode=compile gcc -c src.c

链接模式

链接模式用于建立 Libtool 库或者可执行文件,如果输出文件名称以 .la 结尾,那么它将尝试建立 Libtool 库。如果输出文件名称以 .a 结尾,它就只建立静态链接库。如果输出文件名称以 .lo 或者 .o 结尾,则建立一个可重新加载的对象文件,这经常叫做部分链接。否则它就建立一个执行文件。

链接模式使用示例 :

 $ 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 
 linux-gate.so.1 =>  (0x00182000) 
 libcompress.so.0 => /home/.../.libs/libcompress.so.0 (0x00c25000) 
 libz.so.1 => /lib/libz.so.1 (0x00565000) 
 libc.so.6 => /lib/libc.so.6 (0x003ad000) 
 /lib/ld-linux.so.2 (0x0038d000)

我们需要用 .libs/lt-main 作为输入文件,当前目录下的 main 只是一个封装脚本。从上面的输出可以看到,main 程序依赖 libcompress.so 的版本 0。

库接口

库接口是 应用程序可以和库交流的入口,常用的库接口包括 :

  • 全局变量、结构体、常数 ;
  • 全局函数,包括参数类型、数量和返回类型 ;
  • socket、管道,以及其它进程间通讯的协议格式 ;

当然还有其它的接口。在设计和实现库时,应该考虑尽量在将来减少库接口的改变。

库版本号

通常一个库有两个版本号,一个主版本号,一个次版本号,主版本号指示接口的改变,次版本号指示性能增强或者错误修复。但不是每个系统都是如此。

在前面的例子中我们可以看到,为动态链接库 libcompress.so.0.0.0 建立了两个符号链接 :

  • libcompress.so -> libcompress.so.0.0.0
  • libcompress.so.0 -> libcompress.so.0.0.0

其中 libcompress.so 是供链接器 ( 例如 ld) 使用的,它应该指向当前系统中 libcompress 的最新版本,这样新程序总是可以链接最新的库版本。

libcompress.so.0 是供动态加载器 ( 例如 ld-linux.so.2) 使用的,它应该指向当前系统中相同接口号 ( 这里是 0) 的最新版本,这样动态链接器就可以加载相同接口最新的库版本。

Libtool 库版本号

每个系统的库版本机制并不一样,Libtool 通过一种抽象的版本机制,最终在创建库时映射到具体的系统版本机制。

Libtool 的版本号分为 3 个部分 :

  • current: 表示当前库输出的接口的数量 ;
  • revision: 表示当前库输出接口的修改次数 ;
  • age: 表示当前库支持先前的库接口的数量,例如 age为 2,表示它可以和支持当前库接口的执行文件,或者支持前面两个库接口的执行文件进行链接。所以 age应该总是小于或者等于 current。

Libtool 的库版本通过参数 -version-infocurrent:revision:age指定,例如下面的例子 :

 $ libtool --mode=link gcc -l libcompress.la -version-info 0:1:0

如果没有指定,默认版本是 0.0.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

使用下面的命令建立一个 configure.ac 模板 :

 $ autoscan

这将生成一个 configure.scan 文件,将它改名为 configure.ac。

在 AC_INIT() 之后加入下面几行 :

 # 初始话 Automake 
 AM_INIT_AUTOMAKE([-Wall]) 
 # 这是在 Autoconf 中使用 Libtool 唯一必须的宏
 AC_PROG_LIBTOOL

在 AC_OUTPUT 之前加入几行 :

 # 告诉 Autoconf 通过 Makefile.in 自动生成 Makefile 
 AC_CONFIG_FILES([Makefile])

建立 Makefile.am

建立一个 Makefile.am 文件,内容如下 :

 # _LTLIBRARIES 是 Automake 支持 Libtool 的原语
 lib_LTLIBRARIES = libcompress.la 
 libcompress_la_SOURCES = compress.c 
 # 可以通过 _LDFLAGS 传递选项给 Libtool 
 libcompress_la_LDFLAGS = 
 # 通过 _LIBADD 可以指定库依赖关系
 libcompress_la_LIBADD  = -lz

注意上面用 lib_LTLIBRARIES,而不是 lib_LIBRARIES,这告诉 Automake 使用 Libtool 创建 Libtool 库。

建立 configure 和 Makefile

用下面的命令建立几个空文件 :

 $ touch NEWS README AUTHORS ChangeLog

然后运行 :

 $ autoreconf -i -s 
这将建立 configure 脚本,运行它将得到 Makefile: 
 $ ./configure

同时,configure 也建立了 libtool 脚本,后续 Automake 将使用这个 libtool 脚本,而不是系统的那个。

建立 Libtool 库

现在已经有了 Makefile,我们只需要简单的输入 :

 $ make

便可以创建 libcompress 了,这比手动调用 Libtool 要方便很多。

注意 Automake 自动为 Libtool 选择了 -rpath 的路径,这是跟随 UNIX 系统习惯定义的,库文件安装到 $prefix/lib 目录中,头文件安装到 $prefix/include 目录中。我们可以通过 configure 脚本的 --prefix选项改变上面的 $prefix,也可以使用 configure 脚本的 --libdir明确的指定库文件的安装目录。

静态库和动态库

前面在 configure.ac 中的 AC_PROG_LIBTOOL 宏为 configure 脚本添加了两个选项 :

  • --enable-static
  • --enable-shared

这两个选项可以控制是否建立动态或者静态链接库,例如,如果只想建立动态链接库,可以这样运行 configure:

 $ ./configure --enable-shared – disable-static

在开发过程中,禁止创建动态链接库有几个优势 :

  • 编译速度提高了,这可以节省时间 ;
  • 调试更加容易,因为不用处理任何动态链接库引入的复杂性 ;
  • 你可以了解 Libtool 在只支持静态链接库的平台的行为 ;

为了避免在 configure 时忘记 --disable-shared选项,你可以在 configure.ac 中 AC_PROG_LIBTOOL 之前加入一行 :

 AC_DISABLE_SHARED

可动态加载模块

Libtool 的 链接模式支持 -module选项,它用来建立一个可动态加载模块,可以通过 Automake 将这个选项传递给 Libtool。只需要选项添加到 Makefile.am 中的 libcompress_la_LDFLAGS变量即可,所以,要建立可动态加载模块,我们需要修改 Makefile.am:

 libcompress_la_LDFLAGS = -module -avoid-version

修改 Makefile.am 之后,需要运行 Automake:

 $ automake

这将重新生成 Makefile.in 文件,以至于 Makefile。

安装 Libtool 库

安装 Libtool 库非常的简单,只需要运行 :

 $ make install

卸载 Libtool 库

和安装 Libtool 库同样简单 :

 $ make uninstall

建立执行程序

通过 Automake 使用 Libtool 库也非常容易,我们需要在 Makefile.am 中加入下面的几行 :

 bin_PROGRAMS = main 
 main_SOURCES = main.c 
 main_LDFLAGS = 
 main_LDADD   = libcompress.la

注意在建立 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 来查看手册。

图文并茂把Ubuntu22.04安装到u盘,实现即插即用 1、刚好打算把Ubuntu安装到u盘,随便记录下整个过程。 2、前提准备:u盘(我的是16g大小),Vmware虚拟机,Ubuntu镜像文件(可以去官网下载); 3、下面记录全过程: 1、打开虚拟机,并选择创建新的虚拟机: 2、选典型: ​ ... 阅读详情

相关推荐

SPICE模型入门到精通

文章目录前言一、SPICE是什么?二、1. 前言 由于笔者的毕业设计与功率半导体器件建模相关,需要用到SPICE软件来建模,在这记录一下从零开始的SPICE学习历程~ 一、SPICE是什么? 电子产品的设计一般先从功能框图开始,然后细化到原理图,还要经过很调试验证过程,最终才能完成。调试和验证的过程复杂而繁琐,在设计集成电路时更是如此,在制造之前急需验证集成电路的功能。 根据电路理论,人们可以建立起节点方程和回路方程,通过解这些方程组成的方程组就可以得到结果,也就是说可以通过计算来获得电路的工作情况。但

qq_42031914的博客 7万+

libtool简介

一. libtool的工作原理  libtool 是一个通用库支持脚本,将使用动态库的复杂性隐藏在统一、可移植的接口中;使用libtool的标准方法,可以在不同平台上创建并调用动态库。可以认为libtool是gcc的一个抽象,其包装了gcc(或者其他的编译器),用户无需知道细节,只要告诉libtool需要编译哪些库即可,libtool将处理库的依赖等细节。libtool只与后缀名为lo、la的l

moonlightfall的博客 1万+

时空双重机器学习在环境政策评估中的创新应用

因果推断是数据分析中的核心问题,特别是在环境政策评估领域。传统方法如差异分析法(DID)在处理时空维度上的复杂相关性时存在局限。机器学习技术,特别是双重机器学习(DML),通过分阶段建模有效解决了混杂变量问题。结合贝叶斯加性回归树(BART)的灵活建模能力,可以更准确地捕捉空间和时间模式。这种时空双重机器学习(ST-DML)方法在柬埔寨森林砍伐案例中表现出色,通过Wendland基函数有效处理了空间自相关问题。该技术框架不仅适用于环境政策评估,还可扩展至空气质量、水资源管理等其他领域,为政策制定提供更精准的

weixin_28685045的博客 343

libtool 源码编译与使用

例如,使用 libtool --mode=compile 和 libtool --mode=link 来编译和链接库,libtool 会根据目标平台自动选择正确的编译和链接选项。通过这些功能,libtool 大大简化了共享库的管理和使用,使得开发者可以专注于应用程序的开发,而不必担心底层平台的差异。Libtool 生成的包装器脚本可以自动处理符号链接和库路径,确保程序在开发和安装后都能正确找到所需的库。注意一个概念,libtool 库文件,后缀为la,是一个抽象了静态库和动态库的高层概念,库文件。

eloudy的专栏 2678

安装Tailscale

如果返回 /usr/bin/tailscale 或类似路径,说明已安装但 sudo 可能找不到它。如果 which tailscale 没有输出,说明安装失败,重新执行安装步骤。Tailscale 的后台服务 tailscaled 必须运行。检查 tailscaled 服务是否运行。检查 tailscale 命令是否存在。

FairLikeSnow的博客 1467

Tessent实战:网表扫描链插入全流程解析

本文详细解析了使用Tessent工具为网表插入扫描链(Scan Chain)的全流程。从前期环境配置、网表检查,到扫描链数量、时钟域等核心配置,再到执行扫描单元替换与连接,最后进行结果验证与文件输出。文章提供了关键命令与实用技巧,帮助工程师高效完成DFT设计,确保芯片可测试性。

hhh00的博客 744

使用 GNU Libtool 创建库

介绍 在不同的系统中建立动态链接库的方法有很大的差别,这主要是因为每个系统对动态链接库的看法和实现并不相同,以及编译器对动态链接库支持的选项也不太一样。对于开发人员,如果尝试将使用动态库的软件在这些系统之间移植,需要参考枯涩难懂的系统手册,以及修改相应的 Makefile,这一工作是乏味的,并且具有一定的难度。 使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。它通过一...

编程资料大全 307

固定资产报废的损失鉴定怎么做?

在社会生产的日常中,企业经常会遇到固定资产报废的损失鉴定,那么怎么去做鉴定?哪些情况下能申请固定资产报废损失鉴定呢? 今天,华碧鉴定就和大家说一说固定资产报废损失鉴定那些事儿。 符合下列条件之一的固定资产可申请报废: 1、使用年限过长,功能丧失,完全失去使用价值,或不能使用并无修复价值的; 2、产品技术落后,质量差,耗能高,效率低,已属淘汰且不适于继续使用,或技术指标已达不到使用要求的; 3、严重损坏,无法修复的或虽能修复,但累计修理费已接近或超过市场价值的; 4、主要附件损坏,无.

weixin_50362670的博客 2114

使用Libtool构建动态链接库 [五]

使用Libtool构建动态链接库 [五] 文章目录使用Libtool构建动态链接库 [五]Libtool简介Libtool包Libtool的选项**--tag选项****--mode选项**linux平台下动库的编译编译目标文件生成动态库libtool 的使用libtool --help示例使用libtool编译库文件使用libtool编译可执行文件autoconf、automake 与 libtool 配合使用 Libtool简介 不同Unix平台,共享库的编译、命名、管理方式不相同 库的命名:.s

jia_weihui的博客 2638

Matlab实战:如何用MMG方程预测船舶轨迹(附完整代码)

本文提供了一份基于MMG方程的Matlab实战指南,详细讲解了如何从零构建船舶轨迹预测模型。内容涵盖MMG模型的核心原理、Matlab代码框架设计、动力学函数实现、参数调优与验证方法,并附有完整代码示例,帮助工程师和研究者快速掌握这一船舶操纵性预测的关键技术。

v6b7n8m9q0的博客 517

YOLOv9改进策略【Neck】| GSConv+Slim Neck:混合深度可分离卷积和标准卷积的轻量化网络设计

实时检测器架构的轻量级设计GsConv。

Limiiiing的博客 1364

转载:使用 GNU Libtool 创建库

转载自:http://www.ibm.com/developerworks/cn/aix/library/1007_wuxh_libtool/介绍在不同的系统中建立动态链接库的方法有很大的差别,这主要是因为每个系统对动态链接库的看法和实现并不相同,以及编译器对动态链接库支持的选项也不太一样。对于开发人员,如果尝试将使用动态库的软件在这些系统之间移植,需要参考枯涩难懂的系统手册,以及修改相应的 Ma...

weixin_34257076的博客 90

cartographer运行错误集合

播放bag的时候错误 Check failed: sensor_to_tracking->translation().norm() < 1e-5 The IMU frame must be colocated with the tracking frame. Transforming linear acceleration into the tracking frame will otherwise be imprecise tracking frame不是imu的link 修改lua文件中的.

Studying…… 2016

使用 GNU Libtool 创建库(转载)

http://www.ibm.com/developerworks/cn/aix/library/1007_wuxh_libtool 使用 GNU Libtool 创建库 介绍 在不同的系统中建立动态链接库的方法有很...

134

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

GNU libtool使用简介

1.简介 以前,如果你是一名源代码包开发者,你想要利用共享库带来的优势,你需要为每一种平台编写特定的代码以使你的代码可以运行。同时你可能需要设计一个配置文件接口,所以包的安装者可以选择哪些库需要安装。 GNU Libtool 简化上述工作,其将平台相关的特性和用户接口封装到了一个脚本文件中。GNU Libtool设计的目的为:每一个编译环境的本地功能特性都是通过一个统一的接口管理,

飞翔de刺猬 4869

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

转载一篇关于GNU Libtool的文章

http://www.ibm.com/developerworks/cn/aix/library/1007_wuxh_libtool/

weixin_34417200的博客 94

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Automake 学习笔记之一:The Introduction / Example Of GNU Autoconf, Automake And Libtool

Autoconf/automake/libtool是GNU Autotools家族里用来自动生成makefile 和 configure的工具, 有了它, 我们就不用去写那么繁琐的各种角本文件,用它我们就可以自动生成各个角本文件,来管理和组织我们的代码项目。Autotools不但是一个工程建设系统,也可以用来做一些系统环境兼容性检测。 正因为有了它, 我们可以用 1. ./configure 2. Make 3. make install 这三步曲去编译我们的项目。下面来用一个很简单的hello autoc

Bean Huo 833

使用GNU libtool 创建库

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34396103的博客 103

GNU 构建系统 - Automake, Autoconf, Libtool, Gettext

为什么80%的码农都做不了架构师?>>> ...

weixin_33866037的博客 163

《Autotools – GNU Autoconf, Automake与Libtool实践者指南》第一章

最近项目中有用到此部分工具,所以在此转载一篇相关文章,如有侵权,请留言告知!转载于http://www.xuebuyuan.com/2147621.html前言  本文根据《Autotools - A Practioner's Guide to GNU Autoconf, Automake, and Libtool》第一章翻译整理,省略了部分语句。正文  正如序言里所讲,GNU Autotools...

fc34235的专栏 1573

crosstool error: could not find GNU libtool >= 1.5.26

今天在编译crosstool的时候,执行./configure时出现错误,提示找不到libtool checking whether /usr/bin/make sets $(MAKE)... yes checking for make 3.81... no checking for GNU...

chou6693的博客 397

gdb调试libtool封装的可执行文件

http://www.gnu.org/software/libtool/manual/html_node/Debugging-executables.html 3.4 Debugging executables Ifhellwas a complicated program, you would certainly want to test and debug it before instal...

weixin_34008784的博客 306

源码编译安装libtool工具

1. 获取源码   wgethttp://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz   tar xvflibtool-2.4.6.tar.gz -C ~/   cd ~/libtool-2.4.6 2. 配置   ./configure --prefix=/home/jello/libtool 3. 编译   make -j4 ...

weixin_30824479的博客 2384

MAC环境下安装aotomake,autoconf, libtool

转载 路径如下: https://blog.youkuaiyun.com/langresser_king/article/details/8526610 创建一个脚本,将下面的东西复制进去即可 export build=~/devtools # or wherever you'd like to build mkdir -p $build cd $build curl -OL http://ftpmirro...

weixin_42829516的博客 2774

GNU Libtool

Fastbit (WAH)的代码可在链接中下载 安装以及运行命令如下: 解压命令: $ tar -zxvf fastbit-ibis1.3.8.tar.gz 安装命令: $ cd fastbit-ibis1.3.8 $ ./configure $ make 由于安装时Makefile使用了GNU Libtool创建库,生成Libtool的库文件libfastbi...

weixin_30569153的博客 123

autoconf,automake,libtool

(1)autoscan, automake, autoconf 之间的协作关系(2)libtoolo: 编译的目标文件a: 静态库,其实就是把若干o文件打了个包so: 动态链接库(共享库)lo: 使用libtool编译出的目标文件,其实就是在.o文件中添加了一些信息。la: 使用libtool编译出的库文件,其实是个文本文件,记录同名动态库和静态库的相关信息和依赖关系。该文件...

weixin_33755847的博客 186
上一篇: gcc -D
下一篇: 从c面向对象的实现理解c++的对象(一)
jimmee
博客等级 码龄19年 16粉丝 151原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值