automake 手冊

For version 1.3, 3 April 1998

David MacKenzie and Tom Tromey
 
王立 譯

 

 


 

目錄

 


 

@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發送到 [email protected]

通用性概念

一些基本概念將有助於理解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用pkglibdirpkgincludedirpkgdatadir擴展了這個列表;除了把`@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')生成兩個程序(ctagsetags)。困難的部分是對 `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',在頂層目錄不帶任何參數地運行automakeautomake將自動地尋找每個合適的`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定義變量PACKAGEVERSIONPACKAGE應該是在捆綁發佈的時候使用的包的名稱。例如,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以確認在創建環境中,程序aclocalautoconfautomakeautoheadermakeinfo是否存在。下面是如何完成這個任務:
    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_YYTEXTAC_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 僅僅在特殊情況下才創建mtrmt

在這種情況下,你必須把可能創建的所有程序都告訴automake,但同時使生成的`Makefile.in'使用由configure 指明的程序。這可以通過在EXTRA_PROGRAMS中列出所有可能創建的程序的同時,把configure提供的值的替換到每個`_PROGRAMS'變量的定義中,來完成。

如果你需要和configure沒有找到的庫相連接,你可以使用LDADD來完成。該變量實際上可以用於把任何選項添加到連接器的命令行中。

有時,要在一個目錄中創建多個程序,但並不共享相同的連接時刻需求(link-time requirement)。在這種情況下,你可以使用變量`prog_LDADD' (其中prog是出現在某些`_PROGRAMS'變量中的程序名)來覆蓋全局的LDADD。(對於某個程序來說,如果存在這個變量,那麼那個程序的連接就不使用LDADD。)

例如,在GNU cpio中,paxcpiomt 需要和庫`libcpio.a'連接。然而,rmt在同一個目錄中創建,並且不需要與`libcpio.a'連接。此外,mtrmt也僅僅在這種結構下創建。這裏是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'。庫可以安裝到libdirpkglibdir之中。

關於如何使用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中繼承而來的;它們是CCCFLAGSCPPFLAGSDEFSLDFLAGSLIBS

還有一些附加的變量是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中應用的改名方式:

#define	yymaxdepth c_maxdepth
#define	yyparse	c_parse
#define	yylex	c_lex
#define	yyerror	c_error
#define	yylval	c_lval
#define	yychar	c_char
#define	yydebug	c_debug
#define	yypact	c_pact	
#define	yyr1	c_r1			
#define	yyr2	c_r2			
#define	yydef	c_def		
#define	yychk	c_chk		
#define	yypgo	c_pgo		
#define	yyact	c_act		
#define	yyexca	c_exca
#define yyerrflag c_errflag
#define yynerrs	c_nerrs
#define	yyps	c_ps
#define	yypv	c_pv
#define	yys	c_s
#define	yy_yys	c_yys
#define	yystate	c_state
#define	yytmp	c_tmp
#define	yyv	c_v
#define	yy_yyv	c_yyv
#define	yyval	c_val
#define	yylloc	c_lloc
#define yyreds	c_reds
#define yytoks	c_toks
#define yylhs	c_yylhs
#define yylen	c_yylen
#define yydefred c_yydefred
#define yydgoto	c_yydgoto
#define yysindex c_yysindex
#define yyrindex c_yyrindex
#define yygindex c_yygindex
#define yytable	 c_yytable
#define yycheck	 c_yycheck

對於每一個define,用任何你喜歡的東西替換前綴`c_'。這些定義可以爲bisonbyacc和傳統的 yacc工作。如果你發現某個解析器使用了這裏所沒有提到的符號,請告訴我們以便把它添加到上述列表中。

C++和其它語言

Automake對C++提供了完整的支持,對其它語言也有一些不完善的支持。對其它語言的支持將根據實際需要被添加進來。

任何包括了C++代碼的包都必須在`configure.in'中定義輸出變量`CXX';完成這一任務的最簡單方式就是使用宏AC_PROG_CXX

在出現C++源文件的時候需要定義幾個附加的變量:

CXX
C++編譯器的名稱。
CXXFLAGS
傳遞給C++編譯器的任何選項。
CXXCOMPILE
實際用於編譯C++源文件的命令。文件名將被添加到它的後面以構成完整的命令行。
CXXLINK
實際用於連接C++程序的命令。

