Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2034071
  • 博文数量: 369
  • 博客积分: 10093
  • 博客等级: 上将
  • 技术积分: 4271
  • 用 户 组: 普通用户
  • 注册时间: 2005-03-21 00:59
文章分类

全部博文(369)

文章存档

2013年(1)

2011年(2)

2010年(10)

2009年(16)

2008年(33)

2007年(146)

2006年(160)

2005年(1)

分类: LINUX

2006-08-31 21:33:17

昨天有些事情把“正事”耽搁了,再次,先行向大家道歉了!另外,还发现IBM的网站上,同样有一篇和我这里类似的文章,不过侧重点不太一样,他背景交代得较为详尽,如果想了解这么做的原因,推荐看一下那篇文章:为多种 UNIX 平台编写软件.
好了,还是言归正传,书接前文,今天我将带领大家走一遍打包的流程。
姑且命名我们的项目为project1,首先建立项目目录:
xiaosuo@gentux skeleton $ mkdir project1
xiaosuo@gentux skeleton $ cd project1
xiaosuo@gentux project1 $ mkdir src
xiaosuo@gentux project1 $ cd src
遵从Linux下源码包目录的一般习惯,我们将源代码放到目录src下。
接下来我们在src目录下建立如下两个文件:
File: i18n.h

#ifndef _I18N_H_
#define _I18N_H_

#ifdef HAVE_CONFIG_H
#include
#endif

#ifdef ENABLE_NLS
#include
#define _(String) gettext(String)
#ifdef gettext_noop
#define N_(String) gettext_noop(String)
#else
#define N_(String) (String)
#endif
#else /* NLS is disabled */
#define _(String) (String)
#define N_(String) (String)
#define textdomain(String) (String)
#define gettext(String) (String)
#define dgettext(Domain,String) (String)
#define dcgettext(Domain,String,Type) (String)
#define bindtextdomain(Domain,Directory) (Domain)
#define bind_textdomain_codeset(Domain,Codeset) (Codeset)
#endif /* ENABLE_NLS */

#endif /* _I18N_H_ */
File: project1.c

#include
#include

#ifdef HAVE_CONFIG_H
#include
#endif

#ifdef ENABLE_NLS
        #include
#endif

#include "i18n.h"

int main(int argc, char *argv[])
{
#ifdef ENABLE_NLS
        bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
        bind_textdomain_codeset(GETTEXT_PACKAGE, getenv("LC_MESSAGES"));
        textdomain(GETTEXT_PACKAGE);
        setlocale(LC_ALL, "");
#endif

        printf(_("Hello, world!\n"));

        return 0;
}
文件i18n.h顾名思义,就是提供和i18n支持相关的一些宏定义。文件project1.c将是我们这个程序的入口文件,难道没有发现传说中的main函数么?不过让大家失望了,洋洋洒洒写了那么多,这个文件的功能还是如此的简单,只是打印"Hello, world!"到终端。其中被条件 ENABLE_NLS包裹起来的三行主要是和国际化相关,一般不需要改变,直接Copy就行了。宏_()需要简单的解释一下,这个宏在国际化选项打开的条件下将被gettext函数所替代,也就是说宏_()的参数,都能被翻译成用户相应的语言,所以,所有希望被翻译的字符串都应该用此宏包裹。
下面再建立三个文件:
File: src/Makefile.am

bin_PROGRAMS = project1

project1_SOURCES = \
        i18n.h  \
        project1.c
File: Makefile.am
SUBDIRS = src
File: configure.in

AC_INIT(configure.in)
AM_INIT_AUTOMAKE(project1, 0.0.1)
AM_CONFIG_HEADER(config.h)

dnl Checks for compiler and system libraries
AC_GNU_SOURCE
AC_PROG_CC
AC_HEADER_STDC
AC_ISC_POSIX
AM_PROG_CC_STDC
AM_PROG_LIBTOOL
AC_PROG_INSTALL

