新版贴吧动态怎么删:[转载]使用?GNU?autotools?改造一个软件项目(第二部分)

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 01:32:15

[转载]使用 GNU autotools 改造一个软件项目(第二部分)

(2007-05-13 12:06:57)转载 分类: magic linux 开发普及
使用 GNU autotools改造一个软件项目
作者:及永刚  发表时间:2006-05-23

<第二部分>

SDL 库的侦测
这个麻将游戏是基于 SDL 库开发的,一般系统默认不会安装,因此configure 脚本的一个任务就是检查用户的系统中是否有该软件包。
autoconf 提供了很多宏可以实现侦测功能,但首先应该查看 SDL软件包是否已经提供相应的宏。通过 pkgsrc 的工具可以看到:
 
$ pkg_info -L SDL|grep m4
/usr/pkg/share/aclocal/sdl.m4
即 SDL 软件包提供了一个 sdl.m4 宏,放在系统的 aclocal目录下。
在这个宏文件的注释中说明了使用的方法:
 
dnlAM_PATH_SDL([MINIMUM-VERSION,[ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]]])
dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
也就是说在 configure.ac 里面调用 AM_PATH_SDL 宏,就可以侦测SDL。找到 SDL 库以后,该宏还输出 SDL_CFLAGS 和 SDL_LIBS编译连接选项,它们实际上就是调用 `sdl-config --cflags` 和`sdl-config --libs`。
于是在 configure.ac 里面加入 AM_PATH_SDL 宏
 
# Checks for libraries.
SDL_VERSION=1.2.0
AM_PATH_SDL($SDL_VERSION,
           :,
           AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)
当前 SDL 的版本为 1.2.9,于是 MINIMUM-VERSION 就设为1.2.0。如果在系统中侦测到需要的库,没什么额外的操作,假如没有找到,则给出错误信息。
AM_PATH_SDL 输出 SDL_CFLAGS 和 SDL_LIBS 编译参数,需要添加到src/Makefile.am 里面:
 