自動de-ANSI-fication

雖然GNU標準允許使用標準C,使用標準C可能使包難以移植到一些舊的編譯器上(典型的是SunOS)。

在實際的編譯發生之前,Automake允許你通過對每個源文件實施"de-ANSI-fying" 以在這一類機器上進行工作。

如果`Makefile.am'變量AUTOMAKE_OPTIONS (參見改變Automake的行爲)包括了選項ansi2knr那麼處理de-ANSI-fication的代碼就被插入到生成的`Makefile.in'中。

這使得目錄中的每個C源文件都被看作標準C。如果有標準C編譯器可以使用,就使用它。如果沒有標準C編譯器可用,就用程序ansi2knr 把文件轉換成K&R C,而後再被編譯。

程序ansi2knr相當簡單。它假定源代碼按照特定的方式進行排版;詳情請參見ansi2knr的man。

支持de-ANSI-fication需要把源文件`ansi2knr.c'`ansi2knr.1'與標準C源代碼放在同一個包中;這些文件與Automake 一同發佈。此外,包的`configure.in'必須調用宏AM_C_PROTOTYPES

Automake還負責在當前包的其它目錄中尋找ansi2knr的支持文件。這通過把到達適當目錄的相對路徑添加到選項ansi2knr之前來完成。例如,假定一個包的標準C代碼儲存在子目錄`src'`lib'中。文件`ansi2knr.c'`ansi2knr.1'出現在`lib'中。那麼下述內容應該在`src/Makefile.am'中出現:

AUTOMAKE_OPTIONS = ../lib/ansi2knr

如果沒有給出前綴,就假定文件在當前目錄中。

自動依賴性跟蹤

作爲開發者,經常痛苦地在每次項目的include文件的依賴關係發生變化的時候對`Makefile.in'進行更新。 automake提供了一種方式以自動跟蹤依賴關係的變化,並且在生成的`Makefile.in'中給出這些依賴關係。

當前這種支持需要使用GNU makegcc。如果有足夠的必要性,將來可能提供對不同的依賴性生成程序的支持。在此之前,如果當前目錄中定義了任何C程序或者庫,在缺省狀態下就啓動這種模式,因而你可能從非GNU make那裏得到一個`Must be a separator'錯誤。

當你決定創建一個發佈版本時,目標dist 將用`--include-deps'和其它選項重新運行automake。這將是的以前生成的依賴關係被插入到生成的`Makefile.in'中,並因而被插入到發佈之中。這一步驟還不會把依賴性生成代碼包括進來,所以那些下載你的發佈版本的人就不必使用GNU makegcc,而且不會導致錯誤。

在添加到`Makefile.in'的時候,所有系統特定的依賴性都被自動刪除了。這可以通過把文件羅列在變量`OMIT_DEPENDENCIES' 中來實現。例如:automake將刪除所有對系統頭文件的引用。有時有必要指明應該刪除哪個頭文件。例如,如果你的 `configure.in'使用了`AM_WITH_REGEX',那麼就應該刪除任何與`rx.h'或者 `regex.h'有關的依賴性,這是因爲在用戶配置包之前還不知道應該使用那個頭文件。

實際上,automake足夠地聰明以至於可以處理諸如常規表達式頭文件的特殊情況。如果使用了`AM_GNU_GETTEXT',它還將自動忽略 `libintl.h'

自動依賴性跟蹤功能可以通過在變量AUTOMAKE_OPTIONS 中設置no-dependencies來關閉。

如果你打開由make dist創建的發佈版本,而且你希望重新添加依賴性跟蹤的代碼,只要重新運行automake就行了。

實際的依賴性文件被儲存在創建目錄下的一個名爲`.deps' 的子目錄中。這些依賴性是機器特有的。如果你願意,刪除它們是安全的;它們將在下次創建的時候自動重建。

其它派生對象

Automake可以處理不是C程序的其它派生對象。有時對實際創建這類對象的支持必須顯式地給出,但Automake仍然會自動地處理安裝和發佈。

可執行腳本

定義和安裝腳本程序是可能的。這種程序被羅列在主變量`SCRIPTS'中。 automake沒有爲腳本定義任何依賴性關係; `Makefile.am'應該包含正確的規則。