dnl Define the default CFLAGS
CFLAGS="-Wall"
AC_SUBST(CFLAGS)

dnl Checks for i18n support
GETTEXT_PACKAGE=project1
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Package name for gettext.])
dnl Languages which your application supports
ALL_LINGUAS="zh_CN"
AC_SUBST(ALL_LINGUAS)
AM_GNU_GETTEXT
AM_GNU_GETTEXT_VERSION([0.15])

dnl Set PACKAGE_LOCALE_DIR in config.h.
if test "x${prefix}" = "xNONE"; then
  AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${ac_default_prefix}/${DATADIRNAME}/locale",
                        [The package locale directory.])
else
  AC_DEFINE_UNQUOTED(PACKAGE_LOCALE_DIR, "${prefix}/${DATADIRNAME}/locale",
                        [The package locale directory.])
fi

dnl Set PACKAGE SOURCE DIR in config.h.
packagesrcdir=`cd $srcdir && pwd`

dnl Set PACKAGE PREFIX
if test "x${prefix}" = "xNONE"; then
  packageprefix=${ac_default_prefix}
  packageetcprefix=/
else
  packageprefix=${prefix}
  packageetcprefix=${prefix}
fi

packagedatadir=share
packagedocdir=doc/${PACKAGE}
packagepixmapsdir=share/pixmaps/${PACKAGE}
packagehelpdir=share/help/${PACKAGE}
packagemenudir=share/apps/${PACKAGE}
packagemandir=share/man/
packageetcdir=etc/${PACKAGE}

dnl Subst PACKAGE_DATA_DIR.
NO_PREFIX_PACKAGE_DATA_DIR="${packagedatadir}"
AC_SUBST(NO_PREFIX_PACKAGE_DATA_DIR)
PACKAGE_DATA_DIR="${packageprefix}/${packagedatadir}"
AC_SUBST(PACKAGE_DATA_DIR)

dnl Subst PACKAGE_DOC_DIR.
NO_PREFIX_PACKAGE_DOC_DIR="${packagedocdir}"
AC_SUBST(NO_PREFIX_PACKAGE_DOC_DIR)
PACKAGE_DOC_DIR="${packageprefix}/${packagedocdir}"
AC_SUBST(PACKAGE_DOC_DIR)

dnl Subst PACKAGE_PIXMAPS_DIR.
NO_PREFIX_PACKAGE_PIXMAPS_DIR="${packagepixmapsdir}"
AC_SUBST(NO_PREFIX_PACKAGE_PIXMAPS_DIR)
PACKAGE_PIXMAPS_DIR="${packageprefix}/${packagepixmapsdir}"
AC_SUBST(PACKAGE_PIXMAPS_DIR)

dnl Subst PACKAGE_HELP_DIR.
NO_PREFIX_PACKAGE_HELP_DIR="${packagehelpdir}"
AC_SUBST(NO_PREFIX_PACKAGE_HELP_DIR)
PACKAGE_HELP_DIR="${packageprefix}/${packagehelpdir}"
AC_SUBST(PACKAGE_HELP_DIR)

dnl Subst PACKAGE_MENU_DIR.
NO_PREFIX_PACKAGE_MENU_DIR="${packagemenudir}"
AC_SUBST(NO_PREFIX_PACKAGE_MENU_DIR)
PACKAGE_MENU_DIR="${packageprefix}/${packagemenudir}"
AC_SUBST(PACKAGE_MENU_DIR)

dnl Subset PACKAGE_MAN_DIR
NO_PREFIX_PACKAGE_MAN_DIR="${packagemandir}"
AC_SUBST(NO_PREFIX_PACKAGE_MAN_DIR)
PACKAGE_MAN_DIR="${packageprefix}/${packagemandir}"
AC_SUBST(PACKAGE_MAN_DIR)

