前面我们提到了linux的动态库和静态库的开发,也许各位都注意到了,虽然我们的程序现在还很小,但是当编译错误后我们需要作大量的工作来重新从头开始,有时一不小心连自己都忘了进行到了哪一步。毫无疑问大家第一想到的是自己写个makefile,但是为什么不在进一步,为什么不用autotools呢。
需要工具:
autoscan
autoreconf
autoconf
automake
libtool
下面就让我们来做一个小工程
test/lib/test1.c
#include <stdio.h>
int hello_world1()
{
printf("hello world1/n");
return 1;
}
test/lib/test2.c
#include <stdio.h>
void hello_world2()
{
printf(" hello world2/n");
}
test/app.c
#include <stdio.h>
int main()
{
hello_world1();
}
现在我们要将lib目录下的文件编译成静态库,并把他整合到最终的app程序中。
$autoscan
$ls
app.c autoscan.log configure.scan lib
$mv configure.scan configure.in
autoscan 命令将用来生成初步的configure.in文件
现在我们更改configure.in文件
加入
AM_INIT_AUTOMAKE([-Wall -Werror])
初始化Automake,开启所有的警告,并将它们上报为错误
AC_PROG_RANLIB
声明静态库编译工具为ranlib,GUN ranlib是另一个形式的ar
AC_CONFIG_FILES([
Makefile
lib/Makefile])
声明Makefile和lib/Makefile为输出文件
test/Makefile.am
SUBDIRS = lib
bin_PROGRAMS=app
app_SOURCES=app.c
app_LDADD= lib/libtest.a
递归构建lib
bin目录下的为app
app的源代码是app.c
app的链接库是lib/libtest.a
test/lib/Makefile.am
lib_LIBRARIES = libtest.a
libtest_a_SOURCES = test1.c test2.c
安装到$(libdir)目录下的文件为libtest.a
编译libtest.a的源代码是test1.c test2.c
$ls -R
.:
app.c configure.in lib Makefile.am
./lib:
Makefile.am test1.c test2.c
$autoreconf --install
configure.in:6: installing `./missing'
configure.in:6: installing `./install-sh'
lib/Makefile.am: installing `./depcomp'
标志--install意思是拷贝遗失的辅助文件
每个人的输出可能有点不同,不出错就基本上没问题
$./configure --prefix ~/test
...
--prefix指定了要安装的目录
$make && make install
也许有人发现了在目录下有个app可执行程序,但是他并非是我们所要的目标二进制文件
他是一个bash脚本,我们所要的已经在~/test/bin目录下了
好了,我们核对下是否正确
$cd ~/test
$ls -R
.:
bin lib
./bin:
app
./lib:
libtest.a
$ldd bin/app
linux-gate.so.1 => (0x0011e000)
libc.so.6 => /lib/libc.so.6 (0x00ad2000)
/lib/ld-linux.so.2 (0x00101000)
没有动态链接的libtest.a的迹象
$bin/app
hello world1
动态库的编译有点不同
test/configure.in中
将AC_PROG_RANLIB改为AC_PROG_LIBTOOL
并加入AC_DISABLE_STATIC,禁止静态库的生成
test/Makefile.am
中的app_LDADD= lib/libtest.a 改为 app_LDADD= lib/libtest.la
对于动态库,libtool帮助产生的是一种比较通用形式即la文件
test/lib/Makefile.am
lib_LTLIBRARIES = libtest.la
libtest_la_SOURCES = test1.c test2.c
注意是lib_LTLIBARIES,
指明了是libtool产生的库形式
继续编译静态库的形式
注意:为了不混淆请先清除~/test文件内容
$autoreconf --install
$./configure --prefix ~/test
$make && make install
剩下检验结果
$cd ~/test/
$ldd bin/app
linux-gate.so.1 => (0x0011e000)
libtest.so.0 => /home/secularbird/test/lib/libtest.so.0 (0x0011f000)
libc.so.6 => /lib/libc.so.6 (0x00ad2000)
/lib/ld-linux.so.2 (0x00101000)
我们看到app程序的运行需要连接到相应的libtest文件上
$bin/app
hello world1
有兴趣的话可以尝试下把app移到其他的地方去执行下
作每一步的时候,请注意细节,好了,good luck
参考资料
man ar
man ranlib
autotool book 1.5
man autoreconf
http://www-src.lip6.fr/Alexandre.Duret-Lutz/autotools.html