使用Automake,Autoconf生成Makefile

在Unix上寫過程序的人尤爲是用 C 來開發程序的人通常都遇到過 Makefile,用 make 來開發和編譯程序的確很方便,但是要寫出一個Makefile就不那麼簡單了。GNU Make 那份幾百頁的文件,讓許多人懼怕。固然,如今關於make的文檔比較多,不過寫一個Makefile老是一件很煩人的事情,GNU Autoconf 及 Automake 這兩個軟件就是幫助程序開發者輕鬆產生Makefile 文件的。如今的GNU軟件如Apache, MySQL Minigui等都是利用Autoconf,Automake實現自動編譯的。用戶只要使用 「./configure」, 「make」, 「make install」 就能夠把程序安裝到系統中。

簡介
Makefile 基本上就是『目標』(target), 『關聯』(dependencies) 和『動做』三者所組成的一系列規則。而 make 就是根據 Makefile 的規則決定如何編譯 (compile) 和鏈接 (link) 程序或者其它動做。固然,make 可作的不僅是編譯和鏈接程序,例如 FreeBSD 的 port collection 中,Makefile還能夠作到自動下載遠程程序,解壓縮 (extract) , 打補丁 (patch),設定,而後編譯,安裝到系統中。

Makefile 基本結構雖然很簡單,可是妥善運用這些規則就能夠變換出許多不一樣的花樣。卻也由於這樣,許多人剛開始學寫Makefile 時會以爲沒有規範能夠遵循,每一個人寫出來的Makefile都不大同樣,不知道從哪裏下手,並且經常會受到開發環境的限制,只要環境參數不一樣或者路徑更改,可能 Makefile 就得跟着修改。雖然有GNU Makefile Conventions (GNU Makefile慣例)制訂出一些在進行 GNU 程序設計時寫 Makefile 的一些標準和規範,可是其內容很長並且很複雜,而且常常做一些調整,爲了減輕程序開發人員維護Makefile 的負擔,就出現了Automake。

利用Automake,編程者只須要寫一些預先定義好的宏 (macro),提交給Automake處理,就會產生一個能夠供 Autoconf 使用的 Makefile.in文件。再配合使用 Autoconf產生的自動配置文件 configure 便可產生一份符合 GNU Makefile 慣例的 Makeifle 了。 

須要的軟件
在開始使用 Automake 以前,首先確認你的系統安裝有以下軟件:

1. GNU Automake
2. GNU Autoconf
3. GNU m4
4. perl
5. GNU Libtool (若是你須要產生 shared library)

最好也使用 GNU C/C++ 編譯器 、GNU Make 以及其它 GNU 的工具程序來做爲開發的環境,這些工具都是屬於 Open Source Software 不但免費並且功能強大。若是你是使用 Red Hat Linux 能夠找到全部上述軟件的 rpm 文件。 

一個簡單的例子
Automake 所產生的 Makefile 除了能夠作到程序的編譯和鏈接,也能夠用來生成文檔(如 manual page, info 文件等),還能夠有把源碼文件包裝起來以供發佈,因此程序源代碼所存放的目錄結構最好符合GNU 的標準慣例,接下來就用一個hello.c 來作爲例子。

在工做目錄下創建一個新的子目錄devel,再在 devel 下創建一個"hello"' 的子目錄,這個目錄將
做爲存放 hello這個程序及其相關文件的地方:
% mkdir devel;cd devel;mkdir hello;cd hello
用編輯器寫一個hello.c文件,
#i nclude <stdio.h>
int main(int argc, char** argv)
{
printf(「Hello, GNU!n」);
return 0;
}
接下來就要用 Autoconf 及 Automake 來產生 Makefile 文件了,