automake並不假定腳本是派生的對象;這些對象必須被手工地刪除;詳情請參見清除了些什麼

automake本身就是在配置時刻從`automake.in' 中生成的腳本。下面給出瞭如何處理它:

bin_SCRIPTS = automake

因爲automake出現在宏AC_OUTPUT中,自動地生成了一個關於它的目標。

腳本對象可以安裝在bindirsbindirlibexecdir或者pkgdatadir中。

頭文件

頭文件由`HEADERS'變量族所指定。通常是不安裝頭文件的,所以變量noinst_HEADERS是最常用的。

所有的頭文件都必須在某些地方列出;沒有列出的頭文件將不會出現在發佈版本中。通常最清楚的方式是和程序的其它源代碼一起列出不會被安裝的頭文件。參見創建一個程序。在變量`_SOURCES'中列出的頭文件不需要在任何 `_HEADERS'變量中再次列出。

頭文件可以安裝到includediroldincludedir或者 pkgincludedir中。

與體系結構無關的數據文件

Automake使用`DATA'族變量來支持對各種數據文件的安裝。

這些數據可以安裝在目錄datadirsysconfdirsharedstatedirlocalstatedir或者pkgdatadir中。

在缺省狀態下,數據文件不會被包含在發佈版本中。

下面是automake如何安裝它的附加數據文件:

pkgdata_DATA = clean-kr.am clean.am ...

已創建的源代碼

有時候,一個可以被稱作“源文件”的文件(例如一個C `.h'文件)實際上是從其它文件中派生出來的。這類文件應該被羅列在變量 BUILT_SOURCES中。

在缺省狀態下,不會編譯已創建的源文件。你必須在一些其它的`_SOURCES'變量中明確地給出它們,以便對其進行編譯。

需要說明的是,在某些情況下,BUILT_SOURCES將以令人驚訝的方式工作。爲了獲得已創建的源文件以進行自動依賴性跟蹤,`Makefile'必須依賴於 $(BUILT_SOURCES)。這導致這些源文件可能在某些可笑的時候被重新創建。

其它的GNU工具

因爲Automake被設計成爲GNU程序自動生成`Makefile.in',它爲與其它GNU工具進行互操作做出了努力。

Emacs Lisp

Automake爲Emacs Lisp提供了一些支持。主變量`LISP'被用於保存一個`.el'文件的列表。該主變量的可能前綴有:`lisp_'`noinst_'。如果定義了lisp_LISP,那麼 `configure.in'就必須運行AM_PATH_LISPDIR (參見Automake支持的Autoconf宏).

在缺省狀態下,Automake將使用通過AM_PATH_LISPDIR 找到的Emacs按字節編譯(byte-compile)所有Emacs Lisp源文件。如果你不希望使用字節編譯,請把變量`ELCFILES'定義爲空。 字節編譯的Emacs Lisp文件並不能在所有版本的Emacs間移植,所以如果你希望在同一個地方安裝多於一個版本的Emacs,你可以關閉它。進一步,許多包並沒有從字節編譯中獲得實際的好處。我們仍然建議你不要改變缺省設置。對站點進行特殊的配置以適用於它們自身,可能比爲其它所有人創建不和諧的安裝要更好一些。

Gettext

如果在`configure.in'中出現了AM_GNU_GETTEXT,那麼Automake就開啓對GNU gettext的支持,一個支持國際化的消息編目系統(參見GNU gettext工具中的`GNU Gettext'節)。

在Automake中對gettext的支持需要把兩個子目錄附加到包中,`intl'`po'。Automake確認這些目錄的存在並且在SUBDIRS中被給出。

更進一步,Automake檢查在`configure.in'中包含了與所有合法的`.po'文件相對應的`ALL_LINGUAS'定義,並且沒有多餘的定義。

Guile

Automake爲構造Guile模塊提供了一些自動支持。如果宏AM_INIT_GUILE_MODULE 出現在`configure.in'中,Automake將開啓對Guile的支持。

現在對Guile的支持僅僅表示宏AM_INIT_GUILE_MODULE

  • 運行了AM_INIT_AUTOMAKE
  • 帶路徑`..'運行了AC_CONFIG_AUX_DIR

