C++coder必读---最详细Autoconf和automake说明(中英文翻译参考文档)

时间:2022-10-30 20:12:28

原文链接http://www.cnblogs.com/konyel/articles/1272101.html

一,内容简介 

*Autoconf和automake用于何处和他们所担任的角色。

*为什么要使用Autoconf和Automake。

*简要的介绍所有工具。

*一些高级的主题。 

1简要的介绍所有工具。

我们来思考为什么有以下这么多的工具和他们各自扮演的角色。

automake

autoconf

autoheader

aclocal

make 

2,一个标准的编译过程。

我们都知道,当你解压了tar一类的文件之后,标准的编译方法是像如下这样。

./configure --prefix=/foo/bar/
make
make check
su -
make install
我们要先记住两个最重要的观点,以下两个方面可以通过工具来管理的,而不是要我们手工写makefile:

1,配置编译相关的细节。

2,生成相关的一部分Makefile文件。

3,配置相关的细节 

我们来看看autoconf为我们做了什么工作:

1,属性的选择

2,依赖项的位置(如静态库,头文件等)

3,编译机器的特性  如:

  *编译器标志

  *函数名

4,安装的路径。

4,自动检测编译工作的细节 

不同的源码在编译的时候可能出现以下的情况:

1,非常通用的部分被autoconf打包。

2,一般通用性的部分被发布为第三方类库宏放在*.m4的文件中。

3,只用一次的部分被直接写到configure.in的文件中。

生成宏代码的工作由autoconf开完成,而第三方的类库包的关联则由aclocal来完成。

 

5,记录编译的细节

(1)一些类库的细节被记录在头文件中,以便容纳下整个包的内容(比如,config.h).处理这一项的工具是autoheader和autoconf。

(2)一些信息成为编译器的标示,链接,或其他处理:包括文件路径,一些不能写进config.h的信息,是通过autoconf和automake来处理的。

 

6,了解什么被编译了

(1)什么文件需要被编译?

(2)编译需要依赖什么文件?

(3)这些被编译的文件是什么类型?

(4)有什么编译的预检测可以运行?

检测哪些文件要被编译,怎么安装,怎么测试编译的合法性,和检测他们的依赖项,是automake的工作范围。

在进行automake处理的时候,编译已经在机器上处于准备完成的阶段。它只是处理一些琐碎的工作和运行编译而已。

 7,综合归类。

  然后我们把所有步骤写在一个文件之中,我们把它命名为autogen.sh。

这个文件的唯一作用就是按照正确的顺序执行以上我们提到的各种工具。

            #!/bin/sh
            aclocal
            autoheader
            automake --add-missing
            autoconf

实际上,这个文件常常要检测程序变量的正确性,它也常常要运行像autopiont这样的程序,或其他预备的脚本。

以上就是autoconf一些基本的步骤,下面我们来开始我们教程的最要内容。 

8,处理过视图。

(这个图并非出自这篇教程的,而是出自其他autoconf的参与者之手,你在其他的很多文章能看到它,我把他完全包括进来是因为它能很好的解释接下来我要讲的其他内容)

C++coder必读---最详细Autoconf和automake说明(中英文翻译参考文档) 

  

9,开发与发布。

前面我们看到的示意图我们看到打包一个程序我们需要做的工作,它只用少到不可思议的源文件,就让关系错综复杂的代码正确的变成我们需要的软件包。

回顾我们前面看到的安装程序所需要的步骤:

 ./configure --prefix=/foo/bar/

make make check su - make install
是的,这么简单你就能做到了。
 

 10,发布文件

(1)开发人员常常拥有众多的工具,而我们进行一个典型的编译并不需要怎么多。 (2)额外的工具常常是安装困难或运行缓慢的(特别是在linux中)。 (3)一些文件常常是变化的,但却不一定适合当前的编译环境。而他们却能安全的被发布,因为在编译时,一些相关的文件被发布包生成,使到他适合相应的机器。

比如,文档翻译程序就很难被很好的安装在不同的机器上。

11,发布编译过的程序 一种学院派的思想是:发布编译过的程序是浪费时间的,还不如直接在目标机器上生成。 相对的有人这么认为:所有程序在发布前都应该完美的编译打包. 但实际上我们是这样子做的:源码和编译好的文件都会发布,用户能直接使用二进制程序,也能从源码中重新生成程序。

 

 二,实践

12,说了这么多大道理和观点,让我们来点实际的操作吧。。。。

这是一个来自gtk文档的automake的文件片段,我们来看看这个文件写了什么?

bin_SCRIPTS = \
 gtkdoc-scanobj  \
 gtkdoc-scangobj \
...

gtkdocdatadir = $(datadir)/gtk-doc
gtkdocdata_DATA = \
 gtkdoc-common.pl \
 gtk-doc.xsl  \
 devhelp.xsl  \
...

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gtk-doc.pc

EXTRA_DIST= \
 MAINTAINERS \
 gtk-doc.pc.in \
...

dist-hook:
 mkdir $(distdir)/doc
 cp -pr $(srcdir)/doc/* $(distdir)/doc
 rm -rf $(distdir)/doc/CVS
 mkdir $(distdir)/db2man
 cp -pr $(srcdir)/db2man/* $(distdir)/db2man
...

 

1,文件类型

automake是会让不同的文件类型得到不同相应处理的工具。

以下是不同文件表示类型,标志,及其说明。 

数据文件 (foo_DATA)

通常是编译的基本文件,是一定要添加的项目。

头文件 (foo_HEADERS)

可执行二进制文件(foo_PROGRAMS)

通常生成自一组源码,安装为一个可执行文件,可以使用strip(瘦身指令)

脚本 (foo_SCRIPTS)

安装为一个可执行文件,你可以使用他们的文件名来传递(如,在configure中),不可以使用瘦身指令。

用户手册 (foo_MAN) 说明手册 (foo_TEXINFOS)

 

 类库(foo_LIBRARIES 和foo_LTLIBRARIES) 

特指生成文件是静态库或共享库,有时会调用libtool来生成。(这个超出了本文的讨论范围)

 

2,多个源文件生成一个程序

第一个最我们经常用到automake的地方就是我们要多个源文件生成一个目标文件的时候(比如,一个而二进制可执行文件)

 

bin_PROGRAMS = bug-buddy

bug_buddy_SOURCES = \
        $(bb_built_sources)     \
        bug-buddy.c             \
        bug-buddy.h             \
        md5-utils.c             \
        md5-utils.h             \
        bugzilla.c              \
        bugzilla.h              \
        cell-renderer-uri.c     \
        cell-renderer-uri.h     \
        config.c                \
        gdb-buddy.c             \
        libglade-buddy.h        \
        save-buddy.c            \
        save-buddy.h            \
        signal-buddy.c          \
        signal-buddy.h          \
        united-states-of-bug-buddy.c

在赋值之前, 先清除$(bb_built_sources)这个变量。

 运行晚make之后我们可以看到了上面的这些源代码生成一个叫 bug-buddy的可执行文件。前面我们提到我以上的这些内容我们将它写入makefile.am之中

 

继续我的前面的例子,Makefile.am文件包括一个代码行就是我们前面定义的变量bb_built_sources

 

bb_built_sources = \
        bb-marshal.c    \
        bb-marshal.h

bb-marshal.h: $(srcdir)/bb-marshal.list
        ...

bb-marshal.c: $(srcdir)/bb-marshal.list
        ...

 

这里需要注意的是automake不能被其他的特殊指令打断,他运行的方式运行automake的过程中,拷贝以上的代码进生成的Makefile文件。

注意变量$(srcdir)的用法,他是表示当前的文件目录,记住生成程序的文件夹和源代码的文件夹可能是不相同的。

 

接下来我们来看看一写automake实际的例子,你会从中很容易的学习到方法并写出你自己需要的automake.

3,子目录和附加文件

在一个项目中管理全局的文件是在根目录上,源码,文档和视图。管理着所有的子目录,因此在根目录下我们的Makefile.am文件会大概的这样写:

SUBDIRS = libsmil dtd po

EXTRA_DIST =   \
 libsmil.spec.in \
 libsmil.spec  \
 intltool-extract.in \
 intltool-merge.in \
 intltool-update.in

snap:
   cp libsmil.spec libsmil.spec.orig; \
   sed -e "s/\(^Version: \)\(.*\)/\1\2.`date +'%Y%m%d'`.snap/" libsmil.spec \
     > libsmil.spec.tmp; \
   mv libsmil.spec.tmp libsmil.spec; \
   $(MAKE) dist distdir=$(PACKAGE)-$(VERSION).`date +"%Y%m%d"`.snap; \
   mv libsmil.spec.orig libsmil.spec

 

注意根目录下的子目录不是列在SUBDIRS变量中,所以它在最后才被编译到。如果要根目录的文件夹安一定的时间编译,只需要将SUBDIRS的列表放在正确的地方。

 

以下是autoconf的实例文件

 

 

INCLUDES = $(LIBGLADE_CFLAGS)                                 

# build documentation when doing a distcheck.
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc

if HAVE_PYTHON
bin_SCRIPTS = libglade-convert
endif

pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libglade-2.0.pc

...

XMLCATALOG = /etc/xml/catalog

xmldir = $(datadir)/xml/libglade
xml_DATA = glade-2.0.dtd

install-data-local:
        -xmlcatalog --noout --add "system" \
          "http://glade.gnome.org/glade-2.0.dtd" \
          $(xmldir)/glade-2.0.dtd $(XMLCATALOG)

uninstall-local:
        -xmlcatalog --noout --del $(xmldir)/glade-2.0.dtd $(XMLCATALOG)

#small hack to get distcheck to work
clean-local:
        rm -f intl/po2tbl.sed .memdump

 

 

 

4,Autoconf

正如先前提到的,autoconf有许多编译时的检测和设置。

分解配置参数。

检测存在的各种变量和函数。

通过Makefile.am创建Makefile.in

通过config.h.in创建config.h文件


 

 

 

(续待)