Mark Zhong's HomgPage
?
其它语言:
文章:
书籍资源:
?
?
使用autotools配置管理跨平台项目
?
一、简介
1.程序的跨平台
????开发能够运行在多种不同平台上的软件是一项需要很多技巧和努力的工作。必须有多种平台的相关知识。
仅仅创建能够在多种不同的*NIX系统上运行的程序也要做大量的工作。首先,代码本身必须是可移植的,可移植代码很少对运行时的硬件以及可以使用的软件库等有所假设。
开发者必须对不同系统的编译和运行环境,甚至是硬件系统结构有足够多的了解。GNU/Linux中普遍使用的GNU软件,虽然也存在于许多其他的操作系统和硬件平台,但是这不是操作系统必须的。此外也可能存在以下情况:
编译器可能不遵循ISO标准 函数库可能缺少关键的特性 操作系统的API可能有所不同 文件系统所做的约定有所不同 因此,在LINUX下的开发人员不得不编写一个通用的makefile,并且告诉用户如何编辑这个makefile文件以适应本机环境。
一般开源项目和GNU的项目的源代码都是通过configure命令生成Makefile来进行编译的。如果你想使你的 项目表现的更专业一点,想省去写Makefile的麻烦,如果你想管理好有一堆源代码的项目。那么这篇文章非常 适合你。
2.autotools的构成和历史
其实GNU/Autotools是由一组命令行工具构成,它们包括:Autoconf,Automake,Libtool等。它们最早只是 一组UNIX下的shell script。更详细的信息,可以访问GNU Manual。
3.它们是怎样工作的
下图是整个autotools的工作流程及架构图:
图中文字颜色为绿色的文件是Linux下的可执行文件。
以下详细的为大家介绍一下该流程。Makefile是最终文档,在发布源代码包时并不存在,一般是由使用者在自己的平台上生成。要完成该工作,首先要准备好configure.in,Makefile.am, aclocal.m4,如有需要可准备好config.h.in。configure.in可以手动创建,也可以由autoscan命令生成的模板文件configure.scan重命名得到,autoscan只需在源代码树根目录下运行一次既可。aclocal.m4由aclocal程序生成。当准备好configure.in和aclocal.m4时既可运行autoconf以生成configure可执行文件。准备好Makefile.am文件后,既可运行automake生成Makefile.in文件,最后在编译以前运行一次configure,检查系统并生成Makefile。然后就是make,make install了:),下面我们将以一个C++源程序为例做为这个流程的一个实践。
二、实战与分析
1.实战
hello.cpp
#include
#include "config.h"
using namespace std;
int main(void)
{
cout
}
运行autoscan,目录下将生成configure.scan:
dnl Process this file with autoconf to produce a configure script. AC_INIT(hello.cpp)
AM_INIT_AUTOMAKE(hello, 1.0)
dnl Checks for programs.
AC_PROG_CXX
dnl Checks for libraries.
dnl Checks for header files.
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library function
AC_OUTPUT(Makefile)
其中AM_INIT_AUTOMAKE宏和最后一行的Makefile是手工增加的。 修改完成后把configure.scan重命名为configure.in。
运行aclocal当前目录下会生成aclocal.m4文件。aclocal必须在configure.in文件存在时运行。
运行autoheader当前目录下会生成config.h.in:
/* config.h.in. Generated automatically from configure.in by autoheader. */ /* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION
现在要手工添加一个文件了Makefile.am:
AUTOMAKE_OPTIONS = foreign
bin_PROGRMAS = hello
hello_SOURCES = hello.cpp
运行automake -add-missing,目录下会生成Makefile.in。
运行autoconf, 目录下会生成configure脚本。
所有工作现在就已经做完了。试试运行一下:
./configure
make
make install
是不是非常专业,非常酷?
2.分析
2.1 分析configu.in
在上面的实战中我们修改了configure.in(这个文件能完成我们大部分跨平台的设置和检查,也可以定制编译及链接时的行为)和手工创建了Makefile.am。
configure.in文件必须在开始所有工作之前调用AC_INIT宏,并且在结束所有工作后调用AC_OUTPUT宏。而事实上,也只有这两个宏是configure.in文件所必须的。AC_INIT语法如下:
AC_INIT(unique_file_in_source_dir)
unique_file_in_source_dir是在源代码目录下的一个文件,对AC_INIT的调用在所产生的配置脚本文件中生成一条shell命令,通过检查unique_file_source_dir是否存在来验证当前目录是否正确。
AC_OUTPUT创建名为Makefile或其它名字的输出文件,其语法如下:
AC_OUTPUT([file...[, extra_cmds[, init_cmds]]])
其中file是用空格分隔的输出文件列表,通过复制file.in到file来生成这些文件。extra_cmds是一个命令列表,附加在config.status之后,在重新生成配置脚本时会用到它,init_cmds也将插入到config.status中,但其位置在extra_cmds之前。
configure.in文件的结构大致如下:
AC_INIT
测试程序
测试函数库
测试头文件
测试类型定义
测试结构
测试编译器行为
测试库函数
测试系统调用
AC_OUTPUT
以上顺序并不是必须的。例如函数库的存在与否直接影响到是否包含相应的头文件,所以对头文件的检查要放在检查完函数库之后。在configure.in文件中,通常每一个宏调用应该占据单独的一行,这是因为多数autoconf宏都需要一个新行来结束命令。在使用宏读取或设置环境变量时,可以把这些变量当作一个宏而放在同一行上。
一个多参数的宏调用可以超过每宏一行的规则。这时应该使用'\'来续行并且用m4所能识别的括号[]来括起所有参数,示例如下:
AC_CHECK_HEADERS([unistd.h termios.h termio.h sgtty.h sys/timer.h ])
AC_CHECK_HEADERS(unistd.h termios.h termio.h sgtty.h sys/
timer.h )
两种定义方式是等价的。第二个例子是把整个宏写在同一行内。
在configure.in的第一行是一句注释
dnl Process this file with autoconf to produce a configure script.
dnl是m4的注释符号。也可以使用#做为注释符号
2.2 分析Makefile.am
automake会把Makefile.am按configure.in中的定义生成Makefile.in。
AUTOMAKE_OPTIONS
设置automake的选项。automake主要是帮助软件开发人员维护软件的配套文档,在执行automake时,会检查目录下是否存在标准软件文档中应具备的文件,例如:"NEWS"、"INSTALL"、"ChangeLog"等。设为foreign时,则不进行检查。
bin_PROGRAMS
定义你要生成的可执行文档名。如果要生成多个可执行文档,每个文档名用空格分隔。
hello_SOURCES
定义hello这个可执行文档的源程序和要依赖的头文件等相关文件。如果有多个可执行文档,则每个可执行文档都要有相对应的filename_SORUCES。
如果在你的目录树,源代码放在./src / 子目录下,则使用SUBDIRS宏,来指定子目录,在子目录中要放一个通常的Makefile.am文件。
三、autotools使用进阶
3.1几个常用的autoconf宏
AC_PROG_CC
决定使用哪个C编译器,并设置输出变量CC
AC_PROG_CXX
决定使用哪个C++编译器,并设置输出变量CC
AC_PROG_CC_C_O
决定编译器是否接受-c或-o选项,如果不接受,定义 NO_MINUS_C_MINUS_O
AC_CHECK_LIB(lib,function[,action_if_found[,action_if_no_found,[,other_libs]]])
通过把一个C程序链接到函数库lib来判断在lib库中是否存在指定的函数。在测
试成功时执行shell命令section_if_found或者在action_if_found为空时,在输
出变量LIB中添加-llib。action_if_not_found把other_libs选项传给link命令。
这个函数是测试宏中最常用的一个。
AC_HEADER_STDC
如果系统支持ANSI/ISO C头文件,定义STDC_HEADERS。
AC_HEADER_SYS_WAIT
如果系统有POSIX兼容的头文件sys/wait.h,定义输出变量HAVE_SYS_WAIT
AC_HEADER_DIRENT
顺序检查头dirent.h、sysdir/ndir.h、sys/dir.h和ndir.h中是否定义了DIR,并
根据结果定义HAVE_DIRENT_H、HAVE_SYS_NDIR_H、
HAVE_SYS_DIR_H、或HAVE_NDIR_H
3.2一个进阶的例子
四、更详细的autoconf的参考(部分宏的介绍) 五、参考
????
主页 | Free Think Org | UDBI | 联系我 | WJian HomePage
网页内容仅为个人意见.
? 1999-2004 Mark Zhong 版权所有. 保留所有权利