隨着Guile模塊代碼的成熟,無疑Automake的支持也將會更好。

Libtool

Automake通過主變量`LTLIBRARIES'提供了對GNU Libtool的支持(參見Libtool手冊)參見創建一個共享庫

Java

通過主變量`JAVA',Automake爲Java的編譯提供了少量支持。

任何在變量`_JAVA'列舉的`.java'文件在創建時刻將用JAVAC進行編譯。在缺省狀態,`.class'文件不會被包含在發佈版本中。

目前Automake正試圖限制只能在`Makefile.am'中使用一個`_JAVA'主變量。引入這個限制是因爲,通常是不可能知道哪個`.class'文件是從哪個`.java' 文件中生成的 -- 因此不可能知道哪個文件應該被安裝到哪裏。

創建文檔

目前Automake提供了對Texinfo和man的支持。

Texinfo

如果當前目錄中含有Texinfo源文件,你必須在主變量`TEXINFOS' 中給出聲明。通常Texinfo文件被轉換成info,因此經常在這裏使用宏info_TEXINFOS。需要指出的是任何Texinfo源文件的文件名的擴展名都必須是`.texi'或者`.texinfo'

如果`.texi'文件@includes `version.texi',就將自動生成那個文件。 `version.texi'定義了三個你可以引用的Texinfo宏:EDITIONVERSIONUPDATED。前兩個宏保存了你的包的版本號(爲清晰起見而分別保存);最後一個宏是最後一次修改主文件的日期。對`version.texi'的支持需要程序mdate-sh;這個程序由Automake提供。

有時,一個info文件實際上依賴於多個`.texi'文件。例如,在GNU Hello中,`hello.texi'包括了文件`gpl.texi'。你可以通過使用變量`texi_TEXINFOS'告訴Automake 這一依賴性。下面就是Hello處理它的代碼:

info_TEXINFOS = hello.texi
hello_TEXINFOS = gpl.texi

在缺省狀態下,Automake認爲`texinfo.tex'出現在Texinfo源文件所在的目錄中。然而,如果你在`configure.in'中使用了AC_CONFIG_AUX_DIR 那麼將到那個目錄中去尋找`texinfo.tex'文件。如果給出了 `--add-missing',Automake將自動提供`texinfo.tex'

如果你的包在許多目錄中儲存了Texinfo文件,你可以用變量TEXINFO_TEX 來告訴automake到那裏去尋找你的包的規範`texinfo.tex'文件。這個變量的值應該是從當前`Makefile.am'`texinfo.tex' 的相對路徑。

TEXINFO_TEX = ../doc/texinfo.tex

選項`no-texinfo.tex'可以消除對`texinfo.tex'的需要。但使用變量TEXINFO_TEX更好些,因爲它使得目標dvi 仍然可以工作。

Automake生成一個install-info目標;一些人顯式地使用它。在缺省狀態下,info文檔通過運行`make install'來安裝。可以通過給出選項no-installinfo以阻止執行這一操作。

Man手冊

一個包還可以包含man手冊。(參見GNU關於此事的標準,GNU編碼標準中的`Man手冊'節。)用主變量`MANS'聲明Man手冊。通常使用宏man_MANS。根據文件的擴展名,Man手冊被自動地安裝到mandir的正確子目錄中。

在缺省狀態下,man手冊通過運行`make install'安裝。然而,因爲GNU項目並不需要man手冊,許多維護者沒有花費時間以及時更新man手冊。在這些情況下,給出選項no-installman 將阻止對man手冊的安裝。用戶仍然可以顯式地使用`make install-man' 來安裝它們。

下面是GNU cpio如何處理它的文檔(它同時包括了Texinfo文檔和 man手冊):

info_TEXINFOS = cpio.texi
man_MANS = cpio.1 mt.1

Texinfo源文件和info文檔都被看作用於創建發佈版本的源代碼。

Man手冊現在並不被看作源代碼,因爲man手冊有時是自動生成的。

安裝了些什麼

自然地,一旦你的程序被創建了,Automake實際上處理了安裝程序的細節。所有PROGRAMSSCRIPTSLIBRARIESLISPDATAHEADERS中列出的文件都被自動地安裝在適當的位置。

