Abstract
在 Unix 底下,automake 和 autoconf 常被用來管理 C/C++ 的專案。 如果您的專案是根據 GNU 的標準建構出來的,那麼它們能夠幫您節省很多 make 以及 configure 的時間。然而,萬事起頭難。希望這篇指南能夠為剛入門的程式設計師提供一些有用的資訊。
我不是 Unix 以及 autoconf, automake 的專家,所以我歡迎有建設性的批評與指教。
make and configure
這個 make tool 能夠用來管理多個檔案的專案。make 會用到您專案裡的 Makefile 這個檔案,這個檔案列出了各式的編譯以及連結步驟,目的,以及一些相依關係。多檔的專案與 GNU 的 make 工具程式是有很大的關係的。
configure 這個 script 被用來協助處理跨平台的編譯工作。一個合適的 configure script 能夠正確的解譯 Makefile.in 然後產生該平台相依的 Makefile。當然。產生 Makefile 之前必須經過很多測試來決定該平台的特性。
所以我們允許使用者執行 './configure' 然後再執行 'make' 來根據自身的平台而編譯這個專案。
aclocal.m4
很明顯的,大部分寫好的 Makefile 和 configure script 看起來都非常的類似。事實上,GNU 提供了一些關於這些檔案的細部描述。因此,GNU 寫出了 automake 以及 autoconf 來簡化處理這些過程,並且確保 Makefile 以及 configure script 能夠遵守 GNU 標準。
這裡是這些工具的簡單的介紹。我這裡也提供了範例供您測試使用。
注意:這些工具使用 m4 程式語言。 aclocal 增加 aclocal.m4 這個檔案到您的專案目錄,因為包含了一些需要用到的 m4 巨集。
autoconf
autoconf 會尋找叫做 configure.in 這個檔案,然後會根據他找到的巨集而生出 configure script。
注意要的是 autoscan 可以用來產生一個可能使用的 configure.in。它會測試你的原始檔案,然後放進一些建議值到一個叫做 configure.scan 的檔案。當然您必須改名成 configure.in。
不管什麼時候,您在 configure.in 加入一個巨集時,然後必須執行 aclocal 和 autoconf,因為 aclocal 會掃描 configure.in 然後找出它必須提供的巨集。
Lines which every configure.in should have
每一個 configure.in 應該有底下這幾行:
AC_INIT(hello.cc)
AM_INIT_AUTOMAKE(hello,0.1)
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_OUTPUT(Makefile)
AC_INIT
這個巨集以一個原始檔當作參數。它會檢查該檔是否存在,也會檢查目錄是否存在。
這個巨集以一個原始檔當作參數。它會檢查該檔是否存在,也會檢查目錄是否存在。
AM_INIT_AUTOMAKE
這行增加了幾個標準的檢查。它是以程式名稱以及版本號碼當作參數。
這行增加了幾個標準的檢查。它是以程式名稱以及版本號碼當作參數。
AC_PROG_CC
指出了該原始檔是用 C 寫成的。假如原始檔是用 C++ 寫成的,那麼應該改成AC_PROG_CXX。
指出了該原始檔是用 C 寫成的。假如原始檔是用 C++ 寫成的,那麼應該改成AC_PROG_CXX。
AC_PROG_INSTALL
會產生安裝目的地,好讓使用者打 make install 便能安裝這套軟體。
會產生安裝目的地,好讓使用者打 make install 便能安裝這套軟體。
AC_OUTPUT
指出應該產生的 Makefile 檔案名稱。
指出應該產生的 Makefile 檔案名稱。
Using a Config Header
AM_CONFIG_HEADER(config.h) 這行指出了您將會使用 config.h 檔。autoconf 將會需要 config.h.in ,並將之處理成 config.h。這是你的原始檔案中,透過 #define 定義的標頭檔,好提供一個方式讓人們為它們的平台自訂 configuration。config.h.in 能夠被autoheader 這個工具程式自動產生。
然而,在你的專案中,你需要 stamp-h 這個檔案來確保 automake 從 config.h.in 重新產生 config.h。執行 'touch stamp-h' 讓您的專案新增這個檔案。
automake
automake 會尋找 Makefile.am 這個檔案,然後依據它找到的巨集產生 Makefile.in。當然,這個會在稍後的 configure script 用到。
GNU-style projects, or not
因為預設值 automake 會嘗試產生 GNU-style 的專案,因此如果一些該有的檔案不存在,automake 會向您抱怨。所以您可以用以下指令產生需要的空白文件:
touch NEWS README AUTHORS ChangeLog
如果您不需要 GNU-style 的檔案,您可以在您的 Makefile.am 增加以下這行:
AUTOMAKE_OPTIONS = foreign
Telling automake about your source files
使用下面這兩行來命名您的程式名稱,以及列出它的原始程式:
bin_PROGRAMS = hello
hello_SOURCES = hello.h hello.cc main.cc
注意:第二個變數的前置是依據第一個變數的。
The Whole Process
假設您已經概略的編輯完 Makefile.am 和 configure.in (底下有範例),藉由底下的指令,您應該能夠 build 您專案了:
autoheader
touch NEWS README AUTHORS ChangeLog
touch stamp-h
aclocal
autoconf
automake
./configure
make
當你想完整重新 build 專案,請重複最後五個步驟。
* autoheader - creates config.h.in
* aclocal - adds aclocal.m4 to directory.
* autoconf - creates configure from configure.in
* automake - Creates Makefile.in from Makefile.am
* ./configure - creates Makefile from Makefile.in
* aclocal - adds aclocal.m4 to directory.
* autoconf - creates configure from configure.in
* automake - Creates Makefile.in from Makefile.am
* ./configure - creates Makefile from Makefile.in
Sub Directories
當 然,專案的檔案應該被組織化的放在子目錄裡。理想上來說,原始檔和 makefile,configure scripts,以及 README 等等這些檔案,應該都放在專案的 src 這個子資料匣中。多層式的專案我們把它叫做 Deep 專案。我會列出應該處理的步驟,但是你依然可以看看範例程式。
當使用子目錄的時候,你必須坐下的步驟:
1. 增加 SUBDIRS 這一項到最頂層的 Makefile.am。例如:
SUBDIRS = doc intl po src tests
注意這些資料匣的名稱要以空白區分。
2. 在每一個子目錄中都要新增一個 Makefile.am。但是不需要 configure.in。而且要確定最頂層的 configure.in 中的 AC_OUPUT 巨集要加入檔名以產生 Makefile。
For sub directories containing additional source code
3. 增加 AC_PROG_RANLIB 巨集到您的 configure.in。這允許您在子目錄中 build 的 code 能夠暫時放到某個暫存目錄,以便之後用來和其他 code 作連結之用。
4. 增加一些巨集到 src 下的任何原始檔目錄的 Makefile.am。這將會 build 一個不會安裝的函式庫。你需要給定以 lib 字母為開頭的函式庫名稱,並且指定該函式庫的原始碼以及標頭檔,例如:
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = foo.h foo.cc
INCLUDES = -I@top_srcdir@/src/includes
注意 SOURCES 巨集會使用底線 '_' 來代替函式庫的名稱的點 '.'。而且要使用 top_srcdir 這個變數來參考到專案的最頂端。
5. 在上一層目錄使用 Makefile.am 的 LDADD 這個巨集,來連結任何可能用到這個暫時函式庫的 Code。例如:
LDADD = foofiles/libfoo.a
For sub directories containing non-source files
3. 一個子目錄下的 Makefile.am 應該包含像底下的這行:
EXTRA_DIST = somefile.txt someotherfile.html
這會告訴 automake 您要發布這些檔案,但是它們不需要編譯。
Example Files
底下就是範例檔了。它是一個使用一個標準函式庫的 C++ 專案。
看看 autoconf 和 automake 的手冊來參閱使用到的一些巨集以及變數。我不要這些範例因為註解而變的難以閱讀。
這個 Deep 專案的架構如下:
helloworld_cc
configure.in
Makefile.am
Makefile.am
src
Makefile.am
helloworld.h
helloworld.cc
main.cc
helloworld.h
helloworld.cc
main.cc
foofiles
Makefile.am
foo.h
foo.cc
foo.h
foo.cc
configure.in
AC_INIT(src/hello.cc)
AM_INIT_AUTOMAKE(hello,0.1)
AM_CONFIG_HEADER(config.h)
AC_PROG_CC
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_RANLIB
AC_OUTPUT(Makefile src/Makefile src/foofiles/Makefile)
Makefile.am
SUBDIRS = src
Makefile.am for the src directory
bin_PROGRAMS = hello
INCLUDES = foofiles
hello_SOURCES = hello.h hello.cc main.cc
SUBDIRS = foofiles
LDADD = foofiles/libfoo.a
Makefile.am for foofiles directory under src
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = foo.h foo.cc
INCLUDES = -I@top_srcdir@/
圖解
1.autoscan (autoconf): 掃描源代碼以搜尋普通的可攜性問題,比如檢查編譯器,庫,頭文件等,生成檔configure.scan,它是configure.ac的一個雛形。
2.aclocal (automake):根據已經安裝的巨集,用戶定義巨集和acinclude.m4檔中的宏將configure.ac檔所需要的巨集集中定義到檔 aclocal.m4中。aclocal是一個perl 腳本程式,它的定義是:“aclocal - create aclocal.m4 by scanning configure.ac”
user input files optional input process output files
================ ============== ======= ============
acinclude.m4 - - - - -.
V
.-------,
configure.ac ------------------------>|aclocal|
{user macro files} ->| |------> aclocal.m4
`-------'
3.autoheader(autoconf): 根據configure.ac中的某些巨集,比如cpp巨集定義,運行m4,聲稱config.h.in
user input files optional input process output files
================ ============== ======= ============
aclocal.m4 - - - - - - - .
|
V
.----------,
configure.ac ----------------------->|autoheader|----> autoconfig.h.in
`----------'
4.automake: automake將Makefile.am中定義的結構建立Makefile.in,然後configure腳本將生成的Makefile.in檔轉換為Makefile。如果在configure.ac中定義了一些特殊的宏,比如AC_PROG_LIBTOOL,它會調用libtoolize,否則它會自己產生config.guess和config.sub
user input files optional input processes output files
================ ============== ========= ============
.--------,
| | - - -> COPYING
| | - - -> INSTALL
| |------> install-sh
| |------> missing
|automake|------> mkinstalldirs
configure.ac ----------------------->| |
Makefile.am ----------------------->| |------> Makefile.in
| |------> stamp-h.in
.---+ | - - -> config.guess
| | | - - -> config.sub
| `------+-'
| | - - - -> config.guess
|libtoolize| - - - -> config.sub
| |--------> ltmain.sh
| |--------> ltconfig
`----------'
5.autoconf:將configure.ac中的宏展開,生成configure腳本。這個過程可能要用到aclocal.m4中定義的宏。
user input files optional input processes output files
================ ============== ========= ============
aclocal.m4 - - - - - -.
V
.--------,
configure.ac ----------------------->|autoconf|------> configure ----->autoconfig.h,Makefile