怎么样正确使用automake手册?
GNU Automake
For version 1.3, 3 April 1998
David MacKenzie and Tom Tromey 王立 译目录
- 介绍
-
通用性概念
- 通用操作
- 深度
- 严格性
- 统一命名机制
- 派生变量是如何命名的
-
一些实例软件包
- 一个简单的例子,从起点到终点
- 一个经典的程序
- 创建etags和ctags
- 创建`Makefile.in'
-
扫描`configure.in'
- 配置需求
- Automake能够识别的其它事情
- 自动生成的aclocal.m4
- 由Automake支持的Autoconf宏
- 编写你自己的aclocal宏
- 顶层`Makefile.am'
-
创建程序和库
- 创建一个程序
- 创建一个库
- 对LIBOBJS和ALLOCA的特别处理
- 创建一个共享库
- 创建一个程序时使用的变量
- 对Yacc和Lex的支持
- C++和其它语言
- 自动de-ANSI-fication
- 自动的依赖性(dependency)跟踪
-
其它派生对象
- 可执行的脚本
- 头文件
- 与体系结构无关(Architecture-independent)的数据文件
- 已创建的源代码
-
其它GNU工具
- Emacs Lisp
- Gettext
- Guile
- Libtool
- Java
-
创建文档
- Texinfo
- Man手册
- 安装了些什么
- 清除了些什么
- 需要发布哪些文件
- 对测试套件(test suites)的支持
- 改变Automake的行为
-
其它规则
-
与
etags
之间的界面 - 处理新的文件扩展名
-
与
- 条件(Conditionals)
-
--gnu
and--gnits
的效果 -
--cygnus
的效果 - 什么时候Automake不够用
- 发布`Makefile.in'
- 未来的某些想法
- 索引
@dircategory GNU admin @direntry * automake: (automake). Making Makefile.in's
@dircategory Individual utilities @direntry * aclocal: (automake)Invoking aclocal. Generating aclocal.m4
Copyright (C) 1995, 96 Free Software Foundation, Inc.
这是GNU Automake文档的第一版,
并且是针对GNU Automake 1.3的。
自由软件基金会出版
59 Temple Place - Suite 330,
Boston, MA 02111-1307 USA
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by the Free Software Foundation.
只要版权声明和本许可声明保留在所有副本中,您就被授权制作和发行本手册的原文副本。
只要整个最终派生工作按照与本手册相同的许可声明发行,您就被授权按照与发行原文相同的条件复制和发行本手册的修改版本。
除了本许可声明应该使用由基金会批准的译文之外,您被授权按照与上述修改版本相同的条件复制和发行本手册的其它语言的译文。
本文档由王立翻译。 1999.12.17
译者在此声明:不对任何由译文错误或者对译文的误解承担任何责任。
介绍
Automake是一个从文件`Makefile.am'自动生成`Makefile.in' 的工具。每个`Makefile.am'基本上是一系列make
的宏定义(make规则也会偶尔出现)。生成的`Makefile.in's服从GNU Makefile标准。
GNU Makefile标准文档(参见GNU编码标准中的‘Makefile惯例’节)长、复杂,而且会发生改变。Automake的目的就是解除个人GNU维护者维护Makefile的负担(并且让Automake的维护者来承担这个负担)。
典型的Automake输入文件是一系列简单的宏定义。处理所有这样的文件以创建 `Makefile.in'。在一个项目(project)的每个目录中通常包含一个 `Makefile.am'。
Automake在几个方面对一个项目做了限制;例如它假定项目使用Autoconf (参见Autoconf手册),并且对`configure.in'的内容施加了某些限制。
为生成`Makefile.in',Automake需要perl
。但是由Automake创建的发布完全服从GNU标准,并且在创建中不需要perl
。
请把关于Automake的建议和bug发送到 automake-bugs@gnu.org。
通用性概念
一些基本概念将有助于理解Automake是如何工作的。
通用操作
Automake读入`Makefile.am'并且生成`Makefile.in'。在`Makefile.am'中定义的一些宏和目标(targets)指挥automake生成更多特定的代码;例如一个`bin_PROGRAMS'宏定义将生成一个需要被编译、连接的目标。
`Makefile.am'中的宏定义和目标被复制到生成的文件中。这使得你可以把任何代码添加到生成的`Makefile.in'文件中。例如,Automake的发布包含了非标准的cvs-dist
目标,Automake的维护者用它从他的版本控制系统中创建发布版本。
Automake不能识别GNU对make的扩展。在`Makefile.am'中使用这些扩展将导致错误或者令人不解的行为。
Automake试图明智地把注释和相邻的目标(或者变量定义)关联起来。
在`Makefile.am'中定义的目标通常覆盖了所有由automake
自动生成的拥有相似名字的目标。虽然Automake提供了这一功能,但最好避免使用它,因为有些时候生成的规则将是十分特别的。
类似地,在`Makefile.am'中定义的变量将覆盖任何通常由automake
创建的变量定义。该功能比覆盖目标定义的功能要常用得多。需要警告的是许多由 automake
生成的变量都被认为是内部使用的,并且它们的名字可能在未来的版本中改变。
在检验变量定义的时候,Automake将递归地检验定义中的变量引用。例如,如果Automake 在如下片断中搜索`foo_SOURCES'的内容。
xs = a.c b.c foo_SOURCES = c.c $(xs)
它将把文件`a.c'、 `b.c'和 `c.c'作为`foo_SOURCES' 的内容。
Automake还允许给出不被复制到输出中的注释;所有以`##'开头的行将被Automake彻底忽略。
作为惯例,`Makefile.am'的第一行是:
## Process this file with automake to produce Makefile.in
深度
automake
支持三种目录层次: “flat”、“shallow”和“deep”。
一个flat(平)包指的是所有文件都在一个目录中的包。为这类包提供的`Makefile.am' 缺少宏SUBDIRS
。这类包的一个例子是termutils
。
一个deep(深)包指的是所有的源代码都被储存在子目录中的包;顶层目录主要包含配置信息。GNU cpio
是这类包的一个很好的例子,GNU tar
也是。deep包的顶层`Makefile.am'将包括宏SUBDIRS
,但没有其它定义需要创建的对象的宏。
一个shallow(浅)包指的是主要的源代码储存在顶层目录中,而各个部分(典型的是库)则储存在子目录中的包。Automake本身就是这类包(GNU make
也是如此,它现在已经不使用automake
)。
严格性
Automake的目的是用于维护GNU包,它为适应那些希望使用它的人做出了一些努力,但并不指望应用所有的GNU惯例。
按照这个目标,Automake支持三级严格性---严格性指的是Automake 将如何检查包所服从的标准。
可用的严格性级别有:
- `foreign'(外来)
- Automake将仅仅检查那些为保证正确操作所必需的事项。例如,尽管GNU标准指出文件`NEWS'必须存在,在本方式下,并不需要它。该模式名来自于Automake 是被设计成用于GNU程序的事实的;它放松了标准模式的操作规则。
- `gnu'
- Automake将尽可能地检查包是否服从GNU标准。这是缺省设置。
- `gnits'
- Automake将按照还没有完成的Gnits标准进行检查。它们是基于GNU标准的,但更加详荆除非你是Gnits标准的参与奉献者,我们建议您在Gnits标准正式出版之前不要使用这一选项。
关于严格性级别的精确含义的详细说明,参见--gnu
和--gnits
的效果
统一命名机制
Automake变量通常服从统一的命名机制,以易于确定如何创建和安装程序(和其它派生对象)。这个机制还支持在运行configure
的时候确定应该创建那些对象。
在运行make
时,某些变量被用于确定应该创建那些对象。这些变量被称为主(primary)变量。例如,主变量PROGRAMS
保存了需要被编译和连接的程序的列表。
另一组变量用于确定应该把创建了的对象安装在哪里。这些变量在主变量之后命名,但是含有一个前缀以指出那个标准目录将作为安装目录。标准目录名在GNU标准中给出(参见GNU编码标准中的`为Directory Variables'节)。 Automake用pkglibdir
、pkgincludedir
和 pkgdatadir
扩展了这个列表;除了把`@PACKAGE@'附加其后之外,与非`pkg'版本是相同的。例如,pkglibdir
被定义为$(datadir)/@PACKAGE@
.
对于每个主变量,还有一个附加的变量,它的名字是在主变量名之前加一个`EXTRA_'。该变量用于储存根据configure
的运行结果,可能创建、也可能不创建的对象列表。引入该变量是因为Automake必须静态地知道需要创建的对象的完整列表以创建在所有情况下都能够工作的`Makefile.in'。
例如,在配置时刻cpio
确定创建哪些程序。一部分程序被安装在bindir
,还有一部分程序被安装在sbindir
:
EXTRA_PROGRAMS = mt rmt bin_PROGRAMS = cpio pax sbin_PROGRAMS = @PROGRAMS@
定义没有前缀的主变量(比如说PROGRAMS
)是错误的。
在构造变量名的时候,通常省略后缀`dir';因此我们使用 `bin_PROGRAMS'而不是`bindir_PROGRAMS'.
不是每种对象都可以安装在任何目录中。Automake将记录它们以试图找出错误。Automake还将诊断目录名中明显的拼写错误。
有时标准目录--即使在Automake扩展之后---是不够的。特别在有些时候,为了清晰起见,把对象安装到预定义目录的子目录中是十分有用的。为此,Automake允许你扩展可能的安装目录列表。如果定义了一个添加了后缀`dir'的变量(比如说`zardir'),则给定的前缀(比如`zar')就是合法的。
例如,在HTML支持成为Automake的一部分之前,你可以使用它安装原始的HTML文档。
htmldir = $(prefix)/html html_DATA = automake.html
特殊前缀`noinst'表示根本不会安装这些有问题的对象。
特殊前缀`check'表示仅仅在运行make check
命令的时候才创建这些有问题的对象。
可能的主变量名有`PROGRAMS'、`LIBRARIES'、 `LISP'、`SCRIPTS'、`DATA'、 `HEADERS'、`MANS'和`TEXINFOS'。
派生变量是如何命名的
有时Makefile变量名是从用户提供的某些文本中派生而来的。例如程序名被重写到Makefile宏名中。Automake把这些文本规范化,以使它可以不必服从Makefile的变量名规则。在名字中除了字母、数字和下划线之外的所有字符都将用下划线代替。例如,如果你的程序被命名为sniff-glue
,那么派生出的变量名将是sniff_glue_SOURCES
,而不是sniff-glue_SOURCES
。
一些实例软件包
一个简单的例子,从起点到终点
让我们假定你刚刚写完zardoz
,一个是你的头从一个漩涡漂流到另一个漩涡的程序。你已经使用了autoconf
以提供一个可移植的框架,但你的`Makefile.in'还未完成,所以你需要automake
。
第一步是更新你的`configure.in'以包含automake
需要的命令。完成这一步的最简单方式是在AC_INIT
之后添加AM_INIT_AUTOMAKE
:
AM_INIT_AUTOMAKE(zardoz, 1.0)
因为你的程序不含有任何复杂性的因素(例如,它不使用gettext
,它不需要共享库),你已经完成了这一步工作。很容易吧!
现在你必须重新生成`configure'。但为此,你需要告诉autoconf
如何找到你使用的新宏。完成该任务的最简单的方式是使用aclocal
程序为你生成你的`aclocal.m4'。但是等等...你已经有了一个`aclocal.m4',这是因为你必须为你的程序写一些宏。aclocal
允许你把你自己的宏放到 `acinclude.m4'中去,所以简单地改名并且运行:
mv aclocal.m4 acinclude.m4 aclocal autoconf
现在是你为zardoz
写的`Makefile.am'的时候了。 zardoz
是一个用户程序,所以你需要把它安装到其它用户程序安装的地方去。 zardoz
还有一些Texinfo文档。你的`configure.in'脚本使用 AC_REPLACE_FUNCS
,因此你需要与`@LIBOBJS@'连接。所以这里你写:
bin_PROGRAMS = zardoz zardoz_SOURCES = main.c head.c float.c vortex9.c gun.c zardoz_LDADD = @LIBOBJS@ info_TEXINFOS = zardoz.texi
现在你运行automake --add-missing
以生成你的`Makefile.in' 并且得到任何你可能需要的附加文件,现在你完成了你的任务!
一个经典的程序
hello
因为它经典的简单性和多用性而出名。本节展示Automake将被如何用于Hello包。下面的例子来自于最新的GNU Hello,但剔除了所有仅为维护者使用的代码和所有的版权注释。
当然,GNU Hello比您的传统的两行的代码具有更多的特征。GNU Hello是国际化的,进行选项处理,并且含有一个手册和一个测试套件。GNU Hello是一个deep包。
这里是来自于GNU Hello的`configure.in':
dnl Process this file with autoconf to produce a configure script. AC_INIT(src/hello.c) AM_INIT_AUTOMAKE(hello, 1.3.11) AM_CONFIG_HEADER(config.h) dnl Set of available languages. ALL_LINGUAS="de fr es ko nl no pl pt sl sv" dnl Checks for programs. AC_PROG_CC AC_ISC_POSIX dnl Checks for libraries. dnl Checks for header files. AC_STDC_HEADERS AC_HAVE_HEADERS(string.h fcntl.h sys/file.h sys/param.h) dnl Checks for library functions. AC_FUNC_ALLOCA dnl Check for st_blksize in struct stat AC_ST_BLKSIZE dnl internationalization macros AM_GNU_GETTEXT AC_OUTPUT([Makefile doc/Makefile intl/Makefile po/Makefile.in / src/Makefile tests/Makefile tests/hello], [chmod +x tests/hello])
宏`AM_'由Automake(或者Gettext库)提供;其它的是标准Autoconf宏。
顶层`Makefile.am':
EXTRA_DIST = BUGS ChangeLog.O SUBDIRS = doc intl po src tests
就像你所见到的,这里的所有工作实际上都是在子目录中完成的。
`po'和`intl'目录是gettextize
自动生成的;在这里我们不讨论它们。
在`doc/Makefile.am'中我们看到:
info_TEXINFOS = hello.texi hello_TEXINFOS = gpl.texi
它足以创建、安装并且发布Hello手册。
这里是`tests/Makefile.am':
TESTS = hello EXTRA_DIST = hello.in testdata
脚本`hello'是由configure
生成的,并且仅仅在测试时才生成。 make check
将运行这个测试。
最后我们有`src/Makefile.am',所有实际工作在此完成:
bin_PROGRAMS = hello hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h hello_LDADD = @INTLLIBS@ @ALLOCA@ localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=/"$(localedir)/"
创建etags和ctags
这里是另一个复杂一些的例子。它展示了如何从同一个源文件(`etags.c')生成两个程序(ctags
和etags
)。困难的部分是对 `etags.c'的每个编译需要不同的cpp
选项。
bin_PROGRAMS = etags ctags ctags_SOURCES = ctags_LDADD = ctags.o etags.o: etags.c $(COMPILE) -DETAGS_REGEXPS -c etags.c ctags.o: etags.c $(COMPILE) -DCTAGS -o ctags.o -c etags.c
其中ctags_SOURCES
被定义为空--这种方式表明没有替换隐含的值然而,隐含的值被用于从`etags.o'生成etags
。
ctags_LDADD
用于把`ctags.o'添加到连接行中。 ctags_DEPENDENCIES
由Automake生成。
如果你的编译器不接受`-c'和`-o',那么上述规则将不能工作。对此,最简单的修正是引入伪依赖(bogus dependency)(以避免由并行 make
所导致的问题):
etags.o: etags.c ctags.o $(COMPILE) -DETAGS_REGEXPS -c etags.c ctags.o: etags.c $(COMPILE) -DCTAGS -c etags.c && mv etags.o ctags.o
同样,如果使用了de-ANSI-fication的特征,这些显式规则将不能工作;支持它需要一些更多的工作:
etags._o: etags._c ctags.o $(COMPILE) -DETAGS_REGEXPS -c etags.c ctags._o: etags._c $(COMPILE) -DCTAGS -c etags.c && mv etags._o ctags.o
创建`Makefile.in'
为了为一个包创建所有的`Makefile.in',在顶层目录不带任何参数地运行automake
。 automake
将自动地寻找每个合适的`Makefile.am'(通过扫描 `configure.in';参见扫描`configure.in')并生成相应的`Makefile.in'。automake
认为包的组成是相当简单的;它假定包仅仅在顶层目录含有一个`configure.in'。如果你的包含有多个 `configure.in',那么你必须在每个含有`configure.in'的目录中运行automake
。
你偶尔可能需要给automake
参数;`.am'被添加到参数之后并且其结果将作为输入文件名。该特征通常仅仅用于自动重新创建一个过时的 `Makefile.in'。automake
必须总是在项目的最顶层目录中运行,即使用于重新生成某些子目录中的`Makefile.in'也是如此。这是因为automake
必须扫描`configure.in',并且因为在某些情况下,automake
根据`Makefile.in'在子目录中这一情况确定它的行为。
automake
接受以下选项:
-
-a
-
--add-missing
-
Automake要求一些通用文件在特定的位置存在。例如如果`configure.in'运行了
AC_CANONICAL_HOST
,就需要`config.guess'。 Automake与几个这样的文件一同发布;只要可能,该选项将把缺少的文件自动添加到包中。通常如果Automake告诉你缺少文件,试一下本选项。 -
--amdir=dir
- 在dir中而不是安装目录中,寻找Automake数据文件,它通常用于调试。
-
--build-dir=dir
-
告诉Automake创建目录在那里。本选项在把依赖性添加到由
make dist
生成的 `Makefile.in'中的时候使用;在其它情况下不应该使用它。 -
--cygnus
-
按照Cygnus规则,而不是GNU或者Gnits规则,生成`Makefile.in',详情请参见
--cygnus
的效果。 -
--foreign
- 把全局严格性设置成`foreign'。详情请参见严格性。
-
--gnits
-
把全局严格性设置成`gnits'。详情请参见
--gnu
和--gnits
的效果 -
--gnu
-
把全局严格性设置成`gnu'。详情请参见
--gnu
和--gnits
的效果。这是缺省严格性。 -
--help
- 打印命令行选项的概述并且退出。
-
-i
-
--include-deps
- 包含生成的`Makefile.in'中所有自动生成的依赖信息(参见自动的依赖性跟踪)。通常在制作发布版本时使用;参见需要发布哪些文件。
-
--generate-deps
-
生成一个连接了所有自动生成的依赖信息的文件(参见 自动的依赖性跟踪)文件,`.dep_segment'。通常在制作发布版本时使用;参见需要发布哪些文件。在维护为其它平台所制作的`SMakefile'或者makefile(`Makefile.DOS',等等,)时是有用的。它只能与
--include-deps
、--srcdir-name
和--build-dir
一同使用。如果给出了本选项,不会实行任何其他处理。 -
--no-force
-
通常
automake
创建在`configure.in'中提到的所有 `Makefile.in'。本选项仅仅更新那些按照它们的依赖性过时了的 `Makefile.in'。 -
-o dir
-
--output-dir=dir
- 把生成的`Makefile.in'放到目录dir中。通常每个`Makefile.in'在对应的`Makefile.am'所在的目录中创建。本选项被用于创建发布版本。
-
--srcdir-name=dir
-
告诉Automake与当前任务相关的源代码目录名。本选项在把依赖性引入由
make dist
生成的`Makefile.in'中时使用;它不应被用于其它情况。 -
-v
-
--verbose
- 让Automake打印关于被读入或创建的文件的信息。
-
--version
- 打印Automake的版本号并且退出。
扫描`configure.in'
Automake扫描包的`configure.in'以确定关于包的一些信息。 Automake需要一些autoconf
宏并且一些变量必须在 `configure.in'中定义。Automake还用来自`configure.in' 的信息以进一步修整它的输出。
为了简化维护,Automake还支持一些autoconf
宏。通过使用程序aclocal
,可以自动地把这些宏附加到你的`aclocal.m4'中。
配置需求
达到Automake要求的最简单方式就是使用宏AM_INIT_AUTOMAKE
(参见由Automake支持的Autoconf宏)。但是如果你愿意,你可以手工完成所需的各个步骤:
-
用
AC_SUBST
定义变量PACKAGE
和VERSION
。PACKAGE
应该是在捆绑发布的时候使用的包的名称。例如,Automake把PACKAGE
定义成`automake'。VERSION
应该是被开发的版本的版本号。我们建议你仅仅在你的包中定义版本号的地方创建`configure.in';这使得发布简单化了。 除非在`Gnits'模式(参见--gnu
和--gnits
的效果),Automake 不会对PACKAGE
或者VERSION
进行任何解释。 -
如果要安装一个程序或者一个脚本,使用宏
AC_ARG_PROGRAM
。 -
如果包不是平(flat)的,使用宏
AC_PROG_MAKE_SET
。 -
使用宏
AM_SANITY_CHECK
以确认创建环境的完整性。 -
如果包安装了任何脚本(参见可执行的脚本),使用宏
AM_PROG_INSTALL
。否则,使用AC_PROG_INSTALL
。 -
使用
AM_MISSING_PROG
以确认在创建环境中,程序aclocal
、autoconf
、automake
、autoheader
和makeinfo
是否存在。下面是如何完成这个任务:missing_dir=`cd $ac_aux_dir && pwd` AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir) AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir) AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir) AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir) AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
这里是Automake需要的,但是没有被AM_INIT_AUTOMAKE
运行的其它宏:
-
AC_OUTPUT
-
Automake用它确定创建那个文件。列出的名为
Makefile
的文件作为`Makefile'处理。对其它列出的文件进行不同的处理。目前唯一的不同是`Makefile'将被make distclean
删除,而其它的文件将被make clean
删除。
Automake能够识别的其它事情
Automake还将能够识别某些宏的使用并且适当地修整生成的`Makefile.in'。目前能够识别的宏以及它们的效果是:
-
AC_CONFIG_HEADER
-
Automake要求使用
AM_CONFIG_HEADER
,它类似于AC_CONFIG_HEADER
而且完成一些有用的Automake特定的工作。 -
AC_CONFIG_AUX_DIR
- Automake将在调用本宏时命名的目录中寻找各种求助脚本,例如`mkinstalldirs'。如果没找到,将在其它标准的位置(顶层目录中,或者在对应与当前`Makefile.am' 的源代码目录,任何一个都是合适的)中寻找脚本。 请帮助我:以给出寻找该目录的完整列表。
-
AC_PATH_XTRA
-
Automake将把由
AC_PATH_XTRA
定义的变量的定义插入每个创建C程序或者库的`Makefile.in'中。 -
AC_CANONICAL_HOST
-
AC_CHECK_TOOL
- Automake将确认`config.guess'和`config.sub'的存在。并且将引入`Makefile'变量`host_alias'和 `host_triplet'。
-
AC_CANONICAL_SYSTEM
-
它类似于
AC_CANONICAL_HOST
,此外还定义了`Makefile' 变量`build_alias'和`target_alias'。 -
AC_FUNC_ALLOCA
-
AC_FUNC_GETLOADAVG
-
AC_FUNC_MEMCMP
-
AC_STRUCT_ST_BLOCKS
-
AC_FUNC_FNMATCH
-
AM_FUNC_STRTOD
-
AC_REPLACE_FUNCS
-
AC_REPLACE_GNU_GETOPT
-
AM_WITH_REGEX
-
Automake将确认为对应于这些宏的对象生成了适当的依赖关系。此外,Automake将验证适当的源文件成为发布的一部分。使用这些宏,Automake并不需要任何C源代码,所以
automake -a
将不会安装源代码。详情请参见创建一个库 -
LIBOBJS
-
Automake将检测把`.o'文件添加到
LIBOBJS
中的语句,并且按照与在AC_REPLACE_FUNCS
中发现的文件相同的方式处理这些附加的文件。 -
AC_PROG_RANLIB
- 如果在包中创建了任何库,就需要它。
-
AC_PROG_CXX
- 如果包含了任何C++源代码,就需要它。
-
AM_PROG_LIBTOOL
-
Automake将启动为
libtool
所做的处理(参见Libtool手册)。 -
AC_PROG_YACC
- 如果找到了Yacc源文件,那么你必须使用这个宏或者在`configure.in' 中定义变量`YACC'。前者更好一些。
-
AC_DECL_YYTEXT
- 如果在包中有Lex源代码,需要使用这个宏。
-
AC_PROG_LEX
- 如果找到了Lex源代码,那么必须使用本宏。
-
ALL_LINGUAS
- 如果Automake发现在`configure.in'中设置了该变量,它将检查目录`po'以确认所有命名了的`.po' 文件都是存在的,并且所有存在的`.po'文件都被命了名。
-
AM_C_PROTOTYPES
- 在使用自动de-ANSI-fication时,需要它。参见自动de-ANSI-fication。
-
AM_GNU_GETTEXT
- 使用了GNU gettext的包需要使用本宏。(参见Gettext)。它将与gettext一起发布。如果Automake看到这个宏,Automake将确认包是否符合gettext的某些要求。
-
AM_MAINTAINER_MODE
-
该宏为
configure
添加一个`--enable-maintainer-mode' 选项。如果使用了本宏,automake
将关闭在生成的 `Makefile.in'中缺省的“maintainer-only”规则。在`Gnits'模式中,不允许使用本宏。(参见--gnu
和--gnits
的效果)。 -
AC_SUBST
-
AC_CHECK_TOOL
-
AC_CHECK_PROG
-
AC_CHECK_PROGS
-
AC_PATH_PROG
-
AC_PATH_PROGS
- 上述任意一个宏的第一个参数将在每个生成的`Makefile.in' 中自动地被定义为一个变量。
自动生成aclocal.m4
Automake包含了许多可以你的包中使用的的Autoconf宏;其中一些实际上是 Automake在某些情况下需要的。你必须在你的`aclocal.m4'中定义这些宏;否则autoconf
将不能找到它们。
程序aclocal
将基于`configure.in'的内容自动生成文件 `aclocal.m4'。它提供了一个不必四处寻找而获得Automake提供的宏的便利方式。此外,aclocal
机制对使用它的其它包来说,是可以扩展的。
在启动时,aclocal
扫描所有它能够找到的`.m4'文件,以寻找宏定义。而后它扫描`configure.in'。任何在第一步中提到的宏,以及它所需要的宏,将被放到`aclocal.m4'中。
如果`acinclude.m4'存在,它的内容将被自动包含在 `aclocal.m4'中。这对于把本地宏合并到`configure'是有用的。
aclocal
接受如下选项:
-
--acdir=dir
- 在目录dir中,而不是在安装目录中,寻找宏文件。这通常用于调试。
-
--help
- 打印命令行选项的概述并且退出。
-
-I dir
- 把目录dir添加到搜索`.m4'的目录列表中。
-
--output=file
- 把输出储存到文件file中,而不是`aclocal.m4'中。
-
--print-ac-dir
-
打印
aclocal
将搜索`m4'文件的目录名。当给出本选项的时候,不实施通常的处理。包可以用本选项确定应该把宏文件安装到哪里。 -
--verbose
- 打印它所检测的文件名。
-
--version
- 打印Automake的版本号并且退出。
由Automake支持的Autoconf宏
-
AM_CONFIG_HEADER
- Automake将生成规则以自动地重新生成config头文件。如果你使用本宏,你必须在你的源代码目录中创建文件`stamp-h.in'。它可以为空。
-
AM_CYGWIN32
-
检查本
configure
是否是在`Cygwin32'环境中运行。(FIXME xref)。如果是,把输出变量EXEEXT
定义为 `.exe';否则,把它定义为空字符串。Automake识别该宏并且用它生成在`Cygwin32'中可以自动工作的`Makefile.in'。在`Cygwin32'环境中,即使在命令行中没有明确指出,gcc
将生成文件名以`.exe'结尾的可执行文件。Automake向 `Makefile.in'添加特定的代码以适当地处理它。 -
AM_FUNC_STRTOD
-
如果不能使用函数
strtod
,或者不能正确地工作(例如在SunOS 5.4上),就把`strtod.o'添加到输出变量LIBOBJS
中。 -
AM_FUNC_ERROR_AT_LINE
-
如果没有找到
error_at_line
函数,就把`error.o'添加到LIBOBJS
中。 -
AM_FUNC_MKTIME
-
检查函数
mktime
。如果没有找到,就把`mktime.o'添加到`LIBOBJS'中。 -
AM_FUNC_OBSTACK
- 检查GNU obstacks代码;如果没有找到,就把`obstack.o'添加到`LIBOBJS'中。
-
AM_C_PROTOTYPES
- 检查编译器是否可以识别函数原型。如果可以识别,就定义`PROTOTYPES' 并且把输出变量`U'和`ANSI2KNR'设置为空。否则,把`U'设置成`_',并且把`ANSI2KNR' 设置成`./ansi2knr'。Automake使用这些值以实现自动de-ANSI-fication。
-
AM_HEADER_TIOCGWINSZ_NEEDS_SYS_IOCTL
-
如果使用
TIOCGWINSZ
需要`<sys/ioctl.h>',那么定义GWINSZ_IN_SYS_IOCTL
。否则,TIOCGWINSZ
可以在`<termios.h>'中发现。 -
AM_INIT_AUTOMAKE
-
运行大部分`configure.in'需要的多个宏。本宏有两个参数,包名称和版本号。缺省情况下,本宏用
AC_DEFINE
定义`PACKAGE'和 `VERSION'。可以通过添加非空的第三个参数以避免这一行为。 -
AM_PATH_LISPDIR
-
搜索程序
emacs
,并且,如果找到了,把输出变量lispdir
设置为到Emac的site-lisp目录的完整路径。 -
AM_PROG_CC_STDC
-
如果C编译器的缺省状态不是标准C(ANSI C),试图把一个选项添加到输出变量
CC
中以使得C编译器这样做。本宏尝试在各种系统中选择标准C的各种选项。如果编译器正确地处理函数原型,它就认为编译器处于标准C模式。 如果你使用本宏,你应该在调用它之后检查C编译器是否被设置成接受标准C;如果不是,shell变量am_cv_prog_cc_stdc
被设置成`no'。如果你按照标准C写你的源代码,你可以利用ansi2knr
选项创建它的非标准C版本。 -
AM_PROG_INSTALL
-
类似与
AC_PROG_INSTALL
,但还定义了INSTALL_SCRIPT
。 -
AM_PROG_LEX
-
类似与带有
AC_DECL_YYTEXT
的AC_PROG_LEX
,但在没有lex的系统上使用脚本missing
。 `HP-UX 10'是一个这样的系统。 -
AM_SANITY_CHECK
-
它检查并确保在创建目录中被创建的文件比源代码目录中的文件要新。在时钟设置不正确的系统中它可能失败。本宏在
AM_INIT_AUTOMAKE
中自动运行。 -
AM_SYS_POSIX_TERMIOS
-
检查系统中,是否可以使用POSIX termios头文件和函数。如果可以,就把shell变量
am_cv_sys_posix_termios
设置为`yes'。如果不能使用,就把am_cv_sys_posix_termios
设置为`no'。 -
AM_TYPE_PTRDIFF_T
- 如果类型`ptrdiff_t'是在`<stddef.h>'中定义的,就定义`HAVE_PTRDIFF_T'。
-
AM_WITH_DMALLOC
-
增加
dmalloc
包支持。如果用户用`--with-dmalloc'进行配置,那么定义WITH_DMALLOC
并且把`-ldmalloc'添加到LIBS
。包dmalloc
可以在ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz 找到。 -
AM_WITH_REGEX
-
把`--with-regex'添加到
configure
的命令行中。如果给出`--with-regex'(缺省设置),那么使用 `regex'常规表达式库,`regex.o' 被添加到`LIBOBJS'中,并且定义`WITH_REGEX'。如果给出`--without-regex',那么使用`rx' 常规表达式库,`rx.o'被添加到`LIBOBJS'中。
编写你自己的aclocal宏
aclocal不含有任何宏的任何内置信息,所以扩展你自己的宏是十分容易的。
它通常被用于那些需要为使用它的其它程序提供它们自己的Autoconf宏的库。例如gettext
库支持宏 AM_GNU_GETTEXT
,该宏将被任何使用gettext
的任何包所使用。在安装库的时候,它安装宏以便aclocal
可以找到它。
一个宏文件应该是一系列AC_DEFUN
'。aclocal还懂得AC_REQUIRE
,所以把每个宏储存在一个单独的文件中是安全的。
一个宏文件的文件名应该以`.m4'结尾。这类文件都应该安装在`$(datadir)/aclocal'中。
顶层`Makefile.am'
在非平(non-flat)包中,顶层`Makefile.am'必须告诉Automake 应该在那个子目录中进行创建。这通过变量SUBDIRS
来完成。
宏SUBDIRS
保存了需要进行各种创建的子目录列表。在生成的`Makefile'中的许多目标(例如,all
)即需要在本目录下运行,也需要在所有特定的子目录下运行。需要指出,出现在 SUBDIRS
中的子目录并不一定含有`Makefile.am' ;只要在配置(运行configuration)之后含有`Makefile'就行了。这使得你可以从不使用Automake的软件包(例如,gettext
)中引入库。在SUBDIRS
中提到的目录必须是当前目录的直接子目录。例如,你可以把`src/subdir'添加到SUBDIRS
中。
在一个深(deep)包中,顶层`Makefile.am'通常十分简短。例如,下面是Hello发布版中的`Makefile.am':
EXTRA_DIST = BUGS ChangeLog.O README-alpha SUBDIRS = doc intl po src tests
就像在GNU Inetutils
中的情况一样,如果你只需要创建整个包的一个子集,你可以覆盖变量SUBDIRS
。在你的 `Makefile.am'中包含:
SUBDIRS = @SUBDIRS@
而后在你的`configure.in'中,你可以指明:
SUBDIRS = "src doc lib po" AC_SUBST(SUBDIRS)
以上修改的结果是:automake将创建包以获得subdirs,但实际上在运行configure
之前并没有把目录列表包括进来。
SUBDIRS
可以包含配置替换(例如,`@DIRS@'); Automake本身并不实际检查这个变量的内容。
如果定义了SUBDIRS
,那么你的`configure.in' 必须包含AC_PROG_MAKE_SET
。
对SUBDIRS
的使用并不限于顶层目录中的`Makefile.am'。 Automake可以用于构造任意深度的包。
创建程序和库
Automake的大部分功能的目的是使创建C程序和库变得容易些。
创建一个程序
在一个含有将被创建成一个程序(而不是创建成一个库)的源代码的目录中,要使用主变量`PROGRAMS'。程序可以安装到`bindir'、 `sbindir'、`libexecdir'、`pkglibdir'中,或者根本不安装(`noinst')。
例如:
bin_PROGRAMS = hello
在这种简单的情况下,最终的`Makefile.in'将含有代码以生成名为hello
的一个程序。变量hello_SOURCES
用于确定哪些源代码应该被创建到可执行文件中去:
hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h
它将导致所有提及的`.c'文件被编译成对应的`.o' 文件。而后被一同连接以生成`hello'。
如果需要`prog_SOURCES',但并未定义它,那么它被缺省地设置成单个文件`prog.c'。在上面的例子中,对hello_SOURCES
的定义实际上是多余的。
可以把多个程序创建到一个目录中。多个程序可以共享一个源代码文件。源代码文件必须在需要它的每个`_SOURCES'中列出。
出现在`_SOURCES'中的头文件将被包含在发布版本中,其它的头文件将被忽略。因为它并不明显,你不应该把由`configure'生成的头文件包含在变量`_SOURCES'中;不应该发布这个文件。也可以列出lex(`.l')和yacc(`.y')文件;参见对Yacc和Lex的支持。
即使不是所有的文件在所有的情况下都需要被创建,Automake也必须知道所有可能被连接到程序中的源文件。所有仅仅是可能被创建的文件应该被适当地添加到变量`EXTRA_'中。例如,如果`hello-linux.c' 是有条件地被包含在hello
中,`Makefile.am'应该包括:
EXTRA_hello_SOURCES = hello-linux.c
类似地,有时候需要在配置的时刻确定创建那些程序。例如GNU cpio
仅仅在特殊情况下才创建mt
和rmt
。
在这种情况下,你必须把可能创建的所有程序都告诉automake
,但同时使生成的`Makefile.in'使用由configure
指明的程序。这可以通过在EXTRA_PROGRAMS
中列出所有可能创建的程序的同时,把configure
提供的值的替换到每个`_PROGRAMS'变量的定义中,来完成。
如果你需要和configure
没有找到的库相连接,你可以使用LDADD
来完成。该变量实际上可以用于把任何选项添加到连接器的命令行中。
有时,要在一个目录中创建多个程序,但并不共享相同的连接时刻需求(link-time requirement)。在这种情况下,你可以使用变量`prog_LDADD' (其中prog是出现在某些`_PROGRAMS'变量中的程序名)来覆盖全局的LDADD
。(对于某个程序来说,如果存在这个变量,那么那个程序的连接就不使用LDADD
。)
例如,在GNU cpio中,pax
、cpio
和mt
需要和库`libcpio.a'连接。然而,rmt
在同一个目录中创建,并且不需要与`libcpio.a'连接。此外,mt
和rmt
也仅仅在这种结构下创建。这里是cpio的`src/Makefile.am' 内容(有删节):
bin_PROGRAMS = cpio pax @MT@ libexec_PROGRAMS = @RMT@ EXTRA_PROGRAMS = mt rmt LDADD = ../lib/libcpio.a @INTLLIBS@ rmt_LDADD = cpio_SOURCES = ... pax_SOURCES = ... mt_SOURCES = ... rmt_SOURCES = ...
变量`prog_LDADD'并不适用与传递程序特定的连接器选项(除了`-l'和`-L'之外)。所以,为此请使用变量`prog_LDFLAGS'。
有时候,是否创建一个程序依赖于不属于那个程序的某些其它目标。通过使用变量`prog_DEPENDENCIES'可以实现该功能。每个程序都依赖于这个变量的内容,但是不对它进行进一步的解释。
如果没有给出`prog_DEPENDENCIES',它就由Automake来计算。自动获取的值是进行了大部分配置替换后的`prog_LDADD'内容,即删除了`-l'和`-L'选项。没有进行的配置替换仅仅是 `@LIBOBJS@' and `@ALLOCA@';没有进行这些替换是因为它们不会使生成的`prog_DEPENDENCIES'含有非法的值。
创建一个库
创建库与创建程序十分类似。在这种情况下,主变量的名字是`LIBRARIES'。库可以安装到libdir
或pkglibdir
之中。
关于如何使用Libtool和主变量`LTLIBRARIES'创建共享库的详情,请参见创建共享库。
每个`_LIBRARIES'变量都是需要被创建的库的列表。例如创建一个名为`libcpio.a'的库,但并不安装它,你可以写:
noinst_LIBRARIES = libcpio.a
确定那些源代码应该被创建到库中的方式与创建程序的情况完全相同,是通过变量`_SOURCES'。需要指出的是,库的名字是规范化的(参见派生变量是如何命名的),所以对应与`liblob.a'的`_SOURCES'变量对应的变量名为`liblob_a_SOURCES',而不是`liblob.a_SOURCES'。
通过使用变量`library_LIBADD',可以把额外的对象添加到库中。这应该由configure
确定的对象使用。再看看cpio:
libcpio_a_LIBADD = @LIBOBJS@ @ALLOCA@
对LIBOBJS和ALLOCA的特别处理
Automake显式地识别对@LIBOBJS@
和@ALLOCA@
的使用,并用该信息,以及从 `configure.in'中派生出的LIBOBJS
文件列表,把适当的源文件自动添加到发布版本中。(参见需要发布哪些文件)。这些源文件还按照依赖跟踪机制进行自动处理,参见自动依赖跟踪。
在任何`_LDADD'或`_LIBADD'变量中, @LIBOBJS@
和@ALLOCA@
都将被自动识别出来。
创建一个共享库
创建共享库是一件相对复杂的事情。为此,提供了GNU Libtool以使我们可以按照与平台无关的方式创建共享库(参见Libtool手册)。
Automake使用Libtool来创建在主变量`LTLIBRARIES'中声明的库。每个`_LTLIBRARIES'变量都是一个需要创建的共享库的列表。例如,为了创建一个名为`libgettext.a'的库和它对应的共享库,并且把它安装到`libdir',可以写:
lib_LTLIBRARIES = libgettext.la
需要指出的是:共享库必须被安装,所以不允许使用 `noinst_LTLIBRARIES'和`check_LTLIBRARIES'。
对于每个库,变量`library_LIBADD'包含了需要被添加到共享库中的额外的libtool对象(`.lo'文件)。变量`library_LDFLAGS'包含了所有附加的libtool选项,例如`-version-info'或者`-static'。
普通的库可能需要使用@LIBOBJS@
,而libtool库必须是使用 @LTLIBOBJS@
。必须这样做是因为libtool所操作的目标文件并不仅仅是`.o'。libtool手册包含了关于这个问题的细节。
对于安装在某些目录中的库,automake
将自动提供适当的 `-rpath'选项。然而,对于那些在配置时刻才能都确定的库(因而必须在EXTRA_LTLIBRARIES
中给出),automake
并不知道它们最终安装的目录;对于这类库,你必须把 `-rpath'选项手工地添加到适当的`_LDFLAGS' 变量中去。
详情请参见Libtool手册。
创建一个程序时使用的变量
有时有必要知道那个`Makefile'变量被Automake用于编译;例如在某些特殊情况下,你可能需要完成你自己的编译任务。
有些变量是从Autoconf中继承而来的;它们是CC
、 CFLAGS
、CPPFLAGS
、DEFS
、 LDFLAGS
和LIBS
。
还有一些附加的变量是Automake自行定义的:
-
INCLUDES
-
一个`-I'选项的列表。如果你需要包含特殊的目录,你可以在你的`Makefile.am'中设置它。
automake
已经自动地提供了一些`-I'选项。特别地,它生成`-I$(srcdir)'和一个指向保存了 `config.h'的目录的`-I'选项(如果你已经使用了AC_CONFIG_HEADER
或者AM_CONFIG_HEADER
)。 除了`-I'以外,INCLUDES
实际上还可以用于添加任何cpp
选项。例如,有时用它把任意的`-D'选项传递给编译器。 -
COMPILE
- 实际用于编译C源文件的命令。文件名被添加到它的后面以形成完整的命令行。
-
LINK
- 实际用于连接C程序的命令。
对Yacc和Lex的支持
Automake对Yacc和Lex有一些特殊的支持。
Automake假定由yacc(或lex)生成的`.c'文件是以输入文件名为基础命名的。就是说,对于yacc源文件`foo.y', automake将认为生成的中间文件是`foo.c'(而不是更加传统的 `y.tab.c')。
yacc源文件的扩展名被用于确定生成的`C'或`C++' 文件的扩展名。使用扩展名`.y'的文件将被转化成 `.c'文件;类似地,扩展名`.yy'转化成 `.cc';`.y++'转化成`c++'; `.yxx'转化成`.cxx';类似地,Lex源文件可以用于生成`C'或者`C++';扩展名 `.l'、`.ll'、`.l++'和 `.lxx'都可以被识别。
你不应该在任何`SOURCES'变量中明确地提及中间的(`C'或者`C++')文件;只要列出源文件就可以了。
由yacc(或lex)生成的中间文件将被包含在由它创建的任何发布版本中。这样用户就不需要拥有yacc或lex了。
如果出现了yacc源文件,那么你的`configure.in'必须定义变量`YACC'。完成这个任务最容易的方式是使用宏`AC_PROG_YACC'。
相似地,如果出现了lex源文件,那么你的`configure.in' 必须定义变量`LEX'。你可以用宏`AC_PROG_LEX' 来完成这个工作。Automake对lex的支持还要求你使用宏 `AC_DECL_YYTEXT'--automake需要知道 `LEX_OUTPUT_ROOT'的值。
Automake允许在一个程序中使用多个yacc (或lex)源文件。 Automake使用一个称为ylwrap
的小程序在子目录中运行 yacc
(或者lex
)。必须这样做是因为 yacc的输出文件名被修改了,并且并行的make可以同时地处理多于一个的yacc实例。ylwrap
和automake一同发布。它应该出现在由`AC_CONFIG_AUX_DIR'给出的目录,如果没有在`configure.in'中给出这个宏,它就应该出现在当前目录中。
对于yacc
,仅仅管理锁是不够的。yacc
的输出还总是在内部使用相同的符号名,所以不可能把两个yacc
解析器(parser)连接到同一个可执行文件中。
我们建议使用如下在gdb
中应用的改名方式:
#defineyymaxdepth c_maxdepth #defineyyparsec_parse #defineyylexc_lex #defineyyerrorc_error #defineyylvalc_lval #defineyycharc_char #defineyydebugc_debu
本文地址:http://www.45fan.com/a/question/67651.html