1. 用 autoscan 產生一個 configure.in 的原型,執行autoscan 後會產生一個configure.scan 的文件,能夠用它做爲 configure.in文件的藍本。
% autoscan
% ls
configure.scan hello.c
2. 編輯 configure.scan文件,以下所示,並且更名爲configure.in
dnl Process this file with Autoconf to produce a configure script.
AC_INIT(hello.c)
AM_INIT_AUTOMAKE(hello, 1.0)
dnl Checks for programs.
AC_PROG_CC
dnl Checks for libraries.
dnl Checks for header files.
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library functions.
AC_OUTPUT(Makefile)
3. 執行 aclocal 和 Autoconf ,分別會產生 aclocal.m4 及 configure 兩個文件
% aclocal
% Autoconf
% ls
aclocal.m4 configure configure.in hello.c
4. 編輯 Makefile.am 文件,內容以下
AUTOMAKE_OPTIONS= foreign
bin_PROGRAMS= hello
hello_SOURCES= hello.c
5. 執行 Automake --add-missing ,Automake 會根據Makefile.am 文件產生一些文件,包含最重要的Makefile.in
% Automake --add-missing
Automake: configure.in: installing `./install-sh'
Automake: configure.in: installing `./mkinstalldirs'
Automake: configure.in: installing `./missing'
6. 最後執行 ./configure:
% ./configure
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
checking for working Autoconf... found
checking for working Automake... found
checking for working autoheader... found
checking for working makeinfo... found
checking for gcc... gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
updating cache ./config.cache
creating ./config.status
creating Makefile

$ ls
Makefile aclocal.m4 config.status hello.c mkinstalldirs
Makefile.am config.cache configure install-sh
Makefile.in config.log configure.in missing
現在你的目錄下已經產生了一個 Makefile 文件,輸入make指令就能夠編譯 hello.c 了!
% make
gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c hello.c
gcc -g -O2 -o hello hello.o

你還能夠試試 「make clean「,」make install「,」make dist「:
[root@localhost hello]# make clean
test -z "hello " || rm -f hello
rm -f *.o core *.core
[root@localhost hello]# make install
gcc -DPACKAGE="hello" -DVERSION="1.0" -I. -I. -g -O2 -c hello.c
gcc -g -O2 -o hello hello.o
make[1]: Entering directory `/home/joe/devel/hello'
/bin/sh ./mkinstalldirs /usr/local/bin
/usr/bin/install -c hello /usr/local/bin/hello
make[1]: Nothing to be done for `install-data-am'.
make[1]: Leaving directory `/home/joe/devel/hello'
[root@localhost hello]# make dist
rm -rf hello-1.0
mkdir hello-1.0
chmod 777 hello-1.0
here=`cd . && pwd`;
top_distdir=`cd hello-1.0 && pwd`;
distdir=`cd hello-1.0 && pwd`;
cd .
&& Automake --include-deps --build-dir=$here --srcdir-name=. --output-dir=$top_distdir --foreign Makefile
chmod -R a+r hello-1.0
GZIP=--best gtar chozf hello-1.0.tar.gz hello-1.0
rm -rf hello-1.0
一切工做得很好! 固然,在make install時因爲須要向系統目錄拷貝文件,您須要有root權限。