Automake還可以處理對info文檔和man手冊的安裝。

Automake生成分離的install-datainstall-exec目標,如果安裝器(installer)在共享的目錄結構中爲多個機器進行安裝,這些目標允許與機器獨立的部分僅僅被安裝一次。目標install依賴於這兩個目標。

Automake還生成一個uninstall目標,一個 installdirs目標,和一個install-strip目標。

通過定義目標install-exec-local,或者目標install-data-local 就可以擴展這一機制。如果這些目標存在,它們將在運行`make install'時運行。

使用標準目錄前綴`data'`info'`man'`include'`oldinclude'`pkgdata'或者 `pkginclude'的變量(例如,`data_DATA')將由 `install-data'安裝。

使用標準目錄前綴`bin'`sbin'`libexec'`sysconf'`localstate'`lib'或者 `pkglib'的變量(例如,`bin_PROGRAMS')將由 `install-exec'安裝。

任何使用了含有`exec'的用戶定義目錄前綴的變量(例如,`myexecbin_PROGRAMS')將由`install-exec'安裝。所有使用其它用戶定義的前綴的變量將由`install-data'安裝。

Automake在所有的install規則中生成對變量`DESTDIR'的支持;參見GNU編碼標準中的`Makefile慣例'節。

清除了些什麼

GNU Makefile標準給出了許多不同的清除規則。通常由Automake自動確定可以清除哪些文件。當然,Automake還能識別一些爲指明需要額外地清除的文件而定義的變量。這些變量是 MOSTLYCLEANFILESCLEANFILESDISTCLEANFILESMAINTAINERCLEANFILES

需要發佈哪些文件

生成的`Makefile.in'中的dist目標可以用於產生用gzip壓縮了的發佈tar文件。 tar文件是根據`PACKAGE'變量和`VERSION'變量命名的;精確地說,被命名爲`package-version.tar.gz'

在大部分情況下,發佈版本中的文件由Automake自動尋找:所有的源文件被自動地包含在發佈版本中,還有所有的 `Makefile.am'`Makefile.in'。Automake定義了一些常用的內置文件,如果出現在當前目錄中,那麼就被自動地包含在發佈版本中。可以用`automake --help'打印它們。此外,由configure 讀入的文件(例如,對應於由AC_OUTPUT調用指明的文件的源文件)將被自動地包含在發佈版本中。

有時,除此而外仍然有一些文件需要被髮布而沒有包含在自動規則之中。這些文件應該在變量EXTRA_DIST中列出。需要指出的是,EXTRA_DIST只能處理當前目錄中的文件;其它目錄中的文件將使make dist在運行時發生錯誤。

如果你定義了SUBDIRS,automake將遞歸地把子目錄包含在發佈版本中。如果是有條件地定義SUBDIRS(參見條件),通常automake將把所有可能出現在SUBDIRS中的所有目錄包含在發佈版本中。如果你需要有條件地給出一組目錄,你可以設置變量DIST_SUBDIRS以精確地列出需要包含在發佈版本中的子目錄。

有時在發佈版本打包之前修改發佈版本是有用的。如果目標dist-hook存在,它可以在填充發布目錄之後,創建tar(或shar)文件之前運行。使用該功能的一種方式是發佈新的`Makefile.am'被刪除了的子目錄中的文件。

dist-hook:
        mkdir $(distdir)/random
        cp -p random/a1 random/a2 $(distdir)/random

Automake還生成一個distcheck目標,它有助於確認給定的發佈版本實際上是可以工作的。 distcheck首先創建發佈版本,而後試圖進行一個VPATH創建。

對測試套件的支持

Automake支持兩種形式的測試套件。

如果定義了變量TESTS,它的值被看作爲了運行測試而運行的程序列表。程序可以是派生對象或者是源對象;生成的規則將在srcdir`.'中尋找。應該在srcdir(它可以既是環境變量,又是make變量)中尋找程序需要的數據文件,所以它們在一個分離的目錄中進行創建的工作(參見Autoconf手冊中的`創建目錄'節),並且是在特別的目標distcheck中創建的(參見那些需要被髮布)。

在運行的終點將打印失敗的次數。如果一個測試程序以狀態77退出,在最後的計數中它的結果將被忽略。這一特徵允許不可移植的測試在對它來說沒有意義的環境下被忽略。

變量TESTS_ENVIRONMENT可以用於爲測試運行而設置環境變量;在該規則中設置環境變量srcdir。如果你所有的測試程序都是腳本,你還可以把TESTS_ENVIRONMENT設置成一個對shell的調用(例如`$(SHELL) -x');這對調試測試結果來說是有用的。

如果`dejagnu'出現在AUTOMAKE_OPTIONS中,那麼就假定運行一個基於dejagnu的測試套件。變量 DEJATOOL的值被作爲--tool的參數傳遞給 runtest;它的缺省值是包的名字。

在缺省狀態下,變量RUNTESTDEFAULTFLAGS保存了傳遞給dejagnu的--tool--srcdir選項;如果有必要,可以覆蓋它。

還可以覆蓋變量EXPECTRUNTESTRUNTESTFLAGS以提供項目特定的值。例如,如果你正在測試編譯器工具鏈(toolchain),你就需要這樣做。這是因爲缺省值並沒有把主機名和目標名考慮進去。

在上述兩種情況中,測試都是通過`make check'來完成的。

改變Automake的行爲

Automake的各種特徵可以在`Makefile.am'中用各種選項進行控制。這些選項在一個名爲AUTOMAKE_OPTIONS的特殊變量中被列出。目前可以理解的選項有:

gnits
gnu
foreign
cygnus
設置適當的嚴格性。選項gnits還隱含了readme-alphacheck-news
ansi2knr
path/ansi2knr
打開自動de-ANSI-fication功能。參見自動de-ANSI-fication。如果以一個路徑開頭,那麼生成的`Makefile.in'將在特別給定的目錄中尋找程序`ansi2knr'。通常,路徑應該是到同一個發佈版本中的其它目錄的相對路徑(雖然Automake並不進行這項檢查)。
check-news
給出該選項後,如果當前的版本號沒有出現在`NEWS'文件中的前幾行中,將導致make dist的失敗。
dejagnu
生成dejagnu特定的規則。參見對測試套件的支持
dist-shar
就象普通的dist目標那樣生成dist-shar目標。這個新目標將創建一個發佈版本的shar包。
dist-zip
就象普通的dist目標那樣生成dist-zip目標。這個新目標將創建一個發佈版本的zip包。
dist-tarZ
就象普通的dist目標那樣生成dist-tarZ目標。這個新目標將創建一個發佈版本的tar包;假定使用傳統的tarcompress。警告:如果你實際上在使用GNU tar,那麼生成的包可能含有不可移植的結構。
no-dependencies
這與在命令行中使用選項`--include-deps'相類似,但在那些你不希望使用自動依賴性跟蹤的場合下更爲有用。參見自動依賴性跟蹤。在這個情況下將有效地關閉自動依賴性跟蹤。
no-installinfo
給出該選項後,生成的`Makefile.in'在缺省的狀態下將不會創建或者安裝info文檔。然而,目標info和目標install-info 仍然是可用的安裝選項。在`GNU'嚴格性以及更高的嚴格性中這個選項是不允許使用的。
no-installman
給出這個選項後,生成的`Makefile.in'在缺省狀態下將不會安裝man手冊。然而,目標install-man仍然是可用的安裝選項。在`GNU'嚴格性以及更高的嚴格性中這個選項是不允許使用的。
no-texinfo.tex
即使在本目錄中含有texinfo文件,也不需要`texinfo.tex'
readme-alpha
如果本發佈是一個alpha版本,並且存在文件`README-alpha',那麼它將被添加到發佈版本中。如果給出了該選項,版本號應該是以下兩種形式之一。第一種形式是`MAJOR.MINOR.ALPHA',其中每個元素都是一個數字;最後的點和數字應該被忽略以用於非alpha版本。第二種形式是`MAJOR.MINORALPHA',其中ALPHA是一個文字;對於非alpha版本來說,應該忽略它。
version
可以給出版本號(例如,`0.30')。如果Automake並不比要求的版本號新,將不會創建`Makefile.in'

automake能夠診斷不能識別的選項。

其它規則

還有一些不適於放在任何其它地方的幾條規則。

etags之間的界面

在某些環境下,automake將生成規則以產生由GNU Emacs使用的`TAGS'文件。

如果出現了任何C源代碼或者頭文件,那麼就爲該目錄創建目標tags和目標TAGS

在運行的時候,將在多個目錄包的頂層目錄創建一個tags文件,它將生成一個包括了對所有子目錄的`TAGS'文件的引用的`TAGS'文件。

此外,如果定義了變量ETAGS_ARGS,將生成目標tags。該變量用於包含了能夠被標記,但是不能夠被etags所識別的源文件的目錄。

下面是Automake如何爲它的源代碼生成標記和它的Texinfo文件中的結點。

ETAGS_ARGS = automake.in --lang=none /
 --regex='/^@node[ /t]+/([^,]+/)//1/' automake.texi

如果你把文件名添加到`ETAGS_ARGS',你將可能還要設置`TAGS_DEPENDENCIES'。該變量的內容將直接添加到目標tags的依賴列表中。

Automake還將生成一個將在源代碼上運行mkidID目標。它僅僅可以在一個目錄到目錄的基礎(directory-by-directory basis)上使用。

處理新的文件擴展名

有時,爲處理Automake不能識別的文件類型而引入新的隱含規則是有用的。如果這樣做,你必須把這些新的後綴告訴GNU Make。可以通過把新後綴的列表添加到變量SUFFIXES來完成。

例如,目前automake不能對Java提供任何支持。如果你寫了一個用於從`.java' 源文件生成`.class'文件的宏,你還需要把這些後綴添加到列表中:

SUFFIXES = .java .class

條件

Automake支持一種簡單的條件。

在使用條件之前,你必須在configure.in文件中使用 AM_CONDITIONAL定義它。宏AM_CONDITIONAL 接受兩個參數。

AM_CONDITIONAL的第一個參數是條件的名字。它應該是一個以字母開頭並且僅僅由字母、數字和下劃線組成的簡單字符串。

AM_CONDITIONAL的第二個參數是一個適用於shell的if語句的shell條件。該條件將在運行configure的時候被求值。

條件典型地依賴於用戶提供給configure腳本的選項。下面是一個演示如果在用戶使用了`--enable-debug'選項的情況下爲真的條件的例子。

AC_ARG_ENABLE(debug,
[  --enable-debug    Turn on debugging],
[case "${enableval}" in
  yes) debug=true ;;
  no)  debug=false ;;
  *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;;
esac],[debug=false])
AM_CONDITIONAL(DEBUG, test x$debug = xtrue)

下面是一個如何在`Makefile.am'中使用條件的例子:

if DEBUG
DBG = debug
else
DBG =
endif
noinst_PROGRAMS = $(DBG)

這個小例子還可以被處理以用於EXTRA_PROGRAMS。(參見創建一個程序)。

你只能在if語句中測試單個變量。可以忽略else語句。條件可以嵌套到任意深度。

需要指出的是Automake中的條件與GNU Make中的條件是不相同的。Automake的條件在配置時刻由`configure'腳本完成檢查,並且將影響`Makefile.in'`Makefile'的轉換。它們是基於傳遞給`configure'的選項和`configure'對本地系統的檢測結果的。 GNU Make條件則在make時完成檢查,並且是基於傳遞給make程序的變量或者是基於在`Makefile'中定義的變量的。

Automake條件在任何make下都可以工作。

--gnu--gnits的效果

選項`--gnu'(或者`AUTOMAKE_OPTIONS'中的`gnu')將使得 automake執行如下檢查:

  • 在包的頂層目錄中應該含有文件`INSTALL'`NEWS'`README'`COPYING'`AUTHORS'`ChangeLog'
  • 禁止使用選項`no-installman'`no-installinfo'

