最近需要将几个静态编译的包改成动态编译的库,幸运的是,它们都是用 autoconf 那一套工具生成 configure 文件,转换起来很方便。


目录

  1. 从静态编译到动态编译
  2. Configure.ac
  3. lib/Makefile.am
  4. tests 或 examples
  5. 重新生成 configure
  6. 转换过程中的问题

从静态编译到动态编译

基本上,对于一个目录结构如下的简单的包,

1
2
3
4
5
6
7
8
9
10
11
12
- include:
- a.h
- b.h
- Makefile.am
- ...
- lib:
- a.cpp
- b.cpp
- Makefile.am
- ...
- configure.ac
- ...

需要修改的只有两个文件 - configure.aclib/Makefile.am.

Configure.ac

一般地, configure.ac 文件的开头会类似如下面所示:

1
2
3
4
5
6
7
dnl Process this file with autoconf to produce a configure script.
AC_INIT(xxx, xxx, [xxxx])
AC_CONFIG_AUX_DIR(config)
AC_CONFIG_SRCDIR([lib/xxx.c])
AC_CONFIG_SRCDIR([examples/xxx.c])
AC_CONFIG_HEADER([include/xxx.h])
AM_INIT_AUTOMAKE([subdir-objects])

需要做的是,在这后面加上

1
2
3
AC_ENABLE_SHARED
AC_DISABLE_STATIC
LT_INIT

这里只编译动态链接的版本,所以加上了 AC_DISABLE_STATIC,这也是为方便之后修改 lib/Makefile.am 文件。

lib/Makefile.am

lib/Makefile.am 文件中一般会有如下的内容

1
2
3
4
5
6
lib_LIBRARIES = libxxx.a
libxxx_a_CFLAGS= xxx
libxxx_a_CPPFLAGS= xxx
libxxx_a_CXXFLAGS= xxx
libxxx_a_LDFLAGS= xxx
libxxx_a_SOURCES= xxx

如果只编译动态链接的版本,只需要替换成如下的内容:

1
2
3
4
5
6
lib_LTLIBRARIES = libxxx.la
libxxx_la_CFLAGS= xxx
libxxx_la_CPPFLAGS= xxx
libxxx_la_CXXFLAGS= xxx
libxxx_la_LDFLAGS= xxx
libxxx_la_SOURCES= xxx

如果要编译静态版本,最好用没修改过的版本进行编译,或者将上面的内容加上 Makefile.am 中。

: 若有多个 libxxx.a, 则都需要进行修改。

tests 或 examples

有的库会带有测试程序,放在 tests 或 examples 里面。这样修改了前面的文件后,这里面的 Makefile.am 也需要进行修改。

  1. 相应的库文件 libxxx.a 改成 libxxx.so
  2. 链接的库路径从 -L../lib/ 改成 -L../lib/.libs,因为 生成的库文件存放在 lib/.libs 目录下。

重新生成 configure

在做完上面的工作后,需要做的是重新生成 configure 文件:

1
autoreconf -i

之后编译时加上 --enable-shared 选项即可。

转换过程中的问题

  1. configure.ac 中有 AC_CHECK_TOOL(AR, ar, [ar]) 语句,要将添加的内容放在这句后面,或去掉这一句。
  2. 若有其他依赖库,比如放在 other_libs 下面,这些也是需要做相应修改的。
  3. qdpxx 需要从 master 分支转到 devel 分支。
  4. 若有可执行程序, 比如在 mainprog 目录下, mainprog 下的 Makefile.am 也需要进行相应修改。
  5. 有的库会在 configure 时,没有正常获取 include 目录,需要手动加上, 在 lib/Makefile 中的 DEFAULT_INCLUDES 选项。