Tuesday, January 11, 2011

autoconf 與 automake 。有了這些工具,要進入 Unix Programming 的殿堂,可就是件輕鬆的事了。

這只是入門,僅僅是入門而已。對於內容有任何意見,也歡迎指教。本文件由
陳雍穆( armor ; armor AT netlab Dot cse Dot yzu Dot edu Dot tw )所作。
作者許可本文件於網路上自由流傳,但保留其它之著作權力。
你可以自由的散佈及使用本文件,只要這份聲明和作者的名字跟本文件不被分割開來,
並且這份聲明不被做任何的修改。


Abstract  
Pre-requisite 
Example
Detail
Future





Abstract





各位修計網的學弟妹,現在大家一定面臨到如何在 Unix 下快速開發程式的問題。在 Unix 系統上
寫C語言程式,根據老祖宗教科書的說法,都會要求模組化、分檔、註解,沒有人要看一個數十萬行的
main 函式。但是使用模組化、分檔撰寫程式,又要如何 compile 這些零零碎碎的檔案。如圖一所示,
檔案少的時候還可以這樣熱血一下,將執行檔 server 和 client 與各個 .o 檔編出來。但是如果手上的 project
是一個數百個分散的檔案時,這樣的作法並不是明智之舉。



圖一


圖二



在Unix系統上,有一個叫做make的工具,可以協助我們來開發和編譯程式,如圖二所示,只要打一個 make
指令就可以把圖一中數行的指令一次做完。不過要寫出一個 Makefile 就不是容易的事了,單是 GNU 本身的
manual ,看到就快打
退堂鼓了。雖然在資工系上有一份留傳久遠的
文件,大部分的人照著畫葫蘆也可以做一個漂亮的 Makefile
,但是總覺得要考慮一堆 "TAB" 就是麻煩的一件事。又如果我們的程式需要使用到各種不同的函式庫時,
當程式被移到另一部機械上,要檢查這部機械有沒有這些函式庫還是一個大問題。於是乎, GNU 當然有更好用的
工具來解決這些問題,那就是
autoconf

automake
有了這些工具,要進入 Unix Programming 的殿堂,可就是件輕鬆的事了。


Top




Pre-requisite




在進入如何使用 automake 之前,大家最好先了解一下 Makefile 是什麼東西。 Makefile 就是告訴 make 如何 compile 和 link 一個程式的檔案。
一個基本的 Makefile 格式如下:
target ... : prerequisites ...
        command
        ...
        ...

  • target ( 目標 ):是一個由程式產生的檔案,他可以是一個執行檔,或是一個目的檔。target也可以是一作用的名稱,例如 clean 或 install 。


  • prerequisite ( 必備檔案 ):一些能建立 target 的程式檔案,一個 target 通常由數個檔案建立。


  • command ( 命令列 ):描述 make 要執行的動作。由一個或一個以上的 tab ( 4個字元空白 )開頭。


  • 註解:在 Makefile 中,以"#"為開頭的的文字皆為註解,在 make 工作時會忽略他們。


  • 多行描述:在寫 Makefile 中,如果命令長度超過一行時,可以在該行的最後加上反斜線( \ )表示下一行為本行之延續,兩行應視為一行來處理。


  • macro ( 巨集 ):在 GNU mamual 中寫到,一個 variable 是在 Makefile 中定義一個字串或一段文字的名稱,
    通常代替一段作用在targets, prerequisites, commands 上,複雜且詳細的命令。在某些版本的 make 中,variables 稱做 macros 。 macro巨集的格式如下
    <string> = <value>
    

下面是幾個 Makefile 的範例。

範例一:

edit : main.o kbd.o command.o display.o \
       insert.o search.o files.o utils.o
        cc -o edit main.o kbd.o command.o display.o \
                   insert.o search.o files.o utils.o

main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit main.o kbd.o command.o display.o \
           insert.o search.o files.o utils.o

範例二:

objects = main.o kbd.o command.o display.o \
          insert.o search.o files.o utils.o

edit : $(objects)
        cc -o edit $(objects)
main.o : main.c defs.h
        cc -c main.c
kbd.o : kbd.c defs.h command.h
        cc -c kbd.c
command.o : command.c defs.h command.h
        cc -c command.c
display.o : display.c defs.h buffer.h
        cc -c display.c
insert.o : insert.c defs.h buffer.h
        cc -c insert.c
