來源: http://www.pigfoot.org/cc/devel/auto1/


Abstract

在 Unix 底下,automakeautoconf 常被用來管理 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 加入一個巨集時,然後必須執行 aclocalautoconf,因為 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

AC_PROG_INSTALL
會產生安裝目的地,好讓使用者打 make install 便能安裝這套軟體。

AC_OUTPUT
指出應該產生的 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

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

src

Makefile.am
helloworld.h
helloworld.cc
main.cc

foofiles

Makefile.am
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@/

台南小新 發表在 痞客邦 PIXNET 留言(0) 人氣()