更進一步
上述產生Makefile 的過程和以往自行編寫的方式很是不同,使用 Automake 只需用到一些已經定義好的宏就能夠了。咱們把宏及目標 (target)寫在Makefile.am 文件內,Automake 讀入 Makefile.am 文件後會把這一串已經定義好的宏展開併產生相對應的
Makefile.in 文件,而後再由configure這個 shell script 根據 Makefile.in 產生合適的Makefile。
具體流程以下所示:
代碼 --> [autoscan*] --> [configure.scan] --> configure.in
configure.in --. .------> Autoconf* -----> configure
+---+
[aclocal.m4] --+ `---.
[acsite.m4] ---' |
+--> [autoheader*] -> [config.h.in]
[acconfig.h] ----. |
+-----'
[config.h.top] --+
[config.h.bot] --'

Makefile.am --&#61664; [Autoconf*] -------> Makefile.in

.-------------> config.cache
configure* ------------+-------------> config.log
|
[config.h.in] -. v .-> [config.h] -.
+--> config.status* -+ +--> make*
Makefile.in ---' `-> Makefile ---'
上圖表示在整個過程當中要使用的文件及產生出來的文件,有星號 (*) 表明可執行文件。在此示例中可由 Autoconf 及 Automake 工具所產生的額外文件有 configure.scan、aclocal.m四、configure、Makefile.in,須要加入設置的有configure.in 及 Makefile.am。 開發者要書寫的文件集中爲confiugre.in和Makefile.am,在minigui項目中,咱們把一系列的命令集中到一個批處理文件中:autogen.sh:
#!/bin/sh
aclocal
autoheader
Automake --add-missing
Autoconf
只要執行該批處理文件,結合configure.in和Makefile.am,就能夠生成須要的Makefile了。 編輯 configure.in 文件 Autoconf 是用來產生 'configure'文件的工具。'configure' 是一個 shell script,它能夠自動設定一些編譯參數使程序可以條件編譯以符合各類不一樣平臺的Unix 系統。Autoconf會讀取configure.in 文件而後產生'configure' 這個 shell script。 configure.in 文件內容是一系列GNU m4 的宏,這些宏經Autoconf處理後會變成檢查系統特性的shell scripts。 configure.in文件中宏的順序並無特別的規定,可是每個configure.in 文件必須在全部其它宏前加入 AC_INIT 宏,而後在全部其它宏的最後加上 AC_OUTPUT宏。通常可先用 autoscan 掃描原始文件以產生一個 configure.scan 文件,再對 configure.scan 作些修改爲 configure.in 文件。在例子中所用到的宏以下: dnl 這個宏後面的內容不會被處理,能夠視爲註釋 AC_INIT(FILE) 該宏用來檢查源代碼所在路徑,autoscan 會自動產生,通常無須修改它。 AM_INIT_AUTOMAKE(PACKAGE,VERSION) 這個是使用 Automake 所必備的宏,PACKAGE 是所要產生軟件的名稱,VERSION 是版本編號。 AC_PROG_CC 檢查系統可用的C編譯器,若源代碼是用C寫的就須要這個宏。 AC_OUTPUT(FILE) 設置 configure 所要產生的文件,如果Makefile ,configure 便會把它檢查出來的結果填充到Makefile.in 文件後產生合適的 Makefile。 實際上,在使用 Automake 時,還須要一些其餘的宏,這些額外的宏咱們用 aclocal來幫助產生。執行 aclocal會產生aclocal.m4 文件,若是沒有特別的用途,不須要修改它,用 aclocal 所產生的宏會告訴 Automake如何動做。 有了 configure.in 及 aclocal.m4兩個文件之後,即可以執行 Autoconf來產生 configure 文件了。 編輯Makefile.am 文件 接下來要編輯Makefile.am 文件,Automake 會根據 configure.in 中的宏並在perl的幫助下把Makefile.am 轉成 Makefile.in 文件。 Makefile.am 文件定義所要產生的目標: AUTOMAKE_OPTIONS 設置 Automake 的選項。Automake 主要是幫助開發 GNU 軟件的人員來維護軟件,因此在執行Automake 時,會檢查目錄下是否存在標準 GNU 軟件中應具有的文件,例如 'NEWS'、'AUTHOR'、 'ChangeLog' 等文件。設置爲foreign 時,Automake 會改用通常軟件的標準來檢查。 bin_PROGRAMS 定義要產生的執行文件名。若是要產生多個執行文件,每一個文件名用空白符隔開。 hello_SOURCES 定義 'hello' 這個執行程序所須要的原始文件。若是 'hello'這個程序是由多個原始文件所產生, 必須把它所用到的全部原始文件都列出來,以空白符隔開。假設 'hello' 還須要 'hello.c'、'main.c'、'hello.h' 三個文件的話,則定義 hello_SOURCES= hello.c main.c hello.h 若是定義多個執行文件,則對每一個執行程序都要定義相對的filename_SOURCES。 編輯好 Makefile.am 文件,就能夠用 Automake --add-missing來產生 Makefile.in。加上 --add-missing 選項來告訴 Automake順便加入包裝一個軟件所必須的文件,若是你不使用該選項,Automake可能會抱怨缺乏了什麼文件。Automake產生出來的 Makefile.in 文件是徹底符合 GNU Makefile 慣例的,只要執行 configure這個shell script 即可以產生合適的 Makefile 文件了。 使用 Makefile 利用 configure 所產生的 Makefile文件有幾個預先設定的目標可供使用,這裏只用幾個簡述以下: make all 產生設定的目標,既範例中的可執行文件。只敲入make 也能夠,此時會開始編譯源代碼,而後鏈接併產生執行文件。 make clean 清除以前所編譯的可執行文件及目標文件(object file, *.o)。 make distclean 除了清除可執行文件和目標文件之外,也把 configure 所產生的 Makefile 清除掉。 一般在發佈軟件前執行該命令。 make install 將程序安裝到系統中,若源碼編譯成功,且執行結果正確,即可以把程序安裝到系統預先設定的執行文件存放路徑中,若用 bin_PROGRAMS 宏的話,程序會被安裝到 /usr/local/bin下。 make dist 將程序和相關的文檔包裝爲一個壓縮文檔以供發佈 (distribution) 。執行完在目錄下會產生一個以 PACKAGE-VERSION.tar.gz 爲名稱的文件。PACKAGE 和 VERSION 這兩個參數是根據 configure.in 文中 AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定義。在咱們的例子中會產生 'hello-1.0.tar.gz' 的文件。 make distcheck 和 make dist 相似,可是加入檢查包裝之後的壓縮文件是否正常,這個目標除了把程序和相關文檔包裝成 tar.gz 文件外,還會自動把這個壓縮文件解開,執行 configure,並執行 make all ,確認編譯無錯誤之後,方顯示這個 tar.gz 文件已經準備好並能夠發佈了。當你看到: ========================================== hello-1.0.tar.gz is ready for distribution ========================================== 就能夠放心地發佈您的軟件了,檢查過關的套件,基本上能夠給任何具有 GNU 開發環境的人去從新編譯成功。 要注意的是,利用 Autoconf 及 Automake 所產生出來的軟件套件是能夠在沒有安裝 Autoconf 及 Automake 的環境使用的,由於 configure 是一個 shell script,它己被設計爲能夠在通常 Unix 的 sh 這個 shell 下執行。可是若是要修改 configure.in 及 Makefile.am 文件再產生新的 configure 及 Makefile.in 文件時就必定要有 Autoconf 及 Automake 了。 相關資料 一般咱們掌握了一些入門知識就能夠開始實踐了,在有新的需求時,參照相關的文檔和別人的例子解決問題,在實踐中不斷提升。 Autoconf 和 Automake 功能十分強大,能夠從它們附帶的 info 文檔中找到詳細的使用說明。或者您喜歡html,能夠從gun站點上下載hmtl版本。你也能夠從許多現有的GNU 軟件或 Open Source 軟件如Minigui中找到相關的 configure.in 或 Makefile.am 文件,他們是學習 Autoconf 及 Automake 更多技巧的最佳範例。
相關文章
相關標籤/搜索