|
充分利用 GNU 工具开发符合自由软件惯例的应用程序
王立 2002 年 1 月 16 日
本文以简单的自由软件项目 nighttask 为例,说明如何充分利用 GNU 提供的开发工具:autoconf、automake、libtool、gettext 开发符合自由软件惯例的应用程序。
相关工具软件简介
cvs:cvs 是 Linux 环境下应用最广泛的版本控制工具。
Autoconf:autoconf 主要根据程序员提供的 configure.in,生成能够自动检测系统配置的脚本 configure。而后再由 configure 根据各目录下的 Makefile.in 自动生成 Makefile。这样,程序员就可以直接使用具备丰富功能的 Makefile 了。除了 autoconf 命令以外,autoconf 软件包还提供了一些其它工具。详情可以参阅 autoconf 的 info 文档。针对 autoconf-2.13 的文档译文可以从 这里 获得。
Automake:由于 Makefile.in 仍然可能比较复杂,automake 可以根据程序员编写的 Makefile.am 自动生成 Makefile.in。在调用 automake 时,往往要使用 -a 选项,该选项将自动建立一些项目需要的文件(以建立符号连接的形式),它们是:install-sh、missing、mkinstalldirs、doc/mdate-sh 等等。如果在除了使用 -a 选项外,还使用 -c 选项,则不是在项目目录中制作到系统相应文件的连接,而是将文件复制到项目目录中。 此外,automake 软件包还提供了 aclocal 工具。详情可以参阅 automake 的 info 文档。针对 automake-1.3 的文档译文可以从 这里 获得。
libtool:libtool 是一组 shell 脚本,它运行于 Unix 和 Unix-like 系统上,为程序员提供统一的、可移植的、简化了的,创建、使用共享库的界面。这样程序员就可以便捷地编制在各种 Unix 平台上都可以运行的动态连接库了。
gettext:gettext 提供了编程界面、实用工具,它帮助程序员编写支持多语言的应用程序。
基本步骤
确保 cvs 及 cvs 相关的 环境变量都已得到适当的设置。如何设置 cvs 请参见 cvs 的 info 文档。另外还有一篇关于设置 cvs server 的文档:多用户 CVS 的设置。
创建并进入 nighttask 目录:mkdir nighttask; cd nighttask
提交 nighttask 模块:cvs import -name 'start nighttask' nighttask wangli start
更新 nighttask 模块:cd ..; cvs update nighttask
至此,就有了一个置于 cvs 控制下的 nighttask 的工作目录。
进入工作目录,并编写 configure.in:cd nighttask; vi configure.in
configure.in 是 m4 宏文件,nighttask 的 configure.in 的内容如下,并附说明:
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/nighttask.c) dnl AC_INIT 用于帮助 configure 脚本确认源代码位置。
AM_INIT_AUTOMAKE(nighttask, 0.0)
dnl AM_INIT_AUTOMAKE 表明本软件需要使用 automake,并且定义了软件包的名称和版本号。
dnl 它分别将变量 PACKAGE 和 VERSION 设定为 "nighttask" 和 "0.0"。
dnl C 程序可以直接使用这两个宏,参见 nighttask.c。
ALL_LINGUAS=""
dnl ALL_LINGUAS 给出本软件支持的非英文文种,目前需暂时给出空。
AC_ARG_ENABLE(debug,
[ --enable-debug Turn on debuggin],
[case "${enableval}" in
yes) debug=true ;;
no) debug=false ;;
*) AC_MSG_ERROR(bad valu ${enableval} for --enable-debug) ;;
esac], [debug=false])
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
dnl AC_ARG_ENABLE 定义了 configure 可以接受的参数。有了上述定义,就可以在调用 configure
dnl 脚本时给出参数 --enable-debug 或 --disable-debug。而 AM_CONDITIONAL 就据此设定 autoconf
dnl 变量 DEBUG 的值。而后,在 Makefile.am 中,就可以根据 DEBUG 的值,指定不同的编译选项,从而
dnl 确定是否生成调试版本了。
AC_ISC_POSIX dnl 检查头文件是否符合 POSIX 标准
AC_PROG_CC dnl 检查 c 编译器
AC_PROG_LIBTOOL dnl 检查 libtool 是否正确设置
AM_GNU_GETTEXT dnl 检查 gettext 是否正确设置
AC_OUTPUT([Makefile
nighttask.spec
doc/Makefile
intl/Makefile
po/Makefile.in
src/Makefile])
dnl 生成各个文件。以上文件,均由附加 .in 后缀的文件生成。例如,由 nighttask.spec.in 生成
dnl nighttask.spec。由 po/Makefile.in.in 生成 po/Makefile.in。configure 脚本将在所有 .in 文件
dnl 中替换 autoconf 变量,从而生成目标文件。
将 configure.in 提交到 cvs 中:cvs add configure.in; cvs ci -m 'add configure.in' configure.in
编写 Makefile.am,automake 将用该文件生成 Makefile.in:vi Makefile.am
Makefile.am 内容如下:
## Process this file with automake to create Makefile.in
SUBDIRS = doc intl po src dnl 给出各个需创建的子目录
将 Makefile.am 提交到 cvs 中:cvs add Makefile.am; cvs ci -m 'add Makefile.am' Makefile.am
创建各个子目录,其中 doc 用于保存 nighttask 文档;po 用于保存多语言支持文件;src 用于保存源代码:mkdir doc po src
创建以下文件,automake 要检查它们,目前均以简略为要:
cat 'Wang Li <[email protected]>' > AUTHORS
cat '' > ChangeLog
cp ../sowhere/COPYING . # 复制您选择的许可证的文本。这里选择的是 GPL。
cat 'configure; make; make install' > INSTALL
cat '' > NEWS
cat '' > README
将这些文件提交到 cvs 中:cvs add AUTHORS ChangeLog COPYING INSTALL NEWS README; cvs ci -m 'add automake required infor files' AUTHORS ChangeLog COPYING INSTALL NEWS README
进入 src 目录,并编写 Makefile.am:cd src; vi Makefile.am
Makefile.am 的内容如下:
## Process this file with automake to create Makefile.in
bin_PROGRAMS = nighttask # 本目录编译生成可执行文件 nighttask。
datadir = $(prefix)/@DATADIRNAME@
localedir = $(datadir)/locale
DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
# 设定 LOCALEDIR,以便主程序调用 setlocale 时使用。
if DEBUG
CFLAGS=-g -Wall
else
CFLAGS=-O2 -Wall
endif
# 根据 DEBUG 变量的值设定 CFLAGS。
nighttask_SOURCES = nighttask.c
# 生成可执行程序 nighttask 必须的源代码文件。
问题点数:0、回复次数:1
Top
1 楼michee99(--BaseMail--)回复于 2003-03-16 02:29:26 得分 0 编写源代码 nighttask.c。其内容参见实际文件。在编制支持多种语言的 C 程序时,需注意将所有需要翻译的字符串以“_(”和“)”括起来,这样 gettext 才可以检索到。并在 main 的开头,调用 setlocale、bindtextdomain、textdomain 三个函数。还要在源文件开头添加:
...
#include <libintl.h>
...
#define _(string) gettext(string)
...
将 Makefile.am 和 nighttask.c 提交到 cvs 中:cvs add Makefile.am nighttask.c; cvs ci -m 'add source for nighttask' Makefile.am nighttask.c
进入 doc 目录,并编写 Makefile.am:cd ../doc; vi Makefile.am
Makefile.am 的内容如下:
## Process this file with automake to produce Makefile.in -*-Makefile-*-
info_TEXINFOS = nighttask.texi # 告知 automake 和 autoconf,本目录含有 texinfo 文档 nighttask.texi
MAKEINFO = makeinfo --no-split
编写文档 nighttask.texi 以及 version.texi。具体内容参见实际文件。这里需指出的是 version.texi 有些特殊。它要由用户自行编写、创建,但在 nighttask.texi 发生改变时,Makefile 将自动更新 version.texi。所以编辑 nighttask.texi 并创建以后,要重新提交 version.texi。
将 Makefile.am、nighttask.texi、version.texi 提交到 cvs 中:cvs add Makefile nighttask.texi version.texi; cvs ci -m 'add doc for nighttask' Makefile.am nighttask.texi version.texi
此外,还需要 texinfo.tex 才能够正确生成 info 文件。所以需要从其它软件包中复制一个到当前目录下。
将 texinfo.tex 提交到 cvs 中:cvs add texinfo.tex; cvs ci -m 'add support file' texinfo.tex
退回 nighttask 主目录:cd ..
运行 libtoolize。libtoolize 是 libtool 提供的工具,可以自动为当前项目安装适当的文件以便使用 libtool,只要在 configure.in 中使用了‘AC_PROG_LIBTOOL’就要运行 libtoolize:libtoolize
运行 aclocal。aclocal 是 automake 提供的工具,可以自动为当前项目生成 aclocal.m4,它将为 configure.in 提供必要的宏定义。
po/POTFILES.in 是一个每行含有一个文件名的文件列表,po/Makefile 将在其中列举的每个文件中寻找需翻译的字符串。可以用这样的命令来生成 POTFILES.in:find . -name '*.[hc]' | xargs grep -l '_(' > po/POTFILES.in
进入 po 目录,将 POTFILES.in 提交到 cvs 中:cvs add POTFILES.in; cvs ci -m 'submit POTFILES.in' POTFILES.in
运行 gettextize。gettextize 是 gettext 提供的工具,可以自动为当前项目创建支持多语言的必要文件。它们包括 intl 目录下的所有文件,还有 po 目录下的 Makefile.in.in。
为了方便使用,还需要编制 nighttask.spec.in 文件。configure 将根据对系统的检测结果和用户设置,替换其中以‘@’起头和结尾的 autoconf 变量,它的内容如下:
%define ver @VERSION@
%define RELEASE 1
%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
%define prefix /usr
Summary: Night Task utility
Name: @PACKAGE@
Version: %ver
Release: %rel
Copyright: GPL
Group: System Environment/Shells
Source: %{name}-%{ver}.tar.gz
BuildRoot: /var/tmp/%{name}-%{ver}-root
%description
Night Task utility is a utility to help the user controll the long
task feasible.
%prep
%setup
%build
aclocal
libtoolize
aclocal
gettextize
automake -a
autoconf
./configure --prefix=%{prefix} --infodir=%{_infodir}
# 指定 prefix 和 infodir 是为了让生成的 RPM 包将文件安装到适当的位置,以便访问。
make
%install
rm -rf $RPM_BUILD_ROOT
make prefix=$RPM_BUILD_ROOT%{prefix} infodir=$RPM_BUILD_ROOT%{_infodir} install
# 此处需作相应设置。
%clean
rm -rf $RPM_BUILD_ROOT
%post
/sbin/install-info %{_infodir}/%{name}.info.gz %{_infodir}/dir
# 安装 info 文档。
%preun
if [ $1 = 0 ]; then
/sbin/install-info --delete %{_infodir}/%{name}.info.gz %{_infodir}/dir
fi
%files
%defattr(-, root, root)
%doc AUTHORS ChangeLog COPYING INSTALL NEW README
%attr(755, root, root) %{prefix}/bin/*
%{_infodir}/nighttask.info.gz
%{prefix}/share/locale/*/LC_MESSAGES/*.mo
%changelog
* Sun Jan 13 2002 Wang Li
- First nighttask RPM
注意,RedHat 自动以 gzip 压缩 info 文档,Mandrake 则自动以 bzip2 压缩 info 文档。因此,若在 Mandrake 下,应将上述所有 info.gz 改为 info.bz2。
运行 automake 和 autoconf:automake -a; autoconf
运行 configure 脚本:./configure
创建:make
至此,除 po 翻译尚未进行以外,nighttask 已成为能够以 .tar.gz 形式发行的软件包。
进入 po 目录,并生成 pot 文件:cd po; make nighttask.pot
若是首次翻译,则尚无 zh_CN.po 文件。则:cp nighttask.pot zh_CN.po; cvs add zh_CN.po
若是更新翻译,则 zh_CN.po 已存在,则:msgmerge zh_CN.po nighttask.pot > zh_CN.po
翻译 zh_CN.po 中的各个条目。
提交完成的译文:cvs ci -m 'zh_CN.po update' zh_CN.po
回到主目录并修改 configure.in:cd ..; vi configure.in
将 configure.in 中 ‘ALL_LINGUAS=""’ 改为 ‘ALL_LINGUAS="zh_CN"’。
重新运行 autoconf,及各创建步骤:autoconf; ./configure; make
此时只要适当安装, nighttask 就可以支持中文 locale。本文采用 RPM 安装方式。
通过运行 configure,已生成了 nighttask.spec,将其复制到 rpm 创建目录中:cp nighttask.spec /usr/src/redhat/SPECS
进入其它空目录中,使用 cvs 获取源代码:cd ..; mkdir tmp; cd tmp; cvs co nighttask
改变目录名,使之符合 rpm 的要求,即'软件包名-版本号’:mv nighttask nighttask-0.0
制作 tar 包:tar czf nighttask-0.0.tar.gz
复制到 rpm 的创建目录中:cp nighttask-0.0.tar.gz /usr/src/redhat/SOURCES
创建 rpm 包即可得到 nighttask 的源代码 RPM 包和二进制可执行 RPM 包:rpm -ba /usr/src/redhat/SPECS/nighttask.spec
安装可执行 RPM 包:rpm -ivh /usr/src/redhat/RPMS/i386/nighttask-0.0-1.i386.rpm
试用
nighttask -h 将看到 nighttask 的中文求助信息。
info nighttask 将看到 nighttask 的 info 文档。
此外,通过 nighttask.texi 还可以创建用于打印的 ps 文档。
进入 nighttask 的 doc 目录,创建 dvi 文档:cd doc; make dvi
从 dvi文档 生成 ps 文档:dvips -o nighttask.po nighttask.dvi |
|