絕世秘籍之GNU構建系統與Autotool概念分析

添加微信公眾號《Linux就該這么學》,掌握最新IT資訊動態,免費領取Linux課程以及專業的RHCE考前答疑服務。

《Linux就該這么學》在線免費閱讀地址:http://www.linuxprobe.com/

純手工打造每一篇開源資訊與技術干貨,數十萬程序員和Linuxer已經關注

導讀

經常使用Linux的開發人員或者運維人員,可能對configure->make->make install相當熟悉。事實上,這叫GNU構建系統,利用腳本和make程序在特定平臺上構建軟件。這種方式成為一種習慣,被廣泛使用。本文從用戶視角和開發者視角詳細說明,這種構建方式的細節,以及開發者如何利用autoconf和automake等工具(autotools)創建兼容GNU構建系統的項目。

為了簡化可移植構建的難度,在早期有一套autotools工具幫助程序員構建軟件。我們熟知的configure->make->make install三部曲,大多都是基于autotools來構建的。autotools是GNU程序的標準構建系統,所以其實我們經常在使用三部曲。有些程序雖然也是這三部曲,但卻不是用autotools實現的,比如nginx的源碼就是作者自己編寫的構建程序。

用戶視角

用戶通過configure->make->make install基于源碼安裝軟件。然而大部分用戶可能并不知道這個過程究竟做了些什么。

configure腳本是由軟件開發者維護并發布給用戶使用的shell腳本。這個腳本的作用是檢測系統環境,最終目的是生成Makefile和config.h。

make通過讀取Makefile文件,開始構建軟件。而make install可以將軟件安裝到需要安裝的位置。

如上圖,開發者在分發源碼包時,除了源代碼(.c .h…),還有許多用以支撐軟件構建的文件和工具,其中最重要的文件就是Makefile.in和config.h.in。configure腳本執行成功后,將為每一個*.in文件處理成對應的非*.in文件。

大部分情況只生成Makefile和config.h,因為Makefile用于make程序識別并構建軟件,而config.h中定義的宏,有助于軟件通過預編譯來改變自身的代碼,以適應目標平臺某些特殊性。有些軟件在configure階段,還可以生成其他文件,這完全取決于如軟件本身。

configure

當運行configure時,將看到類似如下的系統檢查,這些檢查的多少取決于軟件本身的需要,也就是由軟件開發者來定義和編寫的。

checking?for?a?BSD-compatible?install...?/usr/bin/install?-c
checking?whether?build?environment?is?sane...?yes
checking?for?a?thread-safe?mkdir?-p...?/bin/mkdir?-p
checking?for?gawk...?gawk
checking?whether?make?sets?$(MAKE)...?yes
checking?for?gcc...?gcc
checking?for?C?compiler?default?output?file?name...?a.out
...

一般來說,configure主要檢查當前目標平臺的程序、庫、頭文件、函數等的兼容性。這些檢查結果將作用于config.h和Makefile文件的生成。從而影響最終的編譯。

用戶也可以通過給configure配置參數來定制軟件需要包含或不需要包含的組件、安裝路徑等行為。這些參數分為5組,可以通過執行./configure --help來查看,軟件提供哪些配置參數:

  • 安裝路徑相關配置。最常見的是--prefix。

  • 程序名配置。例如--program-suffix可用于為生成的程序添加后綴。

  • 跨平臺編譯。不太常用。

  • 動態庫靜態庫選項。用于控制是否生成某種類型的庫文件。

  • 程序組件選項。用于配置程序是否將某種功能編譯到程序中,一般形如--with-xxx。這可能是最常用的配置,而且由軟件開發者來定義。


(*表示這是幾乎所有軟件都支持的配置,因為這些配置是autotool生成的configure腳本默認支持的。)

configure在執行過程中,除了生成Makefile外,還會生成的文件包括但不限于:

config.log 日志文件

config.cache 緩存,以提高下一次configure的速度,需通過-C來指定才會生成

config.status 實際調用編譯工具構建軟件的shell腳本

如果軟件通過libtool構建,還會生成libtool腳本。關于libtool腳本如何生成,請看開發者視角。