dnl Subset PACKAGE_ETC_DIR
NO_PREFIX_PACKAGE_ETC_DIR="${packageetcdir}"
AC_SUBST(NO_PREFIX_PACKAGE_ETC_DIR)
PACKAGE_ETC_DIR="${packageetcprefix}/${packageetcdir}"
AC_SUBST(PACKAGE_ETC_DIR)

AC_DEFINE_UNQUOTED([PACKAGE_DATA_DIR], "${packageprefix}/${packagedatadir}",
                                   [The data directory.])
AC_DEFINE_UNQUOTED(PACKAGE_DOC_DIR, "${packageprefix}/${packagedocdir}",
                                   [The doc directory.])
AC_DEFINE_UNQUOTED(PACKAGE_PIXMAPS_DIR, "${packageprefix}/${packagepixmapsdir}",
                                   [The pixmaps directory.])
AC_DEFINE_UNQUOTED(PACKAGE_HELP_DIR, "${packageprefix}/${packagehelpdir}",
                                   [The help directory.])
AC_DEFINE_UNQUOTED(PACKAGE_MENU_DIR, "${packageprefix}/${packagemenudir}",
                                   [The menu directory.])
AC_DEFINE_UNQUOTED(PACKAGE_MAN_DIR, "${packageprefix}/${packagemandir}",
                                   [The man directory.])
AC_DEFINE_UNQUOTED(PACKAGE_ETC_DIR, "${packageetcprefix}/${packageetcdir}",
                                   [The etc directory.])
AC_DEFINE_UNQUOTED(PACKAGE_SOURCE_DIR, "${packagesrcdir}",
                                   [The source directory.])

AC_OUTPUT([
Makefile
src/Makefile
])
Makefile.am和configure.in撰写的详细说明我将略去,如有需要请参见相关教程和手册,Gnome上所列出的关于autoconf和automake的教程都很不错。实际上以上的程序只需要稍微作些修改,就能适应你程序的需求的。还有另外一点需要说明,我们这里为什么没有用autoscan呢?实际上也是没有多少必要的,并且autoscan生成的configure.in也并不是很理想,所以不如直接找一个现成的作些修改呢。如果你觉得你对于一些条件的检查做得不够,那么你可以用autoscan来帮你找到那些特定的条件查找宏,然后直接把那些宏添加到以上文件就ok了。
真麻烦,我写得都感觉疲倦了。可是,还得一步步来,建立一些必须的档案文件:
xiaosuo@gentux project1 $ touch NEWS README AUTHORS ChangeLog
上面列出的文件,你就看着自己的需求更改吧!
终于完成了约一半了,下面到了用些自动程序来代替我们完成些琐碎任务的时候了:
xiaosuo@gentux project1 $ gettextize -c -f --intl --no-changelog
Creating intl/ subdirectory
Creating po/ subdirectory
Copying file ABOUT-NLS
Copying file config.rpath
Copying file intl/bindtextdom.c
Copying file intl/ChangeLog
Copying file intl/config.charset
Copying file intl/dcgettext.c
Copying file intl/dcigettext.c
Copying file intl/dcngettext.c
Copying file intl/dgettext.c
Copying file intl/dngettext.c
Copying file intl/eval-plural.h
Copying file intl/explodename.c
Copying file intl/export.h
Copying file intl/finddomain.c
Copying file intl/gettext.c
Copying file intl/gettextP.h
Copying file intl/gmo.h
Copying file intl/hash-string.c
Copying file intl/hash-string.h
Copying file intl/intl-compat.c
Copying file intl/intl-exports.c
Copying file intl/l10nflist.c
Copying file intl/langprefs.c
Copying file intl/libgnuintl.h.in
Copying file intl/loadinfo.h
Copying file intl/loadmsgcat.c
Copying file intl/localcharset.c
Copying file intl/localcharset.h
Copying file intl/locale.alias
Copying file intl/localealias.c
Copying file intl/localename.c
Copying file intl/lock.c
Copying file intl/lock.h
Copying file intl/log.c
Copying file intl/Makefile.in
Copying file intl/ngettext.c
Copying file intl/os2compat.c
Copying file intl/os2compat.h
Copying file intl/osdep.c
Copying file intl/plural.c
Copying file intl/plural-exp.c
Copying file intl/plural-exp.h
Copying file intl/plural.y
Copying file intl/printf-args.c
Copying file intl/printf-args.h
Copying file intl/printf.c
Copying file intl/printf-parse.c
Copying file intl/printf-parse.h
Copying file intl/ref-add.sin
Copying file intl/ref-del.sin
Copying file intl/relocatable.c
Copying file intl/relocatable.h
Copying file intl/textdomain.c
Copying file intl/vasnprintf.c
Copying file intl/vasnprintf.h
Copying file intl/vasnwprintf.h
Copying file intl/VERSION
Copying file intl/version.c
Copying file intl/wprintf-parse.h
Copying file intl/xsize.h
Copying file po/Makefile.in.in
Copying file po/boldquot.sed
Copying file po/en@boldquot.header
Copying file po/en@quot.header
Copying file po/insert-header.sin
Copying file po/Makevars.template
Copying file po/quot.sed
Copying file po/remove-potcdate.sin
Copying file po/Rules-quot
Creating initial po/POTFILES.in
Creating directory m4
Copying file m4/codeset.m4
Copying file m4/gettext.m4
Copying file m4/glibc2.m4
Copying file m4/glibc21.m4
Copying file m4/iconv.m4
Copying file m4/intdiv0.m4
Copying file m4/intmax.m4
Copying file m4/inttypes_h.m4
Copying file m4/inttypes-h.m4
Copying file m4/inttypes-pri.m4
Copying file m4/lcmessage.m4
Copying file m4/lib-ld.m4
Copying file m4/lib-link.m4
Copying file m4/lib-prefix.m4
Copying file m4/lock.m4
Copying file m4/longdouble.m4
Copying file m4/longlong.m4
Copying file m4/nls.m4
Copying file m4/po.m4
Copying file m4/printf-posix.m4
Copying file m4/progtest.m4
Copying file m4/signed.m4
Copying file m4/size_max.m4
Copying file m4/stdint_h.m4
Copying file m4/uintmax_t.m4
Copying file m4/ulonglong.m4
Copying file m4/visibility.m4
Copying file m4/wchar_t.m4
Copying file m4/wint_t.m4
Copying file m4/xsize.m4
Updating Makefile.am (backup is in Makefile.am~)
Updating configure.in (backup is in configure.in~)

