Automake簡介
本系列文章均翻譯自Automake官方文件:Automake Manual,github同步專案:question
目錄
Automake介紹
Automake是從Makefile.am(定義一系列make變數的檔案)自動生成Makefile.in檔案的工具。生成的Makefile.in符合GNU Makefile 標準。
因為不同的平臺需要修改Makefile,所以編寫configure
指令碼自動修改Makefile,再執行./configure && make && make install
命令安裝包,形成了GNU構建系統。
Autotools介紹
Autotools
是為包建立GNU構建系統的工具;Autoconf
主要關注configure
;Automake
主要關注Makefile
。
當安裝一個程式時,安裝步驟有以下幾步:
- tar -zxf xxx.tar.gz
- cd xxx
- ./configure #檢查要求的環境,生成包括Makefile(s)在內的多個檔案
- make #構建所有的檔案結構,生成檔案
- make check #原始碼檢查
- su #切換到root使用者
- make install #複製原始碼檔案到目的目錄
- make installcheck #安裝後檢查
note:
- make uninstall 需要在構建樹下執行
- make clean 刪除make生成的檔案
- make distclean 額外刪除 ./configure生成的檔案
- make dist 從原始碼重新建立xxx.tar.gz
有一些可配置變數,可以通過./configure --help
檢視完整版
如果想配置系統預設變數,可以修改/usr/local/share/config.site
檔案中指定
2.2.3 標準目錄變數
Directory variable Default value
prefix /usr/local
exec_prefix ${prefix}
bindir ${exec_prefix}/bin
libdir ${exec_prefix}/lib
…
includedir ${prefix}/include
datarootdir ${prefix}/share
datadir ${datarootdir}
mandir ${datarootdir}/man
infodir ${datarootdir}/info
docdir ${datarootdir}/doc/${PACKAGE}
通過./configure --help
檢視完整版。
可以在執行時改變這些目錄:./configure --prefix ~/usr
。
2.2.6 並行構建樹(VPATH 構建)
對比原始碼樹與構建樹
原始碼樹:包含了configure檔案的所有原始檔
構建樹:在原始碼樹的基礎上,包含上執行configure之後派生出來的檔案。通常目錄結構與原始碼樹一致,子目錄是被構建系統自動創建出來的
虛擬路徑構建
可以在解壓完壓縮包之後在任意位置新建一個build子資料夾並在該資料夾下執行後續步驟,所有的派生檔案會存放在build目錄下,這樣的構建叫做parallel build
或者VPATH builds
。
虛擬路徑構建可以建立多個子資料夾進行構建,這樣就可以使用不同的引數構建同一份原始碼。
一些特性
2.2.8 交叉編譯
在指定的構建平臺上編譯可以在執行平臺上執行的二進位制檔案
./configure --build指定構建平臺,–host指定執行平臺
notes:如果需要構建的包本身就是一個交叉編譯器,需要使用–target引數指定架構
2.2.9 重新命名程式
可以在執行configure的時候對安裝的程式重新命名,比如安裝tar
變為gtar
以下三個引數可以滿足該需求:
- –program-prefix #給程式名字新增字首
- –program-suffix #給程式名字新增字尾
- –program-transform-name #重新命名程式
eg.
./configure --program-prefix tea
2.2.10 指定目的資料夾構建二進位制檔案
make DESTDIR=$HOME/inst install
此舉會將程式安裝在~/inst
資料夾下,資料夾下包含了程式的安裝結構
安裝的目錄結構如下所示:
打包:
cd ~/inst
find . -type f -print > ../files.lst
tar zcvf ~/amhello-1.0-i686.tar.gz `cat ../files.lst`
如此一來,直接解壓這個壓縮包,就可以直接完成amhello的安裝。
2.2.11 準備釋出
使用make distcheck
來保證包擁有所需要的構建步驟並且不會報錯
- 嘗試完整的打包、解包、執行make、make check、make install、make installcheck、make dist
- 測試只讀原始碼樹的
VPATH Builds
- 保證make clean、make distclean、make uninstall不會遺漏任何檔案
- 檢查
DESTDIR
安裝工作
生成構建系統
autoreconfig
是一個按照正確執行autoconf、automake和一堆其它命令的指令碼,用於生成構建系統。
編寫configure.ac、Makefile.am、main.c、README檔案,執行
autoreconfig --install
例項化一個構建系統
autoconf負責從configure.ac生成configure檔案
automake負責從Makefile.am和configure.ac生成Makefile.in檔案
note:只有構建系統沒有時才執行autoreconfig
,如果修改了configure.ac
或者Makefile.am
,執行make時會自動重新生成相關檔案。configure.ac
的語法參考Autoconf手冊。
2.4 小程式檔案解讀
在/usr/share/doc/automake-1.13.4
目錄下,會有一個amhello的軟體包,以它作為例子講解:
amhello-1.0
├── aclocal.m4
├── config.h.in
├── configure
├── configure.ac
├── depcomp
├── install-sh
├── Makefile.am
├── Makefile.in
├── missing
├── README
└── src
├── main.c
├── Makefile.am
└── Makefile.in
configure.ac
AC_INIT([amhello], [1.0], [[email protected]])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_PROG_CC
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AC_
開頭的是autocofig的巨集;AM_
開頭的是automake的巨集。- AC_INIT 定義了包名、版本、聯絡地址
- AM_INIT_AUTOMAKE 括號中的是automake的選項。-Wall -Werror 意味著關閉警告並作為錯誤進行報告;foreign 不要遵守GNU的規則,GNU包總是還應該有其他的檔案
- AC_PROG_CC 使configure指令碼搜尋C編譯器然後用其名字定義變數CC,src/Makefile.in檔案需要使用CC變數來構建hello
- AC_CONFIG_HEADERS 使configure指令碼建立config.h檔案收集在configure.ac檔案中定義的巨集
- AC_CONFIG_FILES 聲明瞭configure檔案應該從*.in模板建立的檔案列表,否則不會使用Makefile.am檔案
- AC_OUTPUT 是一個關閉命令,是真正的負責生成檔案(在AC_CONFIG_HEADERS和AC_CONFIG_FILES中註冊的)的指令碼部分
src/Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = main.c
與Makefile的語法一樣。automake驅動該檔案時會將整個內容複製到Makefile.in
檔案,但是會通過構建規則和其他變數對特定的變數定義做出反應。通常該檔案只包含上述的變數定義列表,但也可以包含其他的變數和規則,只是automake僅僅傳遞他們,不對其進行處理。
- bin表明了安裝位置
- 以
_PROGRAMS
結尾的特殊變數指定了Makefile應該構建的檔案型別。Automake將這些變數稱之為primary
,其他的primary例如 _SCRIPTS, _DATA, _LIBRARIES 等等,對應不同的檔案型別。 - bin 意味著程式應該被安裝到
${exec_prefix}/bin
資料夾下 - hello_SOURCES 該宣告的副作用是當執行
make dist
時main.c會成為tar包的一部分 - 因為程式需要從原始檔構建,所以每個程式在一個
_PROGRAMS
變數中列出了prog
,automake會尋找另一個名為prog_SOURCES
的變數列出其所有的原始檔。所有的原始檔會被一起編譯和連結。
Makefil.am
SUBDIRS = src
dist_doc_DATA = README
- SUBDIRS 列出所有的在驅動當前目錄之前make需要遞迴進入的資料夾,make install也會先安裝src/hello,再安裝README
- dist_doc_DATA
_DATA primary
列出的檔案列表不會自動地成為tar包的一部分,所以加上了dist字首來達到這個目的。唯一重要的影響是此行在make install
的時候會安裝README。
note:檔案中沒有涉及到安裝路徑,請參考autocong手冊中的Defining Directories。
3. 基本理念
3.1 一般操作
Automake讀取Makefile.am生成Makefile.in檔案。某些在Makefile.am中定義的變數和規則指導Automake生成更加專用的程式碼。
大部分GNU make擴充套件不能被Automake所識別。
定義在Makefile.am或者configure.ac中的變數會覆蓋automake的預設變數。
automake在檢查變數定義的時候會遞迴檢查所有引用的變數
註釋以##
開頭
3.2 嚴格程度
雖然Automake旨在供GNU包維護中使用,但是並不想遵守其全部的規定。
有以下三個等級:
- foreign - 只檢查正確操作所必須的東西。
- gnu - 會盡可能多的滿足GNU標準。預設選項
- gnits - 會檢查還未成文的GNU標準,比GNU標準更細。通常不會使用該選項
3.3 命名格式
Automake變數遵守uniform naming scheme
,使何時程式被構建和如何被安裝變得很容易。
一套不同的名字用來決定構建物件應該被安裝到哪裡。這些名字是primary的字首,定義了哪個標準資料夾是安裝目錄。標準的資料夾名字參考 Directory Variables in The GNU Coding Standards
每個primary都有一個額外的以EXTRA_
作為字首的變數名。它用於列出可能會或不會被構建的物件,取決於configure。
可以自定義目錄,任何在Makefile.am中以dir
結尾的自定義變數都可以用作primary的合法字首:
xmldir = $(datadir)/xml
xml_DATA = file.xml
不是在每個資料夾的每個物件的每個部分都會被安裝。Automake會標記這些錯誤。還會檢查目錄名的拼寫錯誤。
noinst_
字首表示變數只構建不安裝。
check_
表明變數不能被構建直到make check
命令執行。也不可安裝。
所有的變數名期望 字母、數字、@、其它符號變為下劃線,比如libmum++.a,派生變數會是libmum___a_SOURCES
超級字首:
- dist #指明哪些檔案應該被髮布
- nodist
- nobase #禁止去掉路徑字首的規則,舉例:
nobase_dist_include_HEADERS = \
jupiter/jupiter_interface.h
正常情況下,該標頭檔案會被安裝到/usr(/local)/include/jupiter_interface.h
,加了nobase
字首之後,會變為/usr(/local)/include/jupiter/jupiter_interface.h
。
nobase_
可以使用下面的寫法代替:
nobase_dist_pkgdata_HEADERS = jupiter/jupiter.ogg
jupiterdir = $(pkgdatadir)/jupiter
dist_jupiter_DATA = jupiter/jupiter.ogg
EXTRA_DIST變數應該被加到釋出包的檔案或資料夾。
3.4 命令長度限制
例如
data_DATA = file1 … fileN fileN+1 … file2N
可以寫成
data_DATA = file1 … fileN
data2dir = $(datadir)
data2_DATA = fileN+1 … file2N
3.6 使用者保留變數
一些保留變數為構建包的使用者使用,讓他們的工作更輕鬆。但是這些變數不能出現在要求正確編譯的包中。
Automake引入了特殊的陰影便量為使用者標記變數。新增字首AM_
到使用者變數名就是陰影變數。
4. 一些示例包
- 使用不同的編譯引數從一個檔案構建兩個專案。通過設定不同的變數名及其標誌指向同一個檔案倆達到效果
bin_PROGRAMS = true false
false_SOURCES =
false_LDADD = false.o
true.o: true.c
$(COMPILE) -DEXIT_CODE=0 -c true.c
false.o: true.c
$(COMPILE) -DEXIT_CODE=1 -o false.o -c true.c
true_SOURCES沒有寫,Automake會預設有一個true.c檔案和預設的規則來編譯true.o、連結true。see Default _SOURCES
bin_PROGRAMS = false true
false_SOURCES = true.c
false_CPPFLAGS = -DEXIT_CODE=1
true_SOURCES = true.c
true_CPPFLAGS = -DEXIT_CODE=0
該種寫法會生成 false-true.o and true-true.o