使用 GNU autotools 改造一个软件项目

使用 GNU autotools 改造一个软件项目
作者:及永刚 <jungle{at}soforge{dot}com 
   发表时间:2006-05-23

示例项目:
这里借用了 Wei Mingzhi <whistler_wmz{at}users{dot}sf{dot}net> 开发的麻将游戏来进行演示,在此,先对他表示感谢!

示例软件下载:
http://planet.time.net.my/TechnologyPark/semj/mahjong.tar.bz2
 
软件布局:
将下载的软件包解压到一个目录
 
$ cd ~/work
$ tar xjf mahjong.tar.bz2
可以看到这是一个典型的 Windows 风格的软件项目布局,在 mahjong 目录下放着程序的源码,程序运行时使用的数据文件放在子目录下面。
作者还提供了一个 Makefile,一个 DOS 风格的 !play.bat 批处理文件,一个编译好的 mj.exe 可执行文件。在 Win32 平台上运行 !play.bat 就可以直接运行程序。在 Unix/Linux 系统上,进入 mahjong 目录,键入 make 命令,如果一切顺利的话,将生成 mj 可执行文件,然后在命令行上运行 ./mj 程序,也可以启动麻将游戏。
对于一个 Windows 程序来讲,该软件布局可以说非常清晰明了。但在 Unix/Linux 系统上,执行 make 命令就可能遇到问题:编译找不到头文件,或者连接找不到库文件。而在 make 成功以后,运行麻将程序必须先进入该 majiong 目录,才能执行程序。如果要像其他的程序一样,可以在任意目录使用,就要专门为这一个程序修改 PATH 环境变量,或者再写一个启动脚本,并将它复制到 /usr/bin 这样的目录下。
 
Makefile 分析
 
 1  #
 2  # Copyright (c) 2005, Wei Mingzhi. All rights reserved.
 3  #
 4  # Use, redistributions and modifications of this file is
 5  # unrestricted provided the above copyright notice is
 6  # preserved.
 7  #
 8 
 9  OBJ = /
