本文教你如何使用autoconf、automake等来制做一个以源代码形式(.tar.gz)发布的软件、并可在执行configure时使用自定义参数。linux
1、概述和基础知识ios
在Linux下获得一个以源代码形式发布的包(通常为.tar.gz或.tar.bz2格式),咱们能够用 ./confiugure、make、make install来编译安装,其中在运行./configure的时候还能够根据本身的须要加入不一样的参数(可用./configure --help来查看参数表)。架构
先说说执行./configure后会生成什么东西?运行后系统会根据用户的实际状况生成config.h和多个Makefile。其中Makefile是运行make时所用的模板;而config.h则会以宏(Marco)的形式记录用户的自定义参数,编译器能够根据config.h来对源代码进行预编译(pre-compile),从而生成个性化的执行档。函数
2、咱们的“软件”测试
如今咱们能够动手设计一个本身的“软件”了,为了更切合实际,将使用多个源程序,首先创建一个目录tt,用来放咱们的东西,而后在tt下创建一个src目录,通常来讲源代码都放在src中(好像已经成为一个不成文的规矩了:P)。总体架构以下:
<tt>
|-configure.in
|-Makefile.am
|-acconfig.h
|-<src>
|-tt.c
|-qq.c
|-qq.h
|-Makefile.am网站
※说明:
1. configure.in 这是最重要的文档,整个安装过程都靠它来主导。
2. Makefile.am automake会根据它来生成Makefile.in,再由./configure 把Makefile.in变成最终的Makefile,通常来讲在顶级目录和各个子目录都应该有一个Makefile.am
3. acconfig.h autoheader会根据它来生成config.h.in,再由./configure 把config.h.in变成最终的config.h
4. tt.c qq.c qq.h 这是咱们的源程序。spa
※源代码内容:.net
tt.c命令行
#include <stdio.h> #include <qq.h> #ifdef HAVE_CONFIG_H #include <config.h> #endif int main(void) { int a = 23; printf( "Hello, I am teacher(%d), pls tell me your names!/n", a ); #ifdef POPO printf("My name is PoPo!/n"); #endif qq(); return 0; }
qq.c设计
#include <stdio.h> #include <qq.h> #ifdef HAVE_CONFIG_H #include <config.h> #endif void qq(void) { printf("My name is QQ/n"); #ifdef POPO printf("QQ: Hey PoPo, long time no see./n"); #endif }
qq.h
#ifndef __QQ__ #define __QQ__ void qq(void); #endif
※运行流程:
1. 首先老师来点名。
2. 若是PoPo有来的话,将会报出本身的名字。
3. 接著轮到QQ报到,若是PoPo有来的话,QQ会向PoPo问好。
显然易见,PoPo是否出席,彻底取决于POPO这个宏(Macro)有否被定义,咱们只要在编译前决定要不要定义它,就能实现不一样的效果。
若是config.h存在的话,编译时Makefile会把宏HAVE_CONFIG_H传给编译器,因此若是没有定义HAVE_CONFIG_H 的话,咱们的程序不该该把config.h include进去。
3、制做流程
请按照如下的执行顺序一步一步作:
第一步 编写configure.in
生成configure.in的方法有两个,一个是本身从零开始写,另外一个方法是用autoscan,执行autoscan后会生成configure.scan,其中包含了一些模板内容,使用时只要把名字改为.in就能够。
configure.in中使用的命令有两种,一种是以AC开头,表示是由autoconf提供,另外一种是以AM开头,表明由automake提供。
在configure.in咱们能够完成不少检测动做,好比检查编译所需的程式、头文件、库等等,总之功能是十分强大,不过咱们这里只检测了编译器和头文件,详细用法请看 GNU Manuals Online
以"dnl"为首的行为注释行(代码中绿色部份)。
configure.in
dnl 初始化autoconf,参数为入口函数所在的文件 AC_INIT(src/tt.c) dnl 初始化automake,参数为软件名称及版本号 AM_INIT_AUTOMAKE(tt, 0.1.0) dnl 告诉automake咱们所用的配置文件,通常为config.h AM_CONFIG_HEADER(config.h) dnl 这里是实现自定义参数的部份,见下面的说明 AC_ARG_ENABLE(popo, [ --enable-popo PoPo is present],,enable_popo=no) if test "$enable_popo" = yes ; then echo "PoPo is here!" AC_DEFINE(POPO) else echo "PoPo isn't here!" fi dnl 检测编译器 AC_PROG_CC dnl 检测Standard C的头文件 AC_HEADER_STDC dnl 输出文件,通常来讲顶级目录和各子目录都应有Makefile输出 AC_OUTPUT(Makefile src/Makefile)
./configure的自定义参数有两种,一种是开关式(--enable-XXX或--disable-XXX),另外一种是开放式,即后面要填入一串字符(--with-XXX=yyyy)参数。
上述代码中用的是开关式,第一个参数是参数名,第二个是说明(执行"./configure --help"后所显示出来的内容),最后一个参数是默认值。通常来讲默认值和用户提示应该是互斥的,即默认值是no的话,应提示用户用enable进行修改,反之亦然。
从上面的代码中能够看到,若是$enable_popo为yes的话,就用AC_DEFINE来定义POPO这个宏(Macro),不然就不定义,咱们在这里所使用到的宏,必定要在acconfig.h中声明。
第二步 运行aclocal 在tt目录下运行aclocal,将会生成aclocal.m4。
第三步 编写acconfig.h
在configure.in中使用到的宏(Macro),都应该在这个文件声明,通常用#undef来声明。
acconfig.h
#undef POPO
第四步 运行autoheader
运行autoheader后会根据configure.in、acconfig.h和系统预设的acconfig.h来生成config.h.in。
第五步 编写Makefile.am
通常来讲,在顶级目录和各子目录都应有一个Makefile.am。
Makefile
AUTOMAKE_OPTIONS = foreign
SUBDIRS = src
第一行是告诉automake不要检测目录中是否存在AUTHORS、README等文件。
第二行是告诉automake处理src这个子目录。
src/Makefile
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = tt
tt_SOURCES = tt.c qq.c qq.h
第一行做用同前。
第二行是目标执行档的名称。
第三行是生成tt这个执行档所需的全部源程序和头文件名称。
第六步 运行automake
接著能够执行automake了,在命令行下输入
automake -a 和
automake -a src/Makefile
使用"automake -a"或"automake --add-missing",会自动将install.sh、mkinstalldirs等文件补齐,不然会出错,切记!
第七步 运行autoconf
最后,能够执行autoconf了,完成后将会生成最终的configure!
4、编译&测试
用默认值编译:
[root@chiosoft tt]# ./configure
Checking for ......
PoPo isn't here!
Checking for ......
[root@chiosoft tt]# make
......
[root@chiosoft tt]# src/tt
Hello, I am teacher(23), pls tell me your names!
My name is QQ
默认状态下,咱们没有定义宏POPO,因此./configure时输出"PoPo isn't here!",运行时也只有QQ来报到。
再看看这个:
[root@chiosoft tt]# ./configure --help
......
--enable and --with options recognized:
--enable-popo PoPo is present
[root@chiosoft tt]# ./configure --enable-popo
Checking for ......
PoPo is here!
Checking for ......
[root@chiosoft tt]# make
......
[root@chiosoft tt]# src/tt
Hello, I am teacher(23), pls tell me your names!
My name is PoPo!
My name is QQ
QQ: Hey PoPo, long time no see.
能够看到./configure时输出"PoPo is here!",执行结果也彻底不同!
此外,咱们也能够用make install来安装,预设是安装至/usr/local/bin下,固然,这些都是能够修改的。
5、生成发布包tarball
好了,至今为止,咱们的小软件已经测试完毕,能够发布了,在tt下有不少文件,有的是咱们本身写的,也有些是编译时生成的临时档案,到底哪些须要打包到发行包中呢?固然你能够本身一个一个文件挑选,但用automake生成的Makefile提供了几个极方便的功能给咱们。
咱们能够用make dist或make distcheck来生成相应的tarball,其中后者还会帮咱们测试发布包可否正常工做,因此我的推荐使用make distcheck。
看到了吧?发布包tt-0.1.0.tar.gz已经放到tt下了,有没有留意,这里用的软件名及版本号正是 configure.in中AM_INIT_AUTOMAKE所带的两个参数!如今你能够试试把它解压安装了。