GNU Autotools 初探 & share library 的蠢事

說GNU Autotools 可能很多人不清楚那是什麼?但是編譯提到編譯套件三部曲"./configure ; make ; make install",就很清楚了,這就是Autotools的功勞,它大大簡化了編譯程式的移植跟相容性問題,只要三個步驟就可以把軟體裝到你的Linux上,*nix系統特點就是家族衍生繁雜,因此也凸顯出Autotools之於GNU / Linux 的重要性。

前情提要說完了,再來一點心得感想,其實一直覺得編譯套件三部曲"./configure ; make ; make install"很神奇,想知道後面的動作,如何能精確的檢查編譯需要的函式庫跟相依性,再進一步就是如何把自己的軟體改成一樣的形式,讓它們可以在各系統暢行無阻,這次因為buildroot強烈要求外掛軟體要遵循Autotools的規範,就開始這次的研究。

廢話交代完畢,進入實做細節,首先是整個Autotools的流程圖:(取自http://en.wikipedia.org/wiki/GNU_build_system)

圖中的橢圓形指的是處理的程式,長方形就是相關的資料檔。

Step by Step教學可以在這裡找到;
http://markuskimius.wikidot.com/programming:tut:autotools/

按著步驟一步一步大概就知道要怎麼進行了,基本上要準備的就是configure.ac跟Makefile.am,前者可以由autoscan產生,後者就要自己寫了,但是configure.ac不是拿到就可以用的,autoscan產生的檔名是configure.scan,要自己手動更名為configure.ac,再來要小小修改一下內容,才能繼續後面的步驟,必須要加入的兩行是:

AM_INIT_AUTOMAKE(httpfs2, 1.0)
AM_PROG_CC_C_O


另外,一個完整的GNU套件需要有一些相關的文件,就是我們拿到套件會包含在內的NEWS、README、AUTHORS、ChangeLog等,上述四個檔案需要自己準備,可以用touch創造空檔案騙過檢查即可,其他的可以透過"automake --add-missing"自動補齊

再來談到Makefile.am,這是產生最終Makefile的設定檔,可以用空檔案替代,不過當然也生不出什麼東西,基本的內容如下:

bin_PROGRAMS=httpfs2
httpfs2_SOURCES=httpfs2.c

要告訴Autotools最終產出的目標名稱,跟相對的來源檔

廢話很多,總結整個導入Autotools的過程可以條列如下:
1 執行 autoscan ,產生configure.scan
2 把 configure.scan 更名為 configure.ac
3 修改 configure.ac 的內容
4 按照專案組成編寫 Makefile.am
5 產生必備的NEWS、README、AUTHORS、ChangeLog等
6 執行 aclocal 生成 aclocal.m4,這個檔案包含所有過程需要的Macro
7 執行 autoheader 生成 config.h.in
8 執行 automake 生成 Makefile.in,它是最終Makefile的範本
9 執行 autoconf 生成 configure 可執行檔,這是用來檢查並產生Makefile的最重要script
10 發生錯誤時,修改相關檔案,然後執行 autoreconf 就會自動執行 6~9的步驟


再來談share library,程式或許會引入外部共用函式庫,要怎麼告訴Autotools去納入我們所需的函式庫呢?很簡單,只要在configure.ac內加入
PKG_CHECK_MODULES(FUSE, fuse)
其中的大寫FUSE是自己取的變數名字,fuse是函式庫的名字(得到函式庫名字的方法:pkg-config --list-all
),也可以視需要加入版本檢查如下:
PKG_CHECK_MODULES(XML, libxml-2.0 >= 2.4)
一樣XML是自訂變數名稱,這樣Autotools就會自己執行pkg-config去取得相關的CFLAGS跟LIBS參數,作用跟以下兩行一樣:
pkg-config fuse --cflags
pkg-config fuse --libs
只不過PKG_CHECK_MODULES這個巨集會自動產生FUSE_CFLAGS跟FUSE_LIBS這兩個對應的變數,是不是方便多了?!

有了*_CFLAGS跟*_LIBS之後,還需要做個小動作,讓他們能在Makefile發揮作用,這時候要修改的檔案就是前面提到的Makefile.am,例如加入以下兩行:
httpfs2_CPPFLAGS=$(FUSE_CFLAGS)
httpfs2_LDFLAGS=$(FUSE_LIBS)

這樣就完成了,快樂的使用....編譯套件三部曲"./configure ; make ; make install"吧!

那本篇的蠢事跟笨點在哪邊呢?
剛說過要使用PKG_CHECK_MODULES這個巨集,我照教學文章把它加進去,但是始終沒有在Makefile中發揮效果,查了config.log跟config.status發現Autotools有照我的要求去獲得*_CFLAGS跟*_LIBS,但在Makefile中都找不到對應的定義
~~~~~經過好幾天的鬼打牆之後~~~~~
發現Autotools是shell script巨集形式的工具,也就是它只是按照我們在configure.ac指定的順序展開巨集罷了,所以如果把PKG_CHECK_MODULES放在AC_OUTPUT之後,Makefile都生米煮成熟飯了才去執行pkg-config的動作,當然沒有用,順序換過來就沒問題了,耍笨完畢....

延伸閱讀:
Step by Step教學;
http://markuskimius.wikidot.com/programming:tut:autotools/
Using Autotools with pkgconfig:
http://library.gnome.org/users/anjuta-build-tutorial/2.26/library-autotools.html.en
Automake跟makefile的綜合介紹http://netlab.cse.yzu.edu.tw/~armor/columns/automake/automake.htm

留言

coolcoolcat寫道…
感謝你的資料整理,這一篇文章對我幫助很大:)

這個網誌中的熱門文章

RTC & CMOS 技術詳解

[自由網路] 如何取得 Google Drive (真實)外連位址 (Direct Link)

教你三招突破網管封鎖