什么是 GNU helloGNU hello 是 GNU 推出的 hello world 软件,就是将入门的 hello world,以正规的 GNU 规范来实现,从而来展示 Unix-like 系统下开发软件的一些常用技术和软件的组织方法。麻雀虽小,五脏俱全,GNU hello 虽然只是一个 hello world,却包含了如下几项技术:
  • Automake 和 Autoconf:生成编译配置脚本
  • Gnulib:程序的基本函数库 
  • Gettext:国际化支持
  •  getopt:命令行参数支持 
  • help2man:用程序的--help选项输出生成manpage
  •  Texinfo:编写程序文档
  • 如何学习 GNU hello最好的方式莫过于自己参照 GNU hello 弄个自己的 hello world 出来,把其中的各项有用技术都自己玩个遍。只看书永远没有实践来得实在,不是么?
    程序主要的新东西自己手写,一些体力劳动就直接复制粘贴了。最终出来的内容不一定与 GNU hello 完全相同。
    本篇学习内容基本的程序文件组织方式
  • 基本的 Autoconf 和 Automake 配置文件写法及其原理
  • 好了,现在开始!
    程序文件的组织严格来说,一个程序并没有什么标准的组织规范,任何组织形式都是可以的。但是良好的程序文件组织结构可以让人快速定位开发文件,更好地管理项目。在 长期的实践中,Unix社区对一些常见文件的组织逐渐形成了一些传统,这些传统不仅是经受了时间的考验,也能让别人更好的了解自己的项目文件组织结构。
    在 GNU hello 中,文件是这样组织的(设“/”是代码根目录)
  • \:根目录存放automake和autoconf等配置文件,以及程序的一些说明文件(NEWS、Changelg、COPYING、INSTALL、AUTHORS等)
  • build-aux:automake 和 autoconf 自动生成的一些脚本
  • contrib:暂时不明
  • doc:程序文档
  • gnulib:Gnulib 的各文件
  • man:manpage存放地
  • po:gettext 翻译文件
  • src:程序源文件
  • tests:测试脚本
  • 在其他项目中,我见过的有doc、man、po和src,这些应该是约定俗成的命名。另外会生成库文件的项目不少是把库文件放在lib目录下的。
    Autoconf 和 Automake它们是干啥的?Unix下的软件,编译安装一般来说是要运行如下三条命令:
    1../configure 

    2.make 

    3.make install
     
    make是通过Makefile里指定的命令与目标来进行相应操作的程序,可以简单地理解为一串指令的集合(当然, 它远远不止于此)。用它就不必为编译代码写一条条的指令,只要把相关的指令写在Makefile里,直接make就行了。
    然而不同的系统里装的软件不一样。可能一台机子里装了gcc,另一台机子里装的是cc。为了使Makefile能在所有机子里通用,就了有 configure脚本。代码里并不带有Makefile,只有一个模板文件Makefile.in,里面用变量来定义要使用的命令,由 configure脚本将检测到的工具填入Makefile.in生成Makefile。
    但是不论是configure脚本还是Makefile,都并不是两句话可以写完的,而其内容多是类似的重复内容,于是就有了autoconf和automake。它们通过一些相对简单的语法来生成标准的configure脚本和Makefile。
    准备工作写一个最简单的hello world,存为src/hello.c:
     1.#include <stdio.h>
    2
    3.int
    4.main (int argc, char *argv[])
    5.{
    6.  printf ("hello world!");
    7.  return 0;
    8.}
     
     编写configure.acconfigure.ac是autoconf的配置文件,可以通过autoscan来辅助生成。旧版本的autoconf使用configure.in,现在这两个文件名都是通用的
    在顶层目录运行autoscan,软件自动生成configure.scan,这是一个根据现有代码生成的configure.ac模板,将它另存为如下的configure.ac文件:
     01.# 初始化autoconf,这句必须写在其他之前。定义的参数分别为软件名,版本号,维护地址(网站/邮件)
    02.AC_INIT([TS Hello][0.1],[tigersoldi&lt;at&gt;gmail&lt;dot&gt;com])
    03.# [可选]定义生成的辅助文件的目录,默认是与configure.ac同目录
    04.AC_CONFIG_AUX_DIR([build-aux])
    05.# 初始化automake
    06.AM_INIT_AUTOMAKE([readme-alpha])
    07.# 定义需要的autoconf最低版本,这是autoscan自动生成的,未必需要这么高的版本
    08.AC_PREREQ([2.63])
    09.# 定义源代码的路径,通过指定源代码目录内一个存在的文件来指定
    10.AC_CONFIG_SRCDIR([src/hello.c])
    11.# 检测C编译器
    12.AC_PROG_CC
    13.# 生成配置文件,配置文件都是将`配置文件.in'进行变量替换后得到的
    14.AC_CONFIG_FILES([Makefile src/Makefile])
    15.# 生成上面要求输出的文件
    16.AC_OUTPUT
     
      编写Makefile.am与autoconf类似,automake的配置文件是Makefile.am,它会用此来生成Makefile.in文件,该文件是configure脚本用来生成Makefile文件的模板。
    与configure.ac不同,我们要为每个文件夹写一个Makefile.am文件
    根目录下的Makefile.am文件很简单,它不用做任何事情, 只要告诉make它有个子目录src,让make去操作src目录:
     1.#处理如下子文件夹
    2.SUBDIRS = src
     src目录下的Makefile.am指定了我们要编译的程序及其文件:
     1.# 定义要编译的程序hello,可以有多个,用空白符(空格、TAB、行末加了`\'的换行)分开
    2.bin_PROGRAMS = hello
    3.# 定义hello的源文件,必须以`<程序名>_SOURCES'的形式来定义,
    4.# <程序名>就是bin_PROGRAMS中定义的程序之一,同样可以有多个源程序
    5.hello_SOURCES = hello.c
     
      编译程序文件都准备好后,就可以开始编译了。在编译之前,我们先让autoconf和automake生成我们需要的文件(确保在程序根目录):
     

    01
    .# 将configure.ac里所需要的M4宏复制到文件夹中
    02.aclocal
    03.# 通过configure.ac生成configure脚本
    04.autoconf
    05.# 创建build-aux文件夹
    06.mkdir build-aux
    07.# 创建GNU要求的说明文件
    08.touch NEWS README AUTHORS ChangeLog
    09.# 通过Makefile.am生成Makefile.in模板
    10.automake --add-missing --copy
     
     
    其中,aclocal是为autoconf进行准备工作的。
    automake默认是GNU模式,GNU规范要求程序包含(NEWS README AUTHORS ChangeLog)等说明文件,我们用touch暂创建几个临时文件上去。
    automake还需要创建一些辅助脚本,这些脚本由--add-missing选项添加到目录中。由于在configure.ac里用 AC_CONFIG_AUX_DIR定义到了build-aux目录下,我们要先创建这个目录。如果没有指定--copy,那么创建的是指向 automake安装目录相应文件的符号链接,指定后是直接复制一份。
    可以看到autoconf创建了configure脚本,而automake则在程序根目录和src子目录下创建了Makefile.in,接下来就用configure脚本配合Makefile.in来生成Makefile:
    1../configure
    由于我们在configure.ac里用AC_CONFIG_FILES指定了生成Makefile和src/Makefile两个文 件,configure脚本通过相应的.in文件替换到检测到的相应变量后生成。注意生成的文件不仅限于Makefile,任何文件名都是可以的,只要它 有.in模板。
    有了Makefile就可以make啦:
    1.make all
    直接用make也可以。all是指定的目标,也是一个约定俗成的目标(这是Makefile指定的,不同Makefile可以指定不同的目标,只要把它放在第一个就行),它的作用是编译程序。
    于是现在可以执行Hello world了:
     
    1../src/hello
     
     可以看到我的hello world出现了:-)
    换一个目标试试:
    1.make install
     install也是个约定俗成的目标,它把我们的软件安装到系统中。现在可以直接输入hello来运行软件了。
    有安装自然也有卸载,卸载的目标是uninstall。
    还可以用make clean来清除编译出来的文件。
    posted on 2010-10-18 17:15  一个人的天空@  阅读(1599)  评论(0编辑  收藏  举报