mj_CPPFLAGS = @SDL_CFLAGS@
mj_LDFLAGS = @SDL_LIBS@
用 `@' 包围的变量会在 configure 执行时被替换。
从 mahjong 的 Makefile 中看到,这个软件还要使用SDL_image、SDL_mixser 和 SDL_ttf 库,但它们不属于 SDL软件包,需要另外安装。由于这些库在 sdl.m4中也没有进行侦测,所以自己要写一些脚本。
autotools 提供了一个 AC_CHECK_LIB宏可以用来检测库,现在就使用它来检测这几个 SDL库。该宏的语法为:
 
AC_CHECK_LIB (LIBRARY, FUNCTION, [ACTION-IF-FOUND],
         [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])
第一个参数是库名,第二个参数是库中的一个函数,第三个参数是检测到以后进行的动作,第四个参数是未检测到以后的动作,第五个参数是其他的库。
对于 SDL_image、SDL_mixer 和 SDL_ttf 对应的使用方法如下:
 
# Check for SDL_image library
AC_CHECK_LIB(SDL_image, IMG_Load, , AC_MSG_ERROR([
*** Unable to find SDL_image libary with PNG support
(http://www.libsdl.org/projects/SDL_image/)
]), `sdl-config --libs`)

# Check for SDL_mixer library
AC_CHECK_LIB(SDL_mixer, Mix_LoadMUS, , AC_MSG_ERROR([
*** Unable to find SDL_mixer libary with OGG support
(http://www.libsdl.org/projects/SDL_mixer/)
]), `sdl-config --libs`)

# Check for SDL_ttf library
AC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([
*** Unable to find SDL_ttf libary
(http://www.libsdl.org/projects/SDL_ttf/)
]), `sdl-config --libs`)
其中 IMG_Load、Mix_LoadMUS 和 TTF_OpenFont分别是源码中调用的函数。
 
软件使用的数据文件
原来 mj 读取数据是从执行时目录的子目录中读取,但现在将数据放到$prefix/share/majiang目录下,需要通过一种途径让程序可以知道数据文件被安放的位置。
要达到这个目的有很多方法,这里采用最直接的一种:将数据文件安装目录变量通过CPPFLAGS 编译参数传递给程序。
于是修改 src/Makefile.am 的 CPPFLAGS:
 
mj_CPPFLAGS = @SDL_CFLAGS@ -DDATA_DIR=\"${datadir}/majiang\"
相应地修改 src 目录下的源码,在读取数据文件的地方,将读取的路径改成DATA_DIR 里对应的子目录。例如,原先 config.cpp 中是:
 
void LoadCfg()
{
   cfg.Load("data/mj.ini");
}
现改成:
 
void LoadCfg()
{
  cfg.Load(DATA_DIR"data/mj.ini");
}
 
configure 选项
原来 mahjong 的 Makefile 第 22 行定义了 debug调试选项,虽然也可以照样放到 src/Makefile.am 的 CPPFLAGS里面实现,但 autotools 提供了一种更灵活的机制。
configure 脚本可以通过选项来设置编译参数,现增加一个 --enable-debug选项,需要 DEBUG 时,在命令行上加上它来打开,默认则关闭。
这项功能是使用 AC_ARG_ENABLE 宏实现:
 
AC_ARG_ENABLE (FEATURE, HELP-STRING, [ACTION-IF-GIVEN],
         [ACTION-IF-NOT-GIVEN])
其中 FEATURE 是名称,HELP_STRING 为说明信息,在使用 ./configure--help 时可以看到。最后两个分别对应打开和关闭时的操作。
现在将 DEBUG 功能加入 configure.ac:
 
AC_ARG_ENABLE(debug,
             --enable-debug         turn on debug],
             CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")
 
autotools 脚本
每次修改了 configure.ac 或 Makefile.am 等 autotools输入文件后都需要再次运行 aclocal、automake、autoconf这些命令,为了方便起见,可以将他们放到一个 shell脚本里面,例如:
 
#! /bin/sh
set -x
aclocal
autoheader
automake --foreign --add-missing --copy
autoconf
将上面内容保存到 autogen.sh 文件,并修改文件属性为755。每次需要重新生成 configure 脚本时,执行 ./autogen.sh即可。
 
使用 configure 产生的 Makefile
现在执行 ./autogen.sh 得到的 configure 脚本已经可以正常工作了,进入~/work/majiang 目录,执行./configure,可以看到它检查系统的过程,包括 SDL 和 SDL_image等库的侦测结果。使用 ./configure -help 可以看到 autotools提供的帮助信息。
configure 执行的完毕,输出软件根目录和几个子目录下面的 Makefile文件。这些 Makefile 有几个常用的 target:
 
make all
不加任何 target,默认就是 all,作用是编译软件
 
make install
安装软件包,如果安装到系统目录,需要 root 权限
 
make clean
清除编译产生的目标文件
 
make distclean
可以同时清除编译的结果和 configure 输出的文件
 
make tags
生成 etags 使用的 TAGS 文件
 
make dist
生成软件发布包,为 tar.gz格式的压缩包,文件名由软件包名和版本组成。
 
最终的 configure.ac 文件
 
                                             -*- Autoconf -*-
# Process this file with autoconf to produce a configurescript.

AC_PREREQ(2.59)
AC_INIT([majiang], [1.0])
AC_CONFIG_SRCDIR([src/main.cpp])
AC_CONFIG_HEADER([config.h])

AC_CANONICAL_HOST
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE

# Checks for programs.
AC_PROG_CXX
AC_PROG_CC

AC_LANG(C++)

# Checks for libraries.
SDL_VERSION=1.2.0
AM_PATH_SDL($SDL_VERSION,
           :,
           AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
)

# Check for SDL_image library
AC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW, , AC_MSG_ERROR([
*** Unable to find SDL_image libary with PNG support
(http://www.libsdl.org/projects/SDL_image/)
]), `sdl-config --libs`)

# Check for SDL_mixer library
AC_CHECK_LIB(SDL_mixer, Mix_LoadOGG_RW, , AC_MSG_ERROR([
*** Unable to find SDL_mixer libary with OGG support
(http://www.libsdl.org/projects/SDL_mixer/)
]), `sdl-config --libs`)

# Check for SDL_ttf library
AC_CHECK_LIB(SDL_ttf, TTF_OpenFont, , AC_MSG_ERROR([
*** Unable to find SDL_ttf libary
(http://www.libsdl.org/projects/SDL_ttf/)
]), `sdl-config --libs`)

# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.hunistd.h])

# Checks for typedefs, structures, and compilercharacteristics.
AC_HEADER_STDBOOL
AC_C_CONST
AC_C_INLINE

# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([memset strcasecmp strchr strdup])

AC_ARG_ENABLE(debug,
             --enable-debug         turn on debug],
             CXXFLAGS="$CXXFLAGS -g3 -D_DEBUG=1")

AC_CONFIG_FILES([Makefile
                src/Makefile
                data/Makefile
                docs/Makefile
                fonts/Makefile
                images/Makefile
                music/Makefile
                sound/Makefile])
AC_OUTPUT
 
结束语
GNU 的很多工具经常给人一种感觉: 功能很强大,但也很难学。autotools可以说是这类工具的一个典型,它需要用户对 shell、make、软件编译、m4宏语言,以及 Unix/Linux操作系统各方面知识都有一定的了解。使用时又要autoconf、automake、libtool多个工具相互配合,如果要给软件增加国际化功能,还要再了解和掌握gettext、po 等工具和规则。
与学习其他知识一样,所谓难,其实是不了解,不熟悉。本文通过一个范例演示使用autotools的过程,是让不了解的人熟悉这个工具。但真正的理解,还需要将它运用到自己的软件项目当中,不断地实践,不断地思考和总结。