search.o : search.c defs.h buffer.h
        cc -c search.c
files.o : files.c defs.h buffer.h command.h
        cc -c files.c
utils.o : utils.c defs.h
        cc -c utils.c
clean :
        rm edit $(objects)

有關Makefile的詳細說明,可以參考網路上其他的文件。

在進入下一個章節前,先檢查你的系統已經安裝以下的軟體:

你可以在shell下鍵入指令 whereis XXXX ,來尋找你要的XXXX。EX: whereis gcc 。如下圖。

你可以使用各套件所包好的 binary 檔或是 source code 安裝。以下四套 Linux 套件都可以在 ftp://ftp.yzu.edu.tw/pub3/Linux/iso-image 下載光碟燒錄檔。

名稱 製作公司 網頁
RedHat Linux Red Hat www.redhat.com
Slackware Linux Patrick Volkerding www.slackware.com
Debian GNU/Linux GNU www.debian.org
Linux-Mandrake Mandrake soft www.linux-mandrake.com

Top


Example

本章節提供一個使用automake的過程給大家參考。automake有許多參數設定,我們裡面只簡單使用幾個,其他詳細的部分,還是要 各位去翻閱 GNU automake manual 和 GNU autoconf manual

當我們已經寫好一組程式後,希望使用 automake 來替我們把 Makefile 做好。如圖三所示,在這組範例程式裡, 總共有 client.c client.h gettime.c gettime.h gmt2local.c gmt2local.h inits.c inits.h server.c config.h 十個檔案。程式主要產生一個 client 和 server 的執行檔,做網路傳輸。圖中的 Makefile.OLD.TXT 是舊的 Makefile ,在這裡我們不會用到他。

圖三

圖四

第一步:使用 autoscan 產生一個 configure.scan ,把他更名成 configure.in 。如圖三、圖四所示。

第二步:修改 configure.in 的內容。由 autoscan 產生的預設檔並不一定一樣,隨系統套件廠商的修改而不同。下面圖五是本範例產生的 預設 configure.in 檔,圖六是修改過的 configure.in 檔。

圖五

圖六

在改過的 configure.in 檔,我們加入了 AM_INIT_AUTOMAKE(s907441, 1.0) 與 AC_PROG_CC ,並更改了 AC_OUTPUT(Makefile) 。

  • AC_INIT(FILE) :autoscan 自行產生的,不要修改。
  • AM_INIT_AUTOMAKE(PACKAGE,VERSION) :這是必備的巨集,PACKAGE 是我們所要產生軟體套件的名稱,VERSION是版本編號,加在 AC_INIT(FILE) 後面。

  • AC_PROG_CC :檢查系統的 C compiler 。

  • AC_OUTPUT(FILE) :Automake 使用這個設定來決定要產生什麼檔案。我們要產生 Makefile 所以填入 Makefile 。

  • 以 dnl 開頭的都是註解。

這次作業上傳是使用學號當檔名,所以我們把 AM_INIT_AUTOMAKE(PACKAGE,VERSION) 的 PACKAGE 設定為學號, VERSION 設定為版本。換句話說,如何在作業繳交期限前有更動 作業版本,就把 VERSION 加 1 ,再執行下面的其他步驟。其他參數的設定,參考GNU autoconf manual

第三步:執行 aclocal 和 autoconf ,分別會產生 aclocal.m4 及 configure 兩個檔案,如圖七。

圖七

第四步:使用編輯器,建立 Makefile.am 檔,內容如圖八所示。

圖八

  1. AUTOMAKE_OPTIONS= foreign

    AUTOMAKE_OPTIONS 所記錄的是嚴謹度。主要是訂定一個套件是否符合 GNU 標準的條件。預設值是 GNU ,這樣一來
    整個 package 就要有一些 GNU規定的檔案存在,例如 INSTALL , NEWS , README , COPYING , AUTHORS , and ChangeLog 檔等。
    foreign 是比較寬鬆的等級,只確定設定檔能完整的工作。


  2. bin_PROGRAMS= client server

    bin_PROGRAMS
    是決定要產生的執行檔檔名。如果要產生多個執行檔,每個檔名用空白字元隔開。換句話說,可以對應到我們上一個章節所講的
    target 來理解。


  3. client_SOURCES= client.c config.h

    這裡就比較明顯,foo_SOURCES 跟上一個章節所講的 prerequisite 對應,這樣大家了解了吧!!而在這裡也可以使用巨集來工作。

    xs = a.c b.c
    foo_SOURCES = c.c $(xs)
    
    automake 會將 $(xs) 換成 a.c b.c ,整個 foo_SOURCES = c.c a.c b.c 。


  4. server_SOURCES= server.c config.h gettime.c gettime.h gmt2local.c gmt2local.h inits.c inits.h

    同上

