1. 程式人生 > >Automake簡介

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主要關注configureAutomake主要關注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.acMakefile.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