目录
该章介绍Automake如何工作。
3.1 General Operation
Automake读取Makefile.am以生成Makefile.in。Makefile.am中定义的某些变量和规则会告诉Automake生成更具体的规则。比如bin_PROGRAMS变量定义了生成编译和链接程序的规则。
Makefile.am文件中大部分的变量和规则一般会原样拷贝到生成的Makefile.in文件中(Makefile.in中还包括其他一些Makefile.am中没有的规则和变量,Makefile.am拷贝过来的内容只占Makefile.in的一部分*),但变量定义会在规则前边。
注意:Automake无法识别大部分GNU make扩展,如果在Makefile.am中使用这些扩展会报错或导致其他奇怪情况。
一个例外是GNU make的附加操作符 +=,Automake支持该操作符。该操作符会将其右侧参数附加到左侧变量上。Automake会将该操作符解释为普通的 = 操作符,所以make程序都可以正常操作 +=。
通常,对于不寻常的Makefile结构,Automake无法正常解析,所以对于空白字符的使用要避免出现奇怪的行为。例如,在一个target和其后的“:”之间不要使用TAB字符,及变量赋值时不要有TAB*缩进等。在targe命名时使用复杂的宏也会导致麻烦:
% cat Makefile.am
$(FOO:=x): bar
% automake
Makefile.am:1: bad characters in variable name ’$(FOO’
Makefile.am:1: ’:=’-style assignments are not portable
Makefile.am文件中定义的规则会覆盖automake将要自动生成的具有相似名字的规则。虽然Automake支持该特性,但最后避免使用该特性,因为有些自动生成的规则比较特殊。
类似的,在Makefile.am中定义或在configure.ac中通过AC_SUBSET定义的变量会覆盖automake将要生成的相同变量。该特性相比规则覆盖特性更常用。注意,automake生成的很多变量都是只在内部使用,未来版本中可能会发生变化。
当检查某个变量的定义时,Automake会递归检查变量定义中的引用。例如假设Automake在查看foo_SOURCES变量的内容:
xs = a.c b.c
foo_SOURCES = c.c $(xs)
它会使用a.c、b.c和c.c文件作为foo_SOURCES变量的内容。
以 ## 开头( ## 前边可以有空白字符)的注释行不会被拷贝到后续生成的文件中(包括Makefile.in和Makefile)。(以 # 开头的注释行在autotools执行过程中会被拷贝到后续生成的Makefile.in和Makefile中,在其中仍以相同注释形式存在)
在Makefile.am第一行通常有如下注释:
## Process this file with automake to produce Makefile.in
3.2 Strictness
Automake通常用于维护GNU packages。它有一些特性可以使用户在使用过程有一些不满足GNU约束的行为。
Automake支持有三种严格性——严格性是指Automake检查标准一致性时的严格程度:
- foreign
Automake只会检查适当操作中确实需要的标准。例如,GNU标准要求的NEWS文件,在该模式下就不做要求。该严格性还会关闭一些默认警告(大部分是可移植性警告)。通过该严格性名字就可以看出Automake在程序构建中使用的规则不是标准模式下的操作。 - gnu
Automake会尽可能检查以使packages服从GNU 标准。这是默认严格性。 - gnits
Automake会检查是否服从Gnits standards(尚未发布)。该标准基于GNU标准,但比其更详细。除非Gnits标准发布,不然尽量避免使用该严格性检查。
3.3 The Uniform Naming Scheme
Automake变量通常服从一个统一命名机制(uniform naming scheme)来决定哪些程序或目标文件需要编译和安装。该机制还支持在configure过程中决定哪些需要编译。
在make过程中,某个变量用于决定哪些目标文件需要编译生成,该变量名字通常是几个片段串接在一起组成的。告诉automake正在编译什么的片段通常称为关键字(primary)。例如,RPOGRAMS关键字指定一个需要编译链接的程序的列表。
变量名的另一部分决定编译生成的目录文件要安装到哪。这一部分称为关键字的前缀,它指定某标准目录作为安装目录。标准目录是GNU标准定义的。Automake扩展了标准目录范围,包括pkgdatadir、pkgincludedir、pkglibdir和pkglibexecdir。这与没有pkg前缀的目录变量(如pkglibdir相对于libdir)相比,只是在后边附加了’$(PACKAGE)’。例如,pkglibdir变量被定义为’$(libdir)/$(PACKAGE)’。(PACKAGE 变量值是 configure.ac文件中 AC_INIT 宏的第一个参数的全小写字符串)
对于每个关键字,有种特殊的变量命名方式是在关键字前边加上EXTRA_。该方式命令的变量指定了一系列目标文件,这些目标文件可能被编译也可能不被编译的,这由configure脚本决定。需要这种方式命名的变量是因为Automake需要静态的知道所有可能被编译的目标文件,以此来生成可在所有情况下执行的Makefile.in。
EXTRA_PROGRAMS = mt rmt
bin_PROGRAMS = cpio pax
sbin_PROGRAMS = $(MORE_PROGRAMS)
定义一个不带前缀的关键字为变量是错误的,如PROGRAMS。注意在构造变量名称时,dir后缀是去掉的,所以会定义变量为bin_PROGRAMS,而不是bindir_PROGRAMS。
并不是任意类型的目标文件可以被安装到任意目录。Automake会标记某些尝试并上报错误(如果确实需要执行该操作,可以覆盖这种检查)。Automake还会判断一些明显的目录名称拼写错误。
有时标准目录不够用,特别是要在某些预先定义标准目录的子目录中安装程序时。为此,Automake允许扩展安装目录数量。如果某个前缀(如zar)被附加上dir后缀(zardir)定义为了标准目录,该前缀就可以作为关键字前缀使用。例如,下面例子将安装file.xml到 $(datadir)/xml:
xmldir = $(datadir)/xml
xml_DATA = file.xml
这种特性还可用于覆盖Automake对可疑(目录,关键字)组合的检查,(在开发者知道自己想做什么的情况下,这种检查是不需要的)。例如,对于下面的变量定义Automake会报错:
# Forbidden directory combinations, automake will error out on this.
pkglib_PROGRAMS = foo
doc_LIBRARIES = libquux.a
但下面的方式会正常执行:
# Work around forbidden directory combinations. Do not use this
# without a very good reason!
my_execbindir = $(pkglibdir)
my_doclibdir = $(docdir)
my_execbin_PROGRAMS = foo
my_doclib_LIBRARIES = libquux.a
'my_execbindir’变量名的‘exec’子串使文件可以在恰当的时刻被安装(see Section 12.2 [The Two Parts of Install])。
一个特殊的前缀’noinst_‘表明包含该前缀的变量指定的目标文件可以被编译但不能被安装。这通常用于那些由源码包剩余部分编译的目标文件,例如静态库或帮助脚本等目标文件。*
- lgd注:
对于 LTLIBRARIES关键字指定生成的以 .la 为扩展名的libtool库。如果该关键字前缀是lib_或pkglib_ 等目录变量,则在库根目录的 .libs目录中会有生成的 xxx.so动态库文件 和 xxx.a静态库文件,安装时动态库会被安装到关键字前缀指定的目录中。如果要只编译静态库,关键字前缀需为noinst_(非必须,未修改为noinst时需要指定 -rpath参数),并且指定链接选项xxx_a_LDFLAGS = -static(必须),则在库根目录的 .libs目录中只会有生成的 xxx.a 静态库文件,这些文件在安装程序时不会被安装。不管生成的是动态库还是静态库,其他模块如果要链接这个库文件时,在其他模块Makefile.am中的LIBADD关键字指定链接库时统一使用构建库时LTLIBRARIES关键字指定的以 .la 为扩展名的libtool库文件名,即xxx.la,同时注意引用路径。
如果编译的静态库最终用于链接成动态库,则在静态库的Makefile.am中需要在AM_CFLAGS或xxx_la_CFLAGS中指定**-fPIC -DPIC**参数,如果不指定会报如下错误:relocation R_X86_64_PC32 against symbol `ogs_vslprintf' can not be used when making a shared object; recompile with -fPIC
另一个特殊的前缀‘check_’表明包含该前缀的变量指定的目标文件在未执行make check时不会被编译。这些目标文件编译后也不会被安装。
目前关键字有‘PROGRAMS’、 ‘LIBRARIES’、 ‘LTLIBRARIES’、 ‘LISP’、‘PYTHON’、‘JAVA’、‘SCRIPTS’、‘DATA’、‘HEADERS’、‘MANS’和 ‘TEXINFOS’。
一些关键字允许添加额外的前缀来控制automake的某些行为。目前定义的前缀有‘dist_’、‘nodist_’、‘nobase_’和 ‘notrans_’。后续会介绍这些前缀。
3.4 Staying below the command line length limit
传统上,大部分unix-like系统在创建新程序时对命令行参数和环境变量内容有长度限制,所以make命令可能会触发这种限制。POSIX标准要求这种限制是最少4096字节,而大部分现代操作系统有更大长度限制(甚至没有限制)。
为了创建可移植的Makefile时不被这些限制困扰,需要控制文件列表长度。Automake无法完全自主处理这种限制,所以需要用户自己处理。典型的是将一个过长的文件列表拆分为多个短的文件列表,每个文件列表使用不同的安装目录名字(可能只是使用同一目录的不同目录变量定义,最终还是指向同一目录),例如对于:
data_DATA = file1 ... fileN fileN+1 ... file2N
可以写为:
data_DATA = file1 ... fileN
data2dir = $(datadir)
data2_DATA = fileN+1 ... file2N
这会使Automake在make install过程中分别处理这两个文件列表,按变量定义顺序安装文件。注意,在该例子中make dist可能只在有更大长度限制的主机上执行。(Note that make dist may still only work
on a host with a higher length limit in this example.)
Automake采用两种策略避免过长的命令行。例如在上述文件列表 $(data_DATA) 中的文件的文件名前面加上‘${srcdir}/’时,Automake限制传递给外部命令的参数个数。有些系统的make命令会自动对源自source tree的文件名前添加VPATH前缀(就像在文件名前添加‘${srcdir}/’)。这种情况下用户可能需要使用GNU make或不使用VPATH Builds,以服从长度限制。
For libraries and programs built from many sources, convenience archives may be used as intermediates in order to limit the object list length (see Section 8.3.5 [Libtool Convenience Libraries], page 61).
3.5 How derived variables are named
有时Makefile中的变量名源于维护人员提供的一些text。例如,在‘_PROGRAMS’的程序名称列表列出的某个程序名称会被重写进‘_SOURCES’关键字变量名中。这种情况下,Automake会按规则转换这些名称文本,所以类似情况下程序本身的名字无需服从Makefile变量命令规则。变量中的程序名由字母、数字和@组成,并且在make过程中变量引用时下划线会转换为多个下划线。(the underscore are turned into underscores
when making variable references.)
例如,如果某个程序名为sniff-glue,衍生的变量名会是sniff_glue_SOURCES而不是sniff-glue_SOURCES。类似的库libmumble++.a的源文件应该被列在‘libmumble___a_SOURCES’变量中。
**@**是个例外,该字符用于Autoconf变量引用替换。(make the use of Autoconf substitutions in variable names
less obfuscating.)
3.6 Variables reserved for the user
GNU Coding Standards为源码包编译者保留了一些Makefile变量。例如CFLAGS就是这样一个用户变量。
有时用户可能想要设置某些用户变量如CFLAGS来简化工作。但是源码包本身不应该自动设置这些用户变量 ,尤其是包含开关来设置这些变量以对源码包做合适的编译。因为这些用户变量是规定了是给用户使用的,用户希望能够在编译过程中修改任意用户变量。
为了规避这个问题,Automake对每个user flag variable使用一种automake-specific shadow variable。(映射变量不会用于像CC等变量,因为没意义。)映射变量在用户变量原名称基础上添加‘AM_’前缀。例如,用户变量YFLAGS的映射变量是AM_YFLAGS。源码包维护人员(Makefile.am文件和configure.ac文件的编写者)可根据需要调整这些映射变量。
3.7 Programs automake might require
Automake可能需要一些辅助程序来保证生成的Makefile正常运行。
下面大部分文件随着Automake发布和安装,但有一些需要单独维护。Automake每次更新发布时都会更新相关文件在Automake中的拷贝。下面介绍的是各文件最原始的版本。(新版本Automake可能没有包含某些文件)
- ar-lib
用于Microsoft库文件的首选封装器,使库文件更加POSIX-like - compile
这是对于不能同时接收 -c 和 -o 选项的编译器的封装。一般情况下用不到。除了需额外关注的Microsoft C/C++编译器外,这类编译器很少见。compile还会使编译器在执行文件名转换时可用下列通用选项:-I、-L、 -l、-Wl和 -Xlinker。 - config.guess
config.sub
这两个程序计算build、host和target architecture三者的联合标准,会定期更新以支持新的架构和修改新版本kernel修改导致的探测失败。每个Automake的新发布版本保存这两个程序的最新拷贝。如果Automake版本过老,建议更新新版本。 - depcomp
这种程序知道编译器如何运行,所以其不仅生成想要的输出结果,还后续依赖关系跟踪特性需要的依赖关系信息。 - install-sh
当程序运行在没有install target或install target无法使用的平台上时,该脚本可作为install程序的一种替代方法。 - mdate-sh
这个脚本用于生成version.texi文件。它检查文件并print文件的日期信息。 - missing
其封装了一些典型的只有维护人员需要的程序。如果相关程序不存在,或程序版本太旧,missing在失败退出前会打印一些有用的警告,给使用者提供更多的有用的信息如上下文等。 - mkinstalldirs
这个脚本是不可移植的’mkdir -p’的一个封装。现在当configure脚本发现’mkdir -p’不生效时更常使用’install-sh -d’,这样发布时就可以少发布一个脚本文件了(不用发布mkinstalldirs脚本)。 - py-compile
用于字节编译Python脚本。 - test-driver
其实现了由并行编译套件(parallel testsuite harness)提供的默认测试驱动(default test driver)。 - texinfo.tex
这不是个程序,当源码包中有Texinfo源文件时,‘make dvi’、‘make ps’ 和 ‘make pdf’需要这个文件。 - ylwrap
这个程序是lex和yacc的封装,来重命名它们的输出文件。该程序还保证多个yacc样例可以在单个目录中被并发引用。