第五步:使用 automake --add-missing 將 Makefile.in 產生出來,如圖九所示。 automake 會根據 Makefile.am , 同時 scan configure.in 檔,來產生對應的Makefile.in 。

圖九

第六步:執行 ./configure ,我們可以看到 automake 強大的功能,他會去 check 一堆 header 檔、 function call 、 compiler 等等,如圖十所示。此時我們期望已久的 Makefile 就產生了。 configure 檢查 header 的動作是根據configure.in裡面所設定的 AC_CHECK_HEADERS( ) 和AC_CHECK_FUNCS( ) 裡面所設定的內容來 check 。

圖十

第七步:執行 make ,讓 make 根據 Makefile 來 compile 和 link 程式,如圖十一所示。而完成狀況 如圖十二所示,已經可以看到執行檔 client 和 server 。

圖十一

圖十二

Top


Detail

本段補充前幾章零碎缺漏的部分。

A. 用 automake 所產生的 Makefile 檔案提供了那些功能。

  1. make all

    與直接使用 make 指令相同。


  2. make clean

    清除所有的執行檔與目的檔 ( .o )如圖十三。




    圖十三


  3. make distclean

    make clean 加上把 ./configure 產生的 Makefile 等檔案刪除,如圖十四。




    圖十四


  4. make install

    把編譯好的執行檔安裝到系統目錄中。預設會放到 /usr/local/bin 裡面。我們可以用 ./configure --help
    看到在 Configuration 的設定項目中,prefix 是設成 /usr/local , bindir 就是 EPREFIX/bin ,EPREFIX
    又跟 prefix 相同。如果我們在執行 ./configure 產生 Makefile 檔時沒有指定目錄,預設就是這些。
    所以,我們也可以根據 ./configure 時使用的參數,來改變程式最後要安裝的目錄。
    ./configure --prefix=PREFIX , PREFIX 就是你想安裝的目錄。 ./configure --prefix=/www ,就是
    把程式執行檔裝到 /www 去。


  5. make dist

    將程式和相關的檔案包裝成一個 tar.gz 的壓縮檔。這個 tar.gz 檔根據在 configure.in 裡,
    AM_INIT_AUTOMAKE(PACKAGE,VERSION) 填寫的 PACKAGE 和 VERSION 對應欄位建立。
    檔名為 package-version.tar.gz ,如圖十五。




    圖十五


  6. make distcheck

    make dist 加上檢查產生的 tar.gz 檔是否能正常工作。包括解開 tar.gz , ./configure , make all 。
    經檢查過的 tar.gz 就可以提供散播 (distribution) ,如圖十六。

圖十六

B. 準備散佈的套件換到另一個平台能不能執行。

configure 是一個 shell script,它可以在一般 Unix 的 sh 這個 shell 下執行,而其他的 install-sh , missing , mkinstalldirs 也都是 shell script 。所以很難有問題產生。

C. 更新的程式組如何重新包裝。

  1. make distclean
  2. 修改configure.in 裡的 AM_INIT_AUTOMAKE(PACKAGE,VERSION) 中的VERSION。
  3. aclocal
  4. autoconf
  5. 建立 Makefile.am 檔
  6. automake --add-missing
  7. make distcheck

D. 更新的程式組如何測試。

這是有點笨的問題,如果只是 function 小部分修改,直接重新 make 看看 gcc 回應的資料就知道。 如果大到翻修結構,增減檔案,那還是重頭 run 一次,翻新 Makefile 吧。

Top


Future

其他還有許多功能與設定,例如使用其他的 compiler ( C++ / Assembly / Fortran 77 / Java / Yacc and Lex )、多層目錄的設定、建立 shared library 、各種巨集的使用等等,這些東西並非一時間就可以完全 寫成稿 ( 跟翻譯 manual 差不多 )。其他部分,就有待各位自行 K 手冊了。 Reference: http://netlab.cse.yzu.edu.tw/~armor/columns/automake/automake.htm

No comments: