Posted on 2008-06-25 11:18
T.S Liu 閱讀(359)
評論(0) 編輯 收藏 引用 所屬分類:
ubuntu
在 Unix 上寫過程序的人一般都遇到過 Makefile,尤其是用 C 來開發(fā)程序的人。用 make 來開發(fā)和編譯程序的確很方便,可是要寫出一個MakeFile就不那么簡單了。偏偏介紹 Makefile 的文件不多,GNU Make 那份印出來要幾百頁的文件,光看完 Overview 自己就快要先Over了,難怪許多人聞 Unix色變。本文將介紹如何利用 GNU Autoconf 及 Automake 這兩套軟件來幫助『自動』產(chǎn)生 Makefile 文件,并且讓開發(fā)出來的的軟件可以象 Apache, MySQL 和常見的 GNU 軟件一樣,只要會 ``./configure'', ``make'', ``make install'' 就可以把程序安裝到系統(tǒng)中。如果您有心開發(fā) Open Source 的軟件,或只是想在 Unix 系統(tǒng)下寫寫程序。希望這份介紹文件能幫助您輕松的進入 Unix Programming 的殿堂。 |
Makefile 基本上就是『目標(biāo)』(target), 『關(guān)聯(lián)』(dependencies) 和『動作』三者所組成的一系列規(guī)則。而 make 就會根據(jù) Makefile 的規(guī)則來決定如何編譯 (compile) 和連接 (link) 程式。實際上,make 可做的不只是編譯和連接程序,例如 FreeBSD 的 port collection 中,Makefile還可以做到自動下載遠程程序,解壓縮 (extract) , 打補丁 (patch),設(shè)定,然后編譯,安裝到系統(tǒng)中。 |
Makefile 基本結(jié)構(gòu)雖然很簡單,但是妥善運用這些規(guī)則就可以變換出許多不同的花樣。卻也因為這樣,許多剛剛開始學(xué)習(xí)寫Makefile 時會覺得沒有規(guī)范可以遵循,每個人寫出來的Makefile都不大一樣,不知道從哪里下手,而且常常會受到自己的開發(fā)環(huán)境的限制,只要環(huán)境參數(shù)不同或者路徑更改,可能 Makefile 就得跟著修改修改。雖然有 GNU Makefile Conventions (GNU Makefile慣例例)訂出一些使用 GNU 程式設(shè)計時撰寫 Makefile 的一些標(biāo)準(zhǔn)和規(guī)范,但是內(nèi)容很長而且很復(fù)雜,并且經(jīng)常作一些調(diào)整,為了減輕程序開發(fā)人員維護Makefile 的負(fù)擔(dān),因此出現(xiàn)了Automake。 |
程序設(shè)計者只需要寫一些預(yù)先定義好的宏 (macro),提交給Automake處理后會產(chǎn)生一個可以供 Autoconf 使用的 Makefile.in文件。再配合利用 Autoconf產(chǎn)生的自動培植設(shè)置文件 configure 即可產(chǎn)生一份符合符合 GNU Makefile 慣例的 Makeifle 了。 |
在開始使用 Automake 之前,首先確認(rèn)你的系統(tǒng)安裝有如下軟件: |
GNU Libtool (如果你需要產(chǎn)生 shared library) |
建議最好也使用 GNU C/C++ 編譯器 、GNU Make 以及其它 GNU 的工具程序來作為開發(fā)的環(huán)境,這些工具都是屬于 Open Source Software 不但免費而且功能強大。如果你是使用 Red Hat Linux 可以找到所有上述軟件的 rpm 文件,F(xiàn)reeBSD 也有現(xiàn)成的 package 可以直接安裝,或也可以自行下載這些軟件的源代碼回來安裝。下面的示例是在Red Hat Linux 5.2 + CLE2 的環(huán)境下所完成的。 |
Automake 所產(chǎn)生的 Makefile 除了可以做到程式的編譯和連接,也已經(jīng)把如何產(chǎn)生程序文件 (如 manual page, info 文件及 dvi 文件) 的動作,還有把源碼文件包裝起來以供發(fā)布都考慮進去了,所以程序源代碼所存放的目錄結(jié)構(gòu)最好符合GNU 的標(biāo)準(zhǔn)慣例,接下來就用一個hello.c 來做為例子。 |
在工作目錄下建立一個新的子目錄"devel"',再在 devel 下建立一個"hello"' 的子目錄,這個目錄將作為存放 hello這個程序及其相關(guān)文件的地方: |
int main(int argc, char** argv) { |
printf(``Hello, GNU!\n''); |
接下來就要用 Autoconf 及 Automake 來產(chǎn)生 Makefile 文件了, |
用 autoscan 產(chǎn)生一個 configure.in 的原型,執(zhí)行autoscan 后會產(chǎn)生一個configure.scan 的文件,可以用它作為 configure.in文件的藍本。 |
編輯 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 libraries. |
dnl Checks for header files. |
dnl Checks for typedefs, structures, and compiler characteristics. |
dnl Checks for library functions. |
執(zhí)行 aclocal 和 autoconf ,分別會產(chǎn)生 aclocal.m4 及 configure 兩個文件 |
aclocal.m4 configure configure.in hello.c |
編輯 Makefile.am 文件,內(nèi)容如下 |
AUTOMAKE_OPTIONS= foreign |
執(zhí)行 automake --add-missing ,Automake 會根據(jù)Makefile.am 文件產(chǎn)生一些文件,包含最重要的 Makefile.in |
% automake --add-missing automake: configure.in: installing `./install-sh' automake: configure.in: installing `./mkinstalldirs' automake: configure.in: installing `./missing' |
% ./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 |
現(xiàn)在你的目錄下已經(jīng)產(chǎn)生了一個 Makefile 檔,下個 ``make'' 指令就可以開始編譯 hello.c 成執(zhí)行檔,執(zhí)行 ./hello 和 GNU 打聲招呼吧! |
% make gcc -DPACKAGE=\"hello\" -DVERSION=\"1.0\" -I. -I. -g -O2 -c hello.c gcc -g -O2 -o hello hello.o % ./hello Hello! GNU! |
你還可以試試 ``make clean'',''make install'',''make dist'' 看看會有什麼結(jié)果。你也可以把產(chǎn)生出來的 Makefile 秀給你的老闆,讓他從此對你刮目相看 :-) |
上述產(chǎn)生Makefile 的過程和以往自行編寫的方式非常不一樣,舍棄傳統(tǒng)自定義make 的規(guī)則,使用 Automake 只需用到一些已經(jīng)定義好的宏就可以了。我們把宏及目標(biāo) (target)寫在Makefile.am 文件內(nèi),Automake 讀入 Makefile.am 文件后會把這一串已經(jīng)定義好的宏展開并產(chǎn)生相對應(yīng)的 Makefile.in 文件,然后再由 configure這個 shell script 根據(jù) Makefile.in 產(chǎn)生合適的Makefile。 |
利用 autoconf 及 automake產(chǎn)生Makefile 的流程
|
上圖表示在上一范例中要使用的文件檔案及產(chǎn)生出來的文件,有星號 (*) 者代表可執(zhí)行文件。在此示例中可由 Autoconf 及 Automake 工具所產(chǎn)生的額外文件有 configure.scan、aclocal.m4、configure、Makefile.in,需要自行加入設(shè)置的有configure.in 及 Makefile.am。 |
Autoconf 是用來產(chǎn)生 'configure'文件的工具。'configure' 是一個 shell script,它可以自動設(shè)定原始程序以符合各種不同平臺上Unix 系統(tǒng)的特性,并且根據(jù)系統(tǒng)參數(shù)及環(huán)境產(chǎn)生合適的Makefile文件或C 的頭文件(header file),讓原始程式可以很方便地在不同的平臺上進行編譯。Autoconf會讀取 configure.in 文件然后產(chǎn)生'configure' 這個 shell script。 |
configure.in 文件內(nèi)容是一系列GNU m4 的宏,這些宏經(jīng)autoconf處理后會變成檢查系統(tǒng)特性的shell scripts。 configure.in 內(nèi)宏的順序并沒有特別的規(guī)定,但是每一個configure.in 文件必須在所有宏前加入 AC_INIT 宏,然后在所有宏的最后加上 AC_OUTPUT宏。可先用 autoscan 掃描原始文件以產(chǎn)生一個 configure.scan 文件,再對 configure.scan 做些修改成 configure.in 文件。在范例中所用到的宏如下: |
該宏用來檢查源代碼所在路徑,autoscan 會自動產(chǎn)生,一般無須修改它。 |
AM_INIT_AUTOMAKE(PACKAGE,VERSION) |
這個是使用 Automake 所必備的宏,PACKAGE 是所要產(chǎn)生軟件套件的名稱,VERSION 是版本編號。 |
檢查系統(tǒng)可用的C編譯器,若源代碼是用C寫的就需要這個宏。 |
設(shè)置 configure 所要產(chǎn)生的文件,若是Makefile ,configure 便會把它檢查出來的結(jié)果帶入 Makefile.in 文件后產(chǎn)生合適的 Makefile。 |
實際上,這里使用 Automake 時,還需要一些其他的宏,這些額外的宏我們用 aclocal來幫助產(chǎn)生。執(zhí)行 aclocal會產(chǎn)生aclocal.m4 文件,如果無特別的用途,可以不需要修改它,用 aclocal 所產(chǎn)生的宏會告訴 Automake如何動作。 |
有了 configure.in 及 aclocal.m4兩個文件以后,便可以執(zhí)行 autoconf來產(chǎn)生 configure 文件了。 |
接下來要編輯Makefile.am 文件,Automake 會根據(jù) configure.in 中的宏把Makefile.am 轉(zhuǎn)成 Makefile.in 文件。 Makefile.am 文件定義所要產(chǎn)生的目標(biāo): |
設(shè)置 automake 的選項。Automake 主要是幫助開發(fā) GNU 軟件的人員來維護軟件,所以在執(zhí)行 automake 時,會檢查目錄下是否存在標(biāo)準(zhǔn) GNU 軟件中應(yīng)具備的文件,例如 'NEWS'、'AUTHOR'、'ChangeLog' 等文件。設(shè)置 foreign 時,automake 會改用一般軟件的標(biāo)準(zhǔn)來檢查。 |
定義要產(chǎn)生的執(zhí)行文件名。如果要產(chǎn)生多個執(zhí)行文件,每個文件名用空白符隔開。 |
定義 'hello' 這個執(zhí)行程序所需要的原始文件。如果 'hello'這個程序是由多個原始文件所產(chǎn)生,必須把它所用到的所有原始文件都列出來,以空白符隔開。假設(shè) 'hello' 還需要 'hello.c'、'main.c'、'hello.h' 三個文件的話,則定義 |
hello_SOURCES= hello.c main.c hello.h |
如果定義多個執(zhí)行文件,則對每個執(zhí)行程序都要定義相對的filename_SOURCES。 |
編輯好 Makefile.am 文件,就可以用 automake --add-missing來產(chǎn)生 Makefile.in。加上 --add-missing 選項來告訴 automake順便假如包裝一個軟件所必須的文件。Automake產(chǎn)生生出來的 Makefile.in 文件是完全符合 GNU Makefile 的慣例,只要執(zhí)行 configure這個shell script 便可以產(chǎn)生合適的 Makefile 文件了。 |
利用 configure 所產(chǎn)生的 Makefile文件有幾個預(yù)先設(shè)定的目標(biāo)可供使用,這里只用幾個簡述如下: |
產(chǎn)生設(shè)定的目標(biāo),既次范例中的執(zhí)行文件。只敲入make 也可以,此時會開始編譯源代碼,然后連接并產(chǎn)生執(zhí)行文件。 |
清除之前所編譯的執(zhí)行文件及目標(biāo)文件(object file, *.o)。 |
除了清除執(zhí)行文件和目的文件以外,也把 configure 所產(chǎn)生的 Makefile 清除掉。 |
將程序安裝到系統(tǒng)中,若源碼編譯成功,且執(zhí)行結(jié)果正確,便可以把程序安裝到系統(tǒng)預(yù)先設(shè)定的執(zhí)行文件存放路徑中,若用 bin_PROGRAMS 宏的話,程序會被安裝到 /usr/local/bin下。 |
將程序和相關(guān)的文檔包裝為一個壓縮文檔以供發(fā)布 (distribution) 。執(zhí)行完在目錄下會產(chǎn)生一個以PACKAGE-VERSION.tar.gz 為名稱的文件。PACKAGE 和 VERSION 這兩個參數(shù)是根據(jù) configure.in 文件中 AM_INIT_AUTOMAKE(PACKAGE, VERSION) 的定義。在此范例中會產(chǎn)生 'hello-1.0.tar.gz' 的文件。 |
和 make dist 類似,但是加入檢查包裝以后的壓縮文件是否正常,這個目標(biāo)除了把程序和相關(guān)文檔包裝成 tar.gz 文件外,還會自動把這個壓縮文件解開,執(zhí)行 configure,并執(zhí)行 make all ,確認(rèn)編譯無錯誤以后,戶顯示這個 tar.gz 文件已經(jīng)準(zhǔn)備好可以發(fā)布了。這個檢查非常有用,檢查過關(guān)的套件,基本上可以給任何具備 GNU 開發(fā)環(huán)境的人去重新編譯成功。就 hello-1.tar.gz 這個范例而言,除了在Red Hat Linux 上,在 FreeBSD 2.2.x 也可以正確編譯。 |
要注意的是,利用 Autoconf 及 Automake 所產(chǎn)生出來的軟件套件是可以在沒有安裝 Autoconf 及 Automake 的環(huán)境使用的,因為 configure 是一個 shell script,它己被設(shè)計為可以在一般 Unix 的 sh 這個 shell 下執(zhí)行。但是如果要修改 configure.in 及 Makefile.am 文件再產(chǎn)生新的 configure 及 Makefile.in 文件時就一定要有 Autoconf 及 Automake 了。 |
Autoconf 和 Automake 功能十分強大,可以從它們附帶的 info 穩(wěn)當(dāng)4中找到詳細(xì)的使用方法說明。你也可以從許多現(xiàn)有的GNU 軟件或 Open Source 軟件中找到相關(guān)的 configure.in 或 Makefile.am 文件,他們是學(xué)習(xí) Autoconf 及 Automake 更多技巧的最佳范例。 |
這個簡介只用到了 Autoconf 及 Automake 的皮毛罷了,如果你有心加入 Open Source 軟件開發(fā)的行列,希望這篇文章可以幫助你對產(chǎn)生 Makefile 有個簡單的了解。其它有關(guān)開發(fā) GNU 程式或 C 程序設(shè)計及 Makefile 的詳細(xì)運用及技巧,建議從 GNU Coding Standards (GNU 編碼規(guī)定) 讀起,里面包含了 GNU Makefile 慣例,及開發(fā) GNU 軟件的標(biāo)準(zhǔn)程序和慣例。這些 GNU 軟件的在線說明文件可以在 http://www.gnu.org/ 上找到。 |
利用 Autoconf 及 Automake,產(chǎn)生一個 Makefile 似乎不再象以前那么困難了,而使用 Autoconf 也使得我們在不同平臺上或各家 Unix 之間發(fā)布及便宜程序變的簡單,這對于在Unix 系統(tǒng)上程序開發(fā)員來說減輕了許多負(fù)擔(dān)。妥善運用這些 GNU 的工具軟件,可以幫助我們更容易的去開發(fā)程序,而且更容易維護源代碼。 |