需要指出的是,該選項將在未來進行擴展以進行更多的檢查;熟悉GNU標準的精確需求是值得推薦的。此外,`--gnu'可以要求某些非標準GNU程序爲了各種僅由維護者使用的目標而存在;例如,在將來`make dist'可能會需要pathchk

選項`--gnits'進行`--gnu'所做的所有檢查,此外還進行如下檢查:

  • `make dist'將檢查以確認文件`NEWS'被更新到當前的版本。
  • 不允許出現文件`COPYING.LIB'。LGPL顯然是一個失敗的試驗。
  • 檢查文件`VERSION'以確保它的格式是符合Gnits標準的。
  • 如果`VERSION'表明本版本是alpha版本,並且文件`README-alpha' 出現在包的頂層目錄中,那麼它就被包含在發佈版本中。因爲該模式是唯一對版本號格式實行限制的模式,所以上述操作在`--gnits' 模式下實施而不在其它模式下進行,因此,該模式也是automake唯一能夠自動確定是否把`README-alpha'包含在發佈版本中的模式。
  • 需要出現文件`THANKS'

--cygnus的效果

對於如何構造`Makefile.in',Cygnus解決方案有一些不同的規則。把`--cygnus'傳遞給automake將使所有生成的`Makefile.in' 服從Cygnus規則。