configure經常會中途出錯,這一般是由于當前平臺不具有構建該軟件所必需的依賴(庫、函數、頭文件、程序…)。此時,不要慌張,仔細查看輸出,解決這些依賴。

開發者視角

開發者除了編寫軟件本身的代碼外,還需要負責生成構建軟件所需要文件和工具。當我接觸到autotools后,我發現,雖然有工具的幫助,但這件事情依舊十分復雜。

對于C或C++程序員,在早期,構建跨平臺的應用程序是相當繁瑣的一件事情,而且對于經驗不足的程序員而言,甚至難度巨大。因為構建可移植的程序的必要前提是對各個平臺足夠了解,這往往要花上相當長的時間去積累。

Unix系統的分支復雜度很高,不同的商用版或開源版或多或少都有差異。這些差異主要體現在:系統組件、系統調用。我們主要將Unix分為如下幾個大類:IBM-AIX HP-UX Apple-DARWIN Solaris Linux FreeBSD。Unix分支大全

因此,對于開發者而言,要么自己編寫構建用的腳本,這往往需要極其扎實的shell能力和平臺熟悉度。另一個選擇就是部分依賴工具。autoconf和automake就是這樣的工具。

autoreconf

為了生成configure腳本和Makefile.in等文件,開發者需要創建并維護一個configure.ac文件(在早期,通常叫configure.in文件,雖然沒有區別,但強烈建議使用.ac,因為.in文件往往意味著被configure腳本識別為模板文件并生成直接參與最終構建的文件,configure.in在命名上有歧義),以及一系列的Makefile.am。autoreconf程序能夠自動按照合理的順序調用autoconf automake aclocal等程序。

configure.ac

configure.ac用于生成configure腳本。autoconf工具用來完成這一步。下面是一個configure.ac的例子:

AC_PREREQ([2.63])
AC_INIT([st],?[1.0],?[zhoupingtkbjb@163.com])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([src/config.h])
AM_INIT_AUTOMAKE([foreign])
#?Checks?for?programs.
AC_PROG_CC
AC_PROG_LIBTOOL
#?Checks?for?libraries.
#?Checks?for?header?files.
#?Checks?for?typedefs,?structures,?and?compiler?characteristics.
#?Checks?for?library?functions.
AC_CONFIG_FILES([Makefile
??????????????? ?src/Makefile
?????????????????src/a/Makefile
?????????????????src/b/Makefile])
AC_OUTPUT

其中以AC_開頭的類似函數調用一樣的代碼,實際是一些被稱為“宏”的調用。這里的宏與C中的宏概念類似,會被替換展開。m4是一個經典的宏工具,autoconf正是構建在m4之上,可以理解為autoconf預先實現了大量的,用于檢測系統可移植性的宏,這些宏在展開后就是大量的shell腳本。所以編寫configure.ac需要對這些宏熟練掌握,并且合理調用。有時,甚至可以自己實現自己的宏。

autoscan和configure.scan

可以通過調用autoscan命令得到一個初始化的configure.scan文件,然后重命名為configure.ac后,在此基礎上編輯configure.ac。autoscan會掃描源碼,并生成一些通用的宏調用、輸入的聲明以及輸出的聲明。盡管autoscan十分方便,但是沒人能夠在構建之前,就把代碼完全寫好,因此autoscan通常用于初始化configure.ac。

autoheader和config.h

autoheader命令掃描configure.ac中的內容,并確定需要如何生成config.h.in。每當configure.ac有所變化,都可以通過再次執行autoheader更新config.h.in。在configure.ac通過AC_CONFIG_HEADERS([config.h])告訴autoheader應當生成config.h.in的路徑。在實際的編譯階段,生成的編譯命令會加上-DHAVE_CONFIG_H定義宏,于是在代碼中,我們可以通過下面代碼安全的引用config.h。

/bin/sh?../../libtool?--tag=CC???--mode=compile?gcc?-DHAVE_CONFIG_H?...
#ifdef?HAVE_CONFIG_H
#include?<config.h>
#endif