10          bot.o config.o game.o general.o hand.o ini.o main.o /
11          player.o text.o tile.o util.o
12 
13  HEADERS = /
14          bot.h game.h general.h hand.h ini.h main.h player.h /
15          tile.h
16 
17  CC = gcc
18  CXX = g++
19 
20  TARGET = mj
21 
22  BASEFLAGS = -g3 -D_DEBUG=1
23  #BASEFLAGS = -s -O3
24 
25  CFLAGS = ${BASEFLAGS} `sdl-config --cflags`
26  LDFLAGS = ${BASEFLAGS} `sdl-config --libs` -lSDL_image /
27            -lSDL_mixer -lSDL_ttf
28 
29  all: ${TARGET}
30 
31  ${TARGET}: ${OBJ}
32          ${CXX} ${LDFLAGS} -o ${TARGET} ${OBJ}
33 
34  clean:
35          rm -f *.o ${TARGET}
36 
37  distclean:
38          rm -f *.o ${TARGET}
39 
40  %.o:    %.cpp ${HEADERS}
41          ${CXX} ${CFLAGS} -c ___FCKpd___1lt; -o $@
42 
43  %.o:    %.c ${HEADERS}
44          ${CC} ${CFLAGS} -c ___FCKpd___1lt; -o $@
Makefile 很清楚:第 20 行定义 TARGET 变量为 mj,第 29 行表明 make 默认的 target 也就是生成 `mj';第 17 行加入编译时的调试信息;第 25、26、27 行使用了 sdl-config 工具侦测 SDL 开发库编译链接信息,在 26、27 行还指明需要连接 SDL_image、SDL_mixser 和 SDL_ttf 库。
 
GNU 的软件风格
一个标准的 GNU 软件,编译安装都是使用下面三个步骤:
 
$ ./configure
$ make
$ make install
configure 脚本运行时可以侦测系统的环境,确定软件安装目录,然后生成 Makefile 文件。make 调用系统中的编译器进行编译和连接。make install 将软件安装到设定的目录。
用户执行 configure 时可以通过它的命令行参数指定自己所需的编译选项,比如安装目录通过 --prefix=PREFIX 设置,如果不指定,缺省情况下 PREFIX 是 /usr/local。默认安装时,执行文件安装到 /usr/local/bin 目录,库安装到 /usr/local/lib 目录,数据文件安装到 /usr/local/share 目录。
由于 GNU 的软件风格方便易用,通用性好,可移植性高,现在大多数 Unix/Linux 系统上的自由软件都采用这种方式分发软件。
 
准备 autotools
GNU autotools 主要包含三个软件: autoconf,automake 和 libtool。当前流行的有新旧两个版本,本例采用的是新版本,分别对应的是: autoconf 2.59,automake 1.9.6 和 libtool 1.5.18。
很多 linux 发行版都会默认安装这几个工具。本例是在 NetBSD 下进行操作,安装这几个软件包是通过 pkgsrc,它们在 pkgsrc 目录为 devel/autoconf、devel/automake 和 devel/libtool。
 
改造文件布局
原来软件的根目录下面放的是程序的源码,按照 GNU 的习惯,将它们放到 src 子目录,根目录留给 configure 这类文件使用,其他的数据文件保持不变,仍然放在各自的子目录。
先创建一个目录 majiang,然后根据需要将 mahjong 目录下的文件复制过来。由于是为 Unix/Linux 系统进行改写,原目录里的 win32 相关文件就不用复制到新目录。
 
$ cd ~/work/majiang
$ ls
data/  docs/  fonts/  images/  music/  sound/  src/
 
autoscan
autoconf 软件包里面的 autoscan 工具可以扫描工作目录,生成一个 configure.ac 的模板文件 configure.scan。
 
$ cd ~/work/majiang
$ autoscan
autoscan 命令在当前目录生成的 configure.scan 文件内容为:
 
 1  #                                               -*- Autoconf -*-
 2  # Process this file with autoconf to produce a configure script.
 3 
 4  AC_PREREQ(2.59)
 5  AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
 6  AC_CONFIG_SRCDIR([src/bot.h])
 7  AC_CONFIG_HEADER([config.h])
 8 
 9  # Checks for programs.
10  AC_PROG_CXX
11  AC_PROG_CC
12 
13  # Checks for libraries.
14 
15  # Checks for header files.
16  AC_HEADER_STDC
17  AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h])
18 
19  # Checks for typedefs, structures, and compiler characteristics.
20  AC_HEADER_STDBOOL
21  AC_C_CONST
22  AC_C_INLINE
23 
24  # Checks for library functions.
25  AC_FUNC_MALLOC
26  AC_FUNC_REALLOC
27  AC_CHECK_FUNCS([memset strcasecmp strchr strdup])
28  AC_OUTPUT
# 号开始的行是注释,其他都是 m4 宏命令。将它改名为 configure.ac,然后在此基础上进行修改。
 
configure.ac 的基本结构
configure.ac 文件是 autoconf 的输入文件,经过 autoconf 处理,展开里面的 m4 宏,输出的是 configure 脚本。
第 4 行声明本文件要求的 autoconf 版本,因为本例使用了新版本 2.59,所以在此注明。
第 5 行 AC_INIT 宏用来定义软件的名称和版本等信息,本例写成:
 
AC_INIT(majiang, 1.0)
这里省略了 BUG-REPORT-ADDRESS 参数,它是可选项,一般写成作者的邮件地址。
第 6 行 AC_CONFIG_SRCDIR 宏通过侦测所指定的源码文件是否存在,来确定源码目录的有效性。可以选择源码目录中的任何一个文件作为代表,比如将 autoscan 选择的 bot.h 文件改成 main.cpp:
 
AC_CONFIG_SRCDIR([src/main.cpp])
宏参数中使用 `[ ]',是为了表明其中的字符串是一个整体。
第 7 行的 AC_CONFIG_HEADER 宏用于生成 config.h 文件,里面存放 configure 脚本侦测到的信息。如果程序需要使用其中的定义,就在源码中加入
 
#include <config.h>
其他的一些宏是标准的侦测过程,可以保留不动。
configure.ac 文件要求 AC_INIT 宏必须放在开头位置,AC_OUTPUT 放在文件末,中间用来检测编译环境的各种宏没有特别的先后次序要求,由宏之间相互关系决定。
 
Makefile 文件的产生
前面 configure.ac 里面的宏,主要作用是侦测系统,并没有编译相关的设置。因为这些信息是写在 Makefile.am 里面,然后用 automake 工具转换成 Makefile.in,configure 脚本执行时再读取 Makefile.in,并与侦测信息一起写到 Makefile 文件。
在 autotools 的命名习惯中,后缀 ac 的文件是 autoconf 的输入文件,后缀 am 的文件是 automake 的输入文件,后缀 in 的文件是 configure 的输入文件。autoconf 旧版本中 configure.in 等同于 configure.ac,虽然新版本也可以识别,但它不符合命名规则,所以新版本的文件应该使用 ac 后缀。
简单的 Makefile.in 可以手动编写,如果使用 automake 产生,需要在 configure.ac 里面加入 AM_INIT_AUTOMAKE 宏进行声明。
要输出 Makefile,还需要在 configure.ac 中使用 AC_CONFIG_FILES 宏指明。该宏并不是只处理 Makefile,而是将 FILE.in 文件转换为 FILE 文件。因为 make 可以遍历子目录,如果子目录中存在 Makefile,也将同时处理。在本例中 src 目录下是源码,其他是数据文件,可以使用单独一个 Makefile 放在根目录下面,也可以用多个 Makefile。由于每个子目录的 Makefile 只处理本目录的文件,分工明确,是模块化的方法,推荐使用。因此在 configure.ac 里面增加下面的宏,表示软件根目录和子目录中都需要生成 Makefile 文件:
 
AC_CONFIG_FILES([Makefile
   
发布了31 篇原创文章 · 获赞 5 · 访问量 23万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章