下面是`--cygnus'的精確效果:

  • 總是在創建目錄中,而不是在源目錄創建Info文件。
  • 如果指明瞭Texinfo源文件,就不需要`texinfo.tex'。其設想是:應該提供該文件,但automake不能在適當的位置找到它。這種設想是Cygnus包典型的包裝方式的產物。
  • `make dist'將在創建目錄和源目錄中尋找文件。爲了支持把info文件儲存在創建目錄中而提供這個功能。
  • 將在創建樹和用戶的`PATH'中尋找某些工具。這些工具是runtestexpectmakeinfotexi2dvi
  • 隱含--foreign選項。
  • 隱含選項`no-installinfo'和選項`no-dependencies'
  • 需要宏`AM_MAINTAINER_MODE'和宏`AM_CYGWIN32'
  • 目標check並不依賴於目標all

建議GNU維護者使用`gnu'嚴格性方式而不是特殊的Cygnus模式。

什麼時候Automake不夠用

Automake的隱含語義意味着許多問題只要通過把一些make 目標和規則添加到`Makefile.in'中就可以解決了。 automake將忽略這些添加的目標和規則。

對於這種做法需要提出告誡。雖然你可以覆蓋已經被automake所使用的目標,但這通常是失策的,在非平包(non-flat)的頂層目錄中尤其如此。然而,你可以在你的`Makefile.in'中給出各種帶有`-local'的有用目標版本。 Automake將用那些用戶提供的目標補充標準的目標。

支持本地版本的目標有allinfodvicheckinstall-datainstall-execuninstall和各種clean目標(mostlycleancleandistcleanmaintainer-clean)。需要指出的是沒有 uninstall-exec-local或者uninstall-data-local目標;請使用uninstall-local。僅僅反安裝數據或僅僅反安裝可執行文件是沒有意義的。

例如,下面是把一個文件安裝到`/etc'的一種方式:

install-data-local:
        $(INSTALL_DATA) $(srcdir)/afile /etc/afile

某些目標還可以在完成它的工作之後運行一個稱爲hook的其它目標。 hook是在源目標名的後面添加`-hook'。允許使用hook的目標是 install-datainstall-execdistdistcheck

例如,下面是如果創建一個到已經安裝的程序的硬連接:

install-exec-hook:
        ln $(bindir)/program $(bindir)/proglink

發佈`Makefile.in'

Automake對於發佈生成的`Makefile.in'沒有施加任何限制。我們仍然鼓勵軟件的作者按照諸如GPL之類的條款發佈它們的作品,但是Automake 並不要求你這樣做。

一些可以通過選項--add-missing自動安裝的文件則受到 GPL的約束;打開每個文件檢查一下。

未來的某些想法

下面是可能在未來發生的一些事情:

  • 支持HTML。
  • 輸出將被清理。例如,只有那些確實使用了的變量纔會出現在生成的 `Makefile.in'文件中。
  • 對發佈版本提供自動重編碼支持。其目的是允許維護者使用對他來說最方便的字符集,但所有的發佈都將使用Unicode或者帶有UTF-8編碼的 ISO 10646。
  • 對自動生成包提供支持(例如Debian包、RPM包、Solaris包等等)。如果有具備創建包的經驗的人告訴我怎樣做纔是有幫助的,那麼將會更快地提供這項支持。
  • 用Guile重寫。這不會在不久的將來發生,但它終將發生。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章