config.h包含了大量的宏定義,其中包括軟件包的名字等信息,程序可以直接使用這些宏;更重要的是,程序可以根據其中的對目標平臺的可移植性相關的宏,通過條件編譯,動態的調整編譯行為。

automake和Makfile.am

手工編寫Makefile是一件相當煩瑣的事情,而且,如果項目復雜的話,編寫難度將越來越大。因而,automake工具應運而生。我們可以編寫像下面這樣的Makefile.am文件,并依靠automake來生成Makefile.in:

SUBDIRS?=?a?b
bin_PROGRAMS????=?st
st_SOURCES??????=?main.c
st_LDADD????????=?$(top_builddir)/src/a/liba.la?$(top_builddir)/src/b/libb.la

這里通過SUBDIRS聲明了兩個子目錄,子目錄的中的構建需要靠a/Makefile.am和b/Makefile.am來進行,這樣多目錄組織起來就方便多了。

bin_PROGRAMS聲明一個可執行文件目標,st_SOURCES指定這個目標所依賴的源代碼文件。另外,st_LDADD聲明了可執行文件在連接時,需要依賴的Libtool庫文件。

通過這個Makefile.am文件生成的Makefile.in文件相當大,不便貼出,但是可以想象,Makefile.in要比我們手工編寫的Makefile文件復雜的多。

automake的出現晚于autoconf,所以automake是作為autoconf的擴展來實現的。通過在configure.ac中聲明AM_INIT_AUTOMAKE告訴autoconf需要配置和調用automake。

aclocal

上面提到,configure.ac實際是依靠宏展開來得到configure的。因此,能否成功生成取決于,宏定義能否找到。autoconf會從自身安裝路徑下來尋找事先定義好了宏。然而對于像automake、libtool和gettext等第三方擴展宏,甚至是開發者自行編寫的宏就一無所知了。于是,存在這個工具aclocal,將在configure.ac同一目錄下生成aclocal.m4,在掃描configure.ac的過程中,將第三方擴展和開發者自己編寫的宏定義復制進去。這樣,autoconf在遇到不認識的宏時,就會從aclocal.m4中查找。

下面這張圖更為詳細的展現了整個工具鏈是如何互相配合的。

libtool

libtool試圖解決不同平臺下,庫文件的差異。libtool實際是一個shell腳本,實際工作過程中,調用了目標平臺的cc編譯器和鏈接器,以及給予合適的命令行參數。libtool可以單獨使用,這里只介紹與autotools集成使用相關的內容。

automake支持libtool構建聲明。在Makefile.am中,普通的庫文件目標寫作xxx_LIBRARIES:

noinst_LIBRARIES?=?liba.a
liba_SOURCES?=?ao1.c?ao2.c?ao3.c

而對于一個libtool目標,寫作xxx_LTLIBRARIES,并以.la作為后綴聲明庫文件。

noinst_LTLIBRARIES?=?liba.la
liba_la_SOURCES?=?ao1.c?ao2.c?ao3.c

在configure.ac中需要聲明LT_INIT:

...
AM_INIT_AUTOMAKE([foreign])
LT_INIT
...

有時,如果需要用到libtool中的某些宏,則推薦將這些宏copy到項目中。首先,通過AC_CONFIG_MACRO_DIR([m4])指定使用m4目錄存放第三方宏;然后在最外層的Makefile.am中加入ACLOCAL_AMFLAGS = -I m4。

all-in-one

上面討論了很多關于autoreconf的細節。實際上,如今我們可以直接調用autoreconf --install來自動調用上面提到的所有子命令。這里--install參數試圖將輔助的腳本和宏copy到當前項目目錄中,下面是執行時的輸出:

autoreconf:?Entering?directory?`.'
autoreconf:?configure.ac:?not?using?Gettext
autoreconf:?running:?aclocal
autoreconf:?configure.ac:?tracing
autoreconf:?running:?libtoolize?--copy
libtoolize:?putting?auxiliary?files?in?`.'.
libtoolize:?copying?file?`./ltmain.sh'
libtoolize:?Consider?adding?`AC_CONFIG_MACRO_DIR([m4])'?to?configure.ac?and
libtoolize:?rerunning?libtoolize,?to?keep?the?correct?libtool?macros?in-tree.
libtoolize:?Consider?adding?`-I?m4'?to?ACLOCAL_AMFLAGS?in?Makefile.am.
autoreconf:?running:?/usr/bin/autoconf
autoreconf:?running:?/usr/bin/autoheader
autoreconf:?running:?automake?--add-missing?--copy?--no-force
configure.ac:10:?installing?`./config.guess'
configure.ac:10:?installing?`./config.sub'
configure.ac:9:?installing?`./install-sh'
configure.ac:9:?installing?`./missing'
src/Makefile.am:?installing?`./depcomp'
autoreconf:?Leaving?directory?`.'

當我們以--install參數運行時,libtoolize --copy被調用,這將使得ltmain.sh被copy進來;接下來分別執行autoconf和autoheader;automake的參數為--add-missing --copy --no-force,這將使得幾個輔助腳本和文件被安裝到目錄下。

這些輔助文件默認安裝在configure.ac同一個目錄下,如果你希望用另一個目錄來存放他們,可以配置AC_CONFIG_AUX_DIR,例如AC_CONFIG_AUX_DIR([build-aux])將使用build-aux目錄來存放輔助文件。

如果不使用--install參數,輔助文件要么不copy,要么以軟鏈的形式創建。推薦使用--install,因為這樣,其他軟件維護可以避免由于構建工具版本不一致造成問題。

輔助文件

一個依靠GNU構建系統開發的軟件除了源碼之外,還有很多輔助的文件,有些是腳本,有些是文本文件。下面將逐一解釋這些文件:

  1. aclocal.m4:上面提到了,這個宏定義文件里面包含了第三方的宏定義,用于autoconf展開configure.ac


  2. NEWS README AUTHORS ChangeLog:這些文件是GNU軟件的標配,不過在項目中不一定需要加入。如果項目中沒有這些文件,每次autoreconf會提示缺少文件,不過這并不影響。如果不想看到這些錯誤提示,可以用AM_INIT_AUTOMAKE([foreign])來配置automake。foreign參數就是告訴automake不要這么較真:)


  3. config.guess config.sub:由automake產生,兩個用于目標平臺檢測的腳本


  4. depcomp install-sh:由automake產生,用于完成編譯和安裝的腳本


  5. missing:由automake產生


  6. ltmain.sh:有libtoolize產生,該腳本用于在configure階段配置生成可運行于目標平臺的libtool腳本


  7. ylwrap:由automake產生,如果檢測構建需要使用lex和yacc,那么會產生這個包裝腳本


  8. autogen.sh:在早期,autoreconf并不存在,軟件開發者往往需要自己編寫腳本,按照順序調用autoconf autoheader automake等工具程序。這個文件就是這樣的腳本。起這么個名字可能是習慣性的


總結

本文總概念上闡述了autotool系列工具是如何工作的。相比如今現成的IDE,GNU構建系統其實是非常難用的,學習成本比較高。

原文來自:http://os.51cto.com/art/201609/518191.htm

本文地址:http://www.linuxprobe.com/system-gnu-autotool.html編輯:馮琪,審核員:逄增寶


讓您學習到的每一節課都有所收獲

《Linux就該這么學》是由資深運維專家劉遄及全國多名紅帽架構師(RHCA)基于最新RHEL7系統共同編寫的高質量Linux技術自學教程,極其適合用于Linux技術入門教程或講課輔助教材。

? 劉遄老師QQ:5604241

? 學員助教QQ:5604674

? Linux技術交流A群(滿):560843

? Linux技術交流B群:340829

? Linux技術交流C群:463590

? 官方站點:www.linuxprobe.com

? 電腦在線閱讀效果更佳:

http://www.linuxprobe.com/chapter-00.html

按住圖片3秒,即可自動關注。

點擊左下角查看更多熱門技術

添加微信公眾號《Linux就該這么學》,掌握最新IT資訊動態,免費領取Linux課程以及專業的RHCE考前答疑服務。

《Linux就該這么學》在線免費閱讀地址:http://www.linuxprobe.com/


閱讀原文:http://linux-love.lofter.com/post/1e7041ab_ca9f0ef
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容