關(guān)于GNU Autotools的介紹
如果你仍未使用過 Autotools,那么這篇文章將改變你遞交代碼的方式。
你有沒有下載過流行的軟件項目的源代碼,要求你輸入幾乎是儀式般的 ./configure; make && make install
命令序列來構(gòu)建和安裝它?如果是這樣,你已經(jīng)使用過 GNU Autotools 了。如果你曾經(jīng)研究過這樣的項目所附帶的一些文件,你可能會對這種構(gòu)建系統(tǒng)的顯而易見的復(fù)雜性感到害怕。
好的消息是,GNU Autotools 的設(shè)置要比你想象的要簡單得多,GNU Autotools 本身可以為你生成這些上千行的配置文件。是的,你可以編寫 20 或 30 行安裝代碼,并免費獲得其他 4,000 行。
Autotools 工作方式
如果你是初次使用 Linux 的用戶,正在尋找有關(guān)如何安裝應(yīng)用程序的信息,那么你不必閱讀本文!如果你想研究如何構(gòu)建軟件,歡迎閱讀它;但如果你只是要安裝一個新應(yīng)用程序,請閱讀我在在 Linux 上安裝應(yīng)用程序的文章。
對于開發(fā)人員來說,Autotools 是一種管理和打包源代碼的快捷方式,以便用戶可以編譯和安裝軟件。 Autotools 也得到了主要打包格式(如 DEB 和 RPM)的良好支持,因此軟件存儲庫的維護者可以輕松管理使用 Autotools 構(gòu)建的項目。
Autotools 工作步驟:
- 首先,在
./configure
步驟中,Autotools 掃描宿主機系統(tǒng)(即當前正在運行的計算機)以發(fā)現(xiàn)默認設(shè)置。默認設(shè)置包括支持庫所在的位置,以及新軟件應(yīng)放在系統(tǒng)上的位置。 - 接下來,在
make
步驟中,Autotools 通常通過將人類可讀的源代碼轉(zhuǎn)換為機器語言來構(gòu)建應(yīng)用程序。 - 最后,在
make install
步驟中,Autotools 將其構(gòu)建好的文件復(fù)制到計算機上(在配置階段檢測到)的相應(yīng)位置。
這個過程看起來很簡單,和你使用 Autotools 的步驟一樣。
Autotools 的優(yōu)勢
GNU Autotools 是我們大多數(shù)人認為理所當然的重要軟件。與 GCC(GNU 編譯器集合)一起,Autotools 是支持將自由軟件構(gòu)建和安裝到正在運行的系統(tǒng)的腳手架。如果你正在運行 POSIX 系統(tǒng),可以毫不保守地說,你的計算機上的操作系統(tǒng)里大多數(shù)可運行軟件都是這些這樣構(gòu)建的。
即使是你的項目是個玩具項目不是操作系統(tǒng),你可能會認為 Autotools 對你的需求來說太過分了。但是,盡管它的名氣很大,Autotools 有許多可能對你有益的小功能,即使你的項目只是一個相對簡單的應(yīng)用程序或一系列腳本。
可移植性
首先,Autotools 考慮到了可移植性。雖然它無法使你的項目在所有 POSIX 平臺上工作(這取決于你,編碼的人),但 Autotools 可以確保你標記為要安裝的文件安裝到已知平臺上最合理的位置。而且由于 Autotools,高級用戶可以輕松地根據(jù)他們自己的系統(tǒng)情況定制和覆蓋任何非最佳設(shè)定。
使用 Autotools,你只要知道需要將文件安裝到哪個常規(guī)位置就行了。它會處理其他一切。不需要可能破壞未經(jīng)測試的操作系統(tǒng)的定制安裝腳本。
打包
Autotools 也得到了很好的支持。將一個帶有 Autotools 的項目交給一個發(fā)行版打包者,無論他們是打包成 RPM、DEB、TGZ 還是其他任何東西,都很簡單。打包工具知道 Autotools,因此可能不需要修補、魔改或調(diào)整。在許多情況下,將 Autotools 項目結(jié)合到流程中甚至可以實現(xiàn)自動化。
如何使用 Autotools
要使用 Autotools,必須先安裝它。你的發(fā)行版可能提供一個單個的軟件包來幫助開發(fā)人員構(gòu)建項目,或者它可能為每個組件提供了單獨的軟件包,因此你可能需要在你的平臺上進行一些研究以發(fā)現(xiàn)需要安裝的軟件包。
Autotools 的組件是:
automake
autoconf
automake
make
雖然你可能需要安裝項目所需的編譯器(例如 GCC),但 Autotools 可以很好地處理不需要編譯的腳本或二進制文件。實際上,Autotools 對于此類項目非常有用,因為它提供了一個 make uninstall
腳本,以便于刪除。
安裝了所有組件之后,現(xiàn)在讓我們了解一下你的項目文件的組成結(jié)構(gòu)。
Autotools 項目結(jié)構(gòu)
GNU Autotools 有非常具體的預(yù)期規(guī)范,如果你經(jīng)常下載和構(gòu)建源代碼,可能大多數(shù)都很熟悉。首先,源代碼本身應(yīng)該位于一個名為 src
的子目錄中。
你的項目不必遵循所有這些預(yù)期規(guī)范,但如果你將文件放在非標準位置(從 Autotools 的角度來看),那么你將不得不稍后在 Makefile
中對其進行調(diào)整。
此外,這些文件是必需的:
NEWS
README
AUTHORS
ChangeLog
你不必主動使用這些文件,它們可以是包含所有信息的單個匯總文檔(如 README.md
)的符號鏈接,但它們必須存在。
Autotools 配置
在你的項目根目錄下創(chuàng)建一個名為 configure.ac
的文件。autoconf
使用此文件來創(chuàng)建用戶在構(gòu)建之前運行的 configure
shell 腳本。該文件必須至少包含 AC_INIT
和 AC_OUTPUT
M4 宏。你不需要了解有關(guān) M4 語言的任何信息就可以使用這些宏;它們已經(jīng)為你編寫好了,并且所有與 Autotools 相關(guān)的內(nèi)容都在該文檔中定義好了。
在你喜歡的文本編輯器中打開該文件。AC_INIT
宏可以包括包名稱、版本、報告錯誤的電子郵件地址、項目 URL 以及可選的源 TAR 文件名稱等參數(shù)。
AC_OUTPUT 宏更簡單,不用任何參數(shù)。
AC_INIT([penguin], [2019.3.6], [[seth@example.com][8]])
AC_OUTPUT
如果你此刻運行 autoconf
,會依據(jù)你的 configure.ac
文件生成一個 configure
腳本,它是可以運行的。但是,也就是能運行而已,因為到目前為止你所做的就是定義項目的元數(shù)據(jù),并要求創(chuàng)建一個配置腳本。
你必須在 configure.ac
文件中調(diào)用的下一個宏是創(chuàng)建 Makefile 的函數(shù)。 Makefile
會告訴 make
命令做什么(通常是如何編譯和鏈接程序)。
創(chuàng)建 Makefile
的宏是 AM_INIT_AUTOMAKE
,它不接受任何參數(shù),而 AC_CONFIG_FILES
接受的參數(shù)是你要輸出的文件的名稱。
最后,你必須添加一個宏來考慮你的項目所需的編譯器。你使用的宏顯然取決于你的項目。如果你的項目是用 C++ 編寫的,那么適當?shù)暮晔?nbsp;AC_PROG_CXX
,而用 C 編寫的項目需要 AC_PROG_CC
,依此類推,詳見 Autoconf 文檔中的 Building Programs and Libraries 部分。
例如,我可能會為我的 C++ 程序添加以下內(nèi)容:
AC_INIT([penguin], [2019.3.6], [[seth@example.com][8]])
AC_OUTPUT
AM_INIT_AUTOMAKE
AC_CONFIG_FILES([Makefile])
AC_PROG_CXX
保存該文件?,F(xiàn)在讓我們將目光轉(zhuǎn)到 Makefile
。
生成 Autotools Makefile
Makefile
并不難手寫,但 Autotools 可以為你編寫一個,而它生成的那個將使用在 ./configure
步驟中檢測到的配置選項,并且它將包含比你考慮要包括或想要自己寫的還要多得多的選項。然而,Autotools 并不能檢測你的項目構(gòu)建所需的所有內(nèi)容,因此你必須在文件 Makefile.am
中添加一些細節(jié),然后在構(gòu)造 Makefile
時由 automake
使用。
Makefile.am
使用與 Makefile
相同的語法,所以如果你曾經(jīng)從頭開始編寫過 Makefile
,那么這個過程將是熟悉和簡單的。通常,Makefile.am
文件只需要幾個變量定義來指示要構(gòu)建的文件以及它們的安裝位置即可。
以 _PROGRAMS
結(jié)尾的變量標識了要構(gòu)建的代碼(這通常被認為是原語目標;這是 Makefile
存在的主要意義)。Automake 也會識別其他原語,如 _SCRIPTS
、_ DATA
、_LIBRARIES
,以及構(gòu)成軟件項目的其他常見部分。
如果你的應(yīng)用程序在構(gòu)建過程中需要實際編譯,那么你可以用 bin_PROGRAMS
變量將其標記為二進制程序,然后使用該程序名稱作為變量前綴引用構(gòu)建它所需的源代碼的任何部分(這些部分可能是將被編譯和鏈接在一起的一個或多個文件):
bin_PROGRAMS = penguin
penguin_SOURCES = penguin.cpp
bin_PROGRAMS
的目標被安裝在 bindir
中,它在編譯期間可由用戶配置。
如果你的應(yīng)用程序不需要實際編譯,那么你的項目根本不需要 bin_PROGRAMS
變量。例如,如果你的項目是用 Bash、Perl 或類似的解釋語言編寫的腳本,那么定義一個 _SCRIPTS
變量來替代:
bin_SCRIPTS = bin/penguin
Automake 期望源代碼位于名為 src
的目錄中,因此如果你的項目使用替代目錄結(jié)構(gòu)進行布局,則必須告知 Automake 接受來自外部源的代碼:
AUTOMAKE_OPTIONS = foreign subdir-objects
最后,你可以在 Makefile.am
中創(chuàng)建任何自定義的 Makefile
規(guī)則,它們將逐字復(fù)制到生成的 Makefile
中。例如,如果你知道一些源代碼中的臨時值需要在安裝前替換,則可以為該過程創(chuàng)建自定義規(guī)則:
all-am: penguin
touch bin/penguin.sh
penguin: bin/penguin.sh
@sed "s|__datadir__|@datadir@|" $< >bin/$@
一個特別有用的技巧是擴展現(xiàn)有的 clean
目標,至少在開發(fā)期間是這樣的。make clean
命令通常會刪除除了 Automake 基礎(chǔ)結(jié)構(gòu)之外的所有生成的構(gòu)建文件。它是這樣設(shè)計的,因為大多數(shù)用戶很少想要 make clean
來刪除那些便于構(gòu)建代碼的文件。
但是,在開發(fā)期間,你可能需要一種方法可靠地將項目返回到相對不受 Autotools 影響的狀態(tài)。在這種情況下,你可能想要添加:
clean-local:
@rm config.status configure config.log
@rm Makefile
@rm -r autom4te.cache/
@rm aclocal.m4
@rm compile install-sh missing Makefile.in
這里有很多靈活性,如果你還不熟悉 Makefile
,那么很難知道你的 Makefile.am
需要什么。最基本需要的是原語目標,無論是二進制程序還是腳本,以及源代碼所在位置的指示(無論是通過 _SOURCES
變量還是使用 AUTOMAKE_OPTIONS
告訴 Automake 在哪里查找源代碼)。
一旦定義了這些變量和設(shè)置,如下一節(jié)所示,你就可以嘗試生成構(gòu)建腳本,并調(diào)整缺少的任何內(nèi)容。
生成 Autotools 構(gòu)建腳本
你已經(jīng)構(gòu)建了基礎(chǔ)結(jié)構(gòu),現(xiàn)在是時候讓 Autotools 做它最擅長的事情:自動化你的項目工具。對于開發(fā)人員(你),Autotools 的接口與構(gòu)建代碼的用戶的不同。
構(gòu)建者通常使用這個眾所周知的順序:
$ ./configure
$ make
$ sudo make install
但是,要使這種咒語起作用,你作為開發(fā)人員必須引導(dǎo)構(gòu)建這些基礎(chǔ)結(jié)構(gòu)。首先,運行 autoreconf
以生成用戶在運行 make
之前調(diào)用的 configure
腳本。使用 -install
選項將輔助文件(例如符號鏈接)引入到 depcomp
(這是在編譯過程中生成依賴項的腳本),以及 compile
腳本的副本(一個編譯器的包裝器,用于說明語法,等等)。
$ autoreconf --install
configure.ac:3: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'
使用此開發(fā)構(gòu)建環(huán)境,你可以創(chuàng)建源代碼分發(fā)包:
$ make dist
dist
目標是從 Autotools “免費”獲得的規(guī)則。這是一個內(nèi)置于 Makefile
中的功能,它是通過簡單的 Makefile.am
配置生成的。該目標可以生成一個 tar.gz
存檔,其中包含了所有源代碼和所有必要的 Autotools 基礎(chǔ)設(shè)施,以便下載程序包的人員可以構(gòu)建項目。
此時,你應(yīng)該仔細查看存檔文件的內(nèi)容,以確保它包含你要發(fā)送給用戶的所有內(nèi)容。當然,你也應(yīng)該嘗試自己構(gòu)建:
$ tar --extract --file penguin-0.0.1.tar.gz
$ cd penguin-0.0.1
$ ./configure
$ make
$ DESTDIR=/tmp/penguin-test-build make install
如果你的構(gòu)建成功,你將找到由 DESTDIR
指定的已編譯應(yīng)用程序的本地副本(在此示例的情況下為 /tmp/penguin-test-build
)。
$ /tmp/example-test-build/usr/local/bin/example
hello world from GNU Autotools
去使用 Autotools
Autotools 是一個很好的腳本集合,可用于可預(yù)測的自動發(fā)布過程。如果你習(xí)慣使用 Python 或 Bash 構(gòu)建器,這個工具集對你來說可能是新的,但它為你的項目提供的結(jié)構(gòu)和適應(yīng)性可能值得學(xué)習(xí)。
而 Autotools 也不只是用于代碼。Autotools 可用于構(gòu)建 Docbook 項目,保持媒體有序(我使用 Autotools 進行音樂發(fā)布),文檔項目以及其他任何可以從可自定義安裝目標中受益的內(nèi)容。