Please create po/Makevars from the template in po/Makevars.template.
You can then remove po/Makevars.template.

Please fill po/POTFILES.in as described in the documentation.

Please run 'aclocal -I m4' to regenerate the aclocal.m4 file.
You need aclocal from GNU automake 1.5 (or newer) to do this.
Then run 'autoconf' to regenerate the configure file.

You will also need config.guess and config.sub, which you can get from the CVS
of the 'config' project at The commands to fetch them
are
$ wget '*checkout*/config/config/config.guess'
$ wget '*checkout*/config/config/config.sub'

You might also want to copy the convenience header file gettext.h
from the /usr/share/gettext directory into your package.
It is a wrapper around that implements the configure --disable-nls
option.

Press Return to acknowledge the previous five paragraphs.

xiaosuo@gentux project1 $ libtoolize -c -f
You should add the contents of `/usr/share/aclocal/libtool.m4' to `aclocal.m4'.
xiaosuo@gentux project1 $ aclocal -I m4
xiaosuo@gentux project1 $ autoheader
xiaosuo@gentux project1 $ automake --add-missing -c --gnu
configure.in: installing `./install-sh'
configure.in: installing `./missing'
src/Makefile.am: installing `./depcomp'
Makefile.am: installing `./INSTALL'
Makefile.am: installing `./COPYING'
xiaosuo@gentux project1 $ autoconf
以上命令都成功返回后,查看一下当前目录:
xiaosuo@gentux project1 $ ls
ABOUT-NLS       ChangeLog     config.sub     COPYING     intl         Makefile.am~  po
aclocal.m4      config.guess  configure      depcomp     ltmain.sh    Makefile.in   README
AUTHORS         config.h.in   configure.in   INSTALL     m4           missing       src
autom4te.cache  config.rpath  configure.in~  install-sh  Makefile.am  NEWS
哇,好多文件啊,好有成就感,不知道的还以为都是你自己写的呢,够忽悠人的吧?
不过这一些都还没有结束,为了国际化的支持,我们还有些额外的工作要做。
xiaosuo@gentux project1 $ cd po
按照其中的注释更改Makevars.template,然后把它重名为Makevars(如果你是那种特懒的人,我悄悄告诉你,这个文件不改也可以,直接重命名行了。)
将包含需要翻译的字符串的文件名加入文件POTFILES.in,就象下面的样子:
File: POTFILES.in
# List of source files which contain translatable strings.
src/project1.c
是时侯提取待翻译字符串了:
xiaosuo@gentux po $ intltool-update -p
xiaosuo@gentux po $ ls
boldquot.sed        insert-header.sin  POTFILES.in   remove-potcdate.sin
en@boldquot.header  Makefile.in.in     project1.pot  Rules-quot
en@quot.header      Makevars           quot.sed
还记不记得我们在configure.in中定义了那种语言的支持?如果你茫然,那么我该批评你了,怎么一点儿都不认真,如果你没看,也应该能猜出来,肯定是中文了,谁让我们都是华夏儿女、炎黄子孙呢!好的,不和你罗嗦了,开始翻译喽!
首先:
xiaosuo@gentux po $ cp project1.pot zh_CN.po
接下来打开zh_CN.po进行翻译,注意你必须用UTF-8编码进行翻译工作,翻译后文件内容大体如下所示:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR , YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: project1 0.0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-08-29 21:48+0800\n"
"PO-Revision-Date: 2006-08-29 21:48+0800\n"
"Last-Translator: xiaosuo \n"
"Language-Team: xiaosuo \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: ../src/project1.c:19
#, c-format
msgid "Hello, world!\n"
msgstr "你好,世界!\n"
终于看以看看效果了:
xiaosuo@gentux project1 $ ./configure --prefix=`pwd`/test && make && make install
看着屏幕稀里哗啦地滚动着,好爽,似乎有些变态!
OK了,迫不及待得测试一下:
xiaosuo@gentux project1 $ ./test/bin/project1
你好,世界!
xiaosuo@gentux project1 $ export LANG=C
xiaosuo@gentux project1 $ export LC_ALL=C
xiaosuo@gentux project1 $ ./test/bin/project1
Hello, world!
哦,耶,中英文都支持!!!
做善后工作,打包!
xiaosuo@gentux project1 $ find . -name "*~" | xargs rm -f
xiaosuo@gentux project1 $ rm test -rf
xiaosuo@gentux project1 $ make distclean
        ... ...
xiaosuo@gentux project1 $ cd ../
xiaosuo@gentux skeleton $ tar cjf project1-0.0.1.tar.bz2 project1
好的,终于完成了打包的工作,接下来你就需要找个网站来发布你的软件了。在上注册个开源项目也许是个不错的选择。
注意事项:
  1. 当你需要更新你的zh_CN.po,或者是你的源代码文件中又多了待翻译的字符串之后,一定要用intltool-update -p更新*.pot后再开始翻译工作。
  2. 如果你又增加了其他语言的支持,那么你需要重新运行autoconf来生成新的configure脚本。
后记:
做完后,发现其中有些工作都是让人厌烦的重复性劳动,也许我们能让脚本来代替我们完成上面的工作!其实,直接用anjuta来创建项目也是一个不错的选择,尤其对于那些不熟悉vim/emacs的用户来说。
阅读(1720) | 评论(3) | 转发(0) |
0

上一篇:闰七夕

下一篇:周末杂记

给主人留下些什么吧!~~