使用autotools辅助linux程序开发

前面我们提到了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
 

你可能感兴趣的:(linux)