歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> 使用GNU Autoconf/Automake創建Makefile

使用GNU Autoconf/Automake創建Makefile

日期:2017/2/28 15:59:07   编辑:Linux教程

原文:

How To Create a GNU Autoconf / Automake Based Configure Script for Your Application

http://www3.fh-swf.de/fbin/roth/download/prg3.howto_autoconfmake.pdf

by Prof.Dr. Walter Roth

University of Applied Science Suedwestfalen, Germany

================================================

1. 本文檔的基本信息

2. 為什麼使用GNU AutoXXX Tools?

3. 它是如何工作的?

4. 你需要什麼?

5. 一步一步為“Hello World”創建配置腳本

6. 比較復雜的應用

7. 參考文獻

==============================================================

1. 本文檔的基本信息

1.1. 印刷

有些字體比較難認,所以用下面這個表給出一些字符的圖像,這對命令很重要。本文檔用Times New Roman的12號字體寫普通文本,用Courier的11號字體寫命令行和源代碼。注意:雙線可能會畫成一個比較長的單線


1.2. 名詞定義

應用(Application)是指你開發的程序。

目標系統(target system)是用於安裝你的程序的計算機。

開發系統(development system)是指開發程序所用計算機


2. 為什麼使用GNU AutoXXX Tools?

使用Autoconf和Automake是唯一的(合理的)為你的應用創建Makefile的方法,只要你的應用工作在任何有GNU工具的系統上。GNU工具可用於所有的Unix、Windows(Cywin)和MacOS系統


3. 它是如何工作的?

GNU Autoconf由多個程序組成,最終由它們為你的應用創建Makefile。它會為源碼的每個子目錄創建一個Makefile。由於Makefile是針對特定的用戶機器的(目標系統),也就是你的程序運行的系統,所以必須在用戶機器上創建。目標系統的所有信息對於這個機器都是可用的。Makefile是由冗長的腳步程序“configure”創建的,這個腳本必須隨你的源代碼一起提供。在目標系統上,configure是根據它運行的一些測試結果來創建Makefile的,這些結果已經事先寫在了Makefile.am文件。Makefile支持很多不同的目標,第一個就是“all”。make all會為你的程序創建二進制文件。install目標會安裝這些二進制文件,uninstall用於卸載。這樣的話,用戶就可以很方便的使用你的程序,只需應用的頂層目錄上,運行如下三條命令即可:

[python]
  1. ./configure
  2. make
  3. make install

第二條命令就相當於make all,因為all是第一個目標。當然,目標系統必須有可用make工具和一個編譯器。但是,這要用configure檢查,如果configure沒有找到所有它需要的程序,它會停止並返回錯誤信息。

可是,必須在你的系統上創建configure腳本,這是個非常復雜的任務。


4. 你需要什麼?

首先,需要你的源碼。確保處在頂層目錄,並且包含了所有的文件,編譯時不會報錯。

你可能要添加一些新文件,為你的應用提供一些必要的文檔。下面這些文件是必須存在於頂層目錄的:

文件名

內容

INSTALL

安裝描述。你可以從其他基於automake的應用中拷貝一個標准的INSTALL文件,然後添加一些針對你的應用的信息。

README

用戶應該知道的一些關於本應用的信息。最好在文件的開始處簡單描述一些這個應用的目的

AUTHORS

作者列表。

NEWS

關於本應用的最新的新聞

ChangLog

本應用的修訂歷史

這些文件可以不包含任何內容,因此,第一次運行時,你可以只創建一些空文件。但是,這些文檔對用戶是很重要的。你應該花點時間好好的寫了它們。README文件是最重要的一個。讓它盡可能的保護一些有用的信息。

然後,當然是需要GNU工具。幸運的是,現在所有的Linux發行版都包含了GNU工具。你可以驗證一些它們是否已經安裝。要檢查的話,只需鍵入:

[python]
  1. which automake

它會產生類似下面的結果:

[python]
  1. /usr/bin/automake
如果返回的是空行,很可能沒有安裝GNU工具。


5. 一步一步為“Hello World”創建配置腳本

5.1. 簡評

下面內容中的命令都用Courier字體。所有的命令都可以在普通用戶中使用,無需變成root。例子中使用的應用叫做myapplication,版本是1.0。該應用只有一個文件夾“myapplication”,單一源文件main.c。你要自己編輯源代碼、文檔、configure.ac和makefile.am文件。其他的都可以自動生成。

5.2. 准備源碼

進入應用的頂層目錄。

[python]
  1. cd myapplication

建立前面提到的那些空文檔文件,稍後再填寫它們。

[python]
  1. touch INSTALL README AUTHORS NEWS ChangeLog

5.3. 新建makefile.am

5.3.1. 構建應用

makefile.am包含了關於應用的信息,配置腳本需要這些信息來創建最終的Makefile。必須建立一個makefile.am,它的內容包括目標、源代碼和應用的子目錄。下面是myapplication的makefile.am,沒有子目錄:

[python]
  1. ##Process this file with automake to create Makefile.in
  2. bin_PROGRAMS = myapplication
  3. myapplication_SOURCES=main.c

第一行是默認的內容,每個makefile.am都可以使用。第二行列出了要建立和安裝到目標系統的二進制程序文件。本例中只有一個myapplication,它將被安裝到SUSE9.0系統的/usr/bin目錄下,這是一個默認目錄。如果你要構建多於一個的程序,或要安裝到其他目錄,請查看第7章的Automake文檔。

第三行列出了該應用的所有源文件。第一個詞是由應用名稱和_SOURCES組成的。

5.3.2. 安裝文件

makefile.am不僅僅管理應用的構建過程,還定義了要安裝到目標系統的文件的目標路徑。automake已經提前定義了標准的安裝目錄,其中最重要的幾個目錄是:

prefix 安裝目錄樹的頂層,標准是/usr/local(KDE是/opt/kde)

binary 二進制程序的目錄

libexecdir 程序的庫的目錄

還有更多的提前定義的目錄,請閱讀“The GNU Coding Startding”的目錄變量(5)。安裝到這些目錄的文件會像下面這樣被列出了:

[python]
  1. bin_PROGRAMS=myapplication
myapplication文件將被放到一個bin目錄下。

如果你需要將某些文件安裝到非標准目錄下,就要自己定義。名字必須以dir作為後綴。例如:

[python]
  1. htmldir=$(prefix)/html

html目錄就會處於prefix之下。在makefile.am定義要安裝的文件,如下:

[python]
  1. html_DATA=usermanual.html

除了標准目錄,automake還為個別包定義了目錄:pkglibdir、pkgincludedir和pkgdatadir,可以用它們將你的文件安裝到標准的bin、lib或data目錄下的獨立子目錄。這些安裝目錄會用包的名字命名。

並不是所有文件都要被最終安裝。例如,圖標(或圖標),它們被編譯到可執行文件後就不再需要了。但它們並不是真正的源文件。由於它們必須包含在最終的發布中,所有要把它們作為EXTRA_dist文件列出了。

5.4. 新建configure.ac

注意:在比較早的automake和autoconf版本中,configure.ac被叫做configure.in。autoscan工具會掃描你的源代碼,然後創建一個默認的configure.ac初始文件。因此,你可以在源代碼的頂層目錄執行autoscan,生成一個configure.scan文件作為configure.ac的模板。

[python]
  1. autoscan
autoscan的執行結果大概是這樣:

[python]
  1. # -*- Autoconf -*-
  2. # Process this file with autoconf to produce a configure script.
  3. AC_PREREQ(2.59)
  4. AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
  5. AC_CONFIG_SRCDIR([config.h.in])
  6. AC_CONFIG_HEADER([config.h])
  7. # Checks for programs.
  8. AC_PROG_CXX
  9. AC_PROG_CC
  10. AC_PROG_CPP
  11. AC_PROG_INSTALL
  12. AC_PROG_LN_S
  13. AC_PROG_MAKE_SET
  14. AC_PROG_RANLIB
  15. # Checks for libraries.
  16. # Checks for header files.
  17. # Checks for typedefs, structures, and compiler characteristics.
  18. AC_HEADER_STDBOOL
  19. AC_C_CONST
  20. # Checks for library functions.
  21. AC_CONFIG_FILES([Makefile
  22. src/Makefile])
  23. AC_OUTPUT

編輯configure.scan文件,修改下面這幾行:

[python]
  1. AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)

用你的應用的名字替換FULL-PACKAGE-NAME,VERSION就是它的版本號。BUG-REPORT-ADDRESS應該設一個Email地址,以便報告Bug。例如:

[python]
  1. AC_INIT(myapplication,1.0)

接下來添加一行,來調用automake。

[python]
  1. AM_INIT_AUTOMAKE(@PACKAGE_NAME@, @PACKAGE_VERSION@)

這一行使用PACKAGE_NAME和PACKAGE_VERSION變量,它們都是AC_INIT中定義過的,最終會傳遞給automake。@表示它包含字符串的是一個變量標識符。沒有用@的字符串直接按字面傳遞,結果包含在PACKAGE_NAME_PACKAGE_VERSION。

AC_CONFIG_SRCDIR用於檢測源代碼目錄下的config.h文件。AC_CONFIG_HEADER表示你想要使用一個配置頭文件。

下面的宏用於檢測構建應用所需的各種程序,把你需要用在目標系統上的程序都添加到這裡。

在typedefs這一組,你可以檢測目標機器上的系統的特殊屬性。AC_HEADER_STDBOOL是autoscan為本例添加的,用於檢測stdbool.h的可用性和C99的bool類型是否存在。AC_C_CONST用於檢測例程所需的常量機制。

最後,你可以在AC_CONFIG_FILES中指定所有你想要配置生成的makefile文件,這些文件將由AC_OUTPUT輸出,通常將它卸載文件的最後一行。

5.5. 新建config.h.in

運行autoheader可以根據configure.ac文件創建一個config.h.in。如果你想要指定config.h中包含#define,必須在configure.ac中定義。查看autoconf文檔中的AC_CONFIG_HEADER。

[python]
  1. autoheader

這樣就會建立config.h文件,文件的內容是用預處理描述應用程序的代碼。下面這段文本是例程的config.h.in文件的一部分。

[python]
  1. /* config.h.in. Generated from configure.in by autoheader. */
  2. * Define to 1 if stdbool.h conforms to C99. */
  3. #undef HAVE_STDBOOL_H
  4. /* Define to 1 if the system has the type `_Bool'. */
  5. #undef HAVE__BOOL
  6. /* Name of package */
  7. #undef PACKAGE
  8. /* Define to the address where bug reports for this package should be
  9. sent. */
  10. #undef PACKAGE_BUGREPORT
  11. /* Define to the full name of this package. */
  12. #undef PACKAGE_NAME
  13. /* Define to the full name and version of this package. */
  14. #undef PACKAGE_STRING
  15. /* Define to the one symbol short name of this package. */
  16. #undef PACKAGE_TARNAME
  17. /* Define to the version of this package. */
  18. #undef PACKAGE_VERSION
  19. /* Define to 1 if you have the ANSI C header files. */
  20. #undef STDC_HEADERS
  21. /* Version number of package */
  22. #undef VERSION
  23. /* Define to empty if `const' does not conform to ANSI C. */
  24. #undef const

5.6. 新建aclocal.m4

很幸運有一個程序可以完成這個工作。只需執行:

[python]
  1. aclocal
這樣就創建了aclocal.m4文件。文件中包含了autoconf的宏,它們可以用在你的機器上。文件包含了宏的完整源代碼,所以很長。如果沒有在你的機器上找到所有的宏,可以嘗試從autoconf的宏檔案(www.gnu.org/software/ac-archive)中找一找。這裡有很多宏,可以解決你遇到的大部分問題。另外,還有BNV_HVE_QT用於檢測Qt庫,MDL_HAVE_OPENGL用於檢測OpenGL。

如果沒有找到你所需的宏,就不得不自己去寫了。“Goat book”(1)會告訴你怎麼做。

5.7. 新建configure

現在,autoconf就可以用autoconfig.ac和aclocal.m4創建一個配置腳本了。只需運行:

[python]
  1. autoconf

這樣會產生一個配置腳本,對於一個GUI應用,可能超過2000行。

5.8. 新建makefile.in

makefile.in包含很多從makefile.am自動添加的信息。makefile.in是配置腳本最終創建Makefile所必須的。很幸運的是,automake程序可以為你完成這個工作。可是,一些應用程序發布包所必須的文件還沒有添加到應用的頂層目錄。如果你運行下面的命令,automake將從GNU工具中拷貝這些文件,然後創建makefile.in:

[python]
  1. automake -a

[python]
  1. automake --add-missing

5.9. 測試包

現在,配置腳本已經准備好了,可以在任何GNU支持系統上創建Makefile。configure接受很多命令行參數。運行./configure可以得到一個概述。最重要的參數可能是--enable-FEATURE,這裡的FEATURE有很多選擇。對於程序開發而言,經常要用到--enabl-debug=full來選擇調試。對於用戶,--prefix和--with-LIBRARY-dir可以控制很多安裝路徑。先試一下不用任何參數運行configure。會在源碼的頂層目錄產生一個Makefile,prefix設為/usr/local。只需鍵入:

[python]
  1. ./configure
你將看到很多check...信息,最後結束時會出現在類似下面的信息:

[python]
  1. configure: creating ./config.status
  2. config.status: creating makefile
  3. config.status: creating config.h
  4. config.status: config.h is unchanged
  5. config.status: executing depfiles commands

然後,測試一下新的makefile:

[python]
  1. make

應該會沒有任何錯誤的編譯應用。注意,不要用root用戶運行make install,否則會將程序安裝到默認的prefix下,那很可能是一個錯誤的地址。運行如下命令就能將應用安裝到默認的prefix:

[python]
  1. make install
只要你不是root,將看到很多錯誤信息,這是因為沒有寫的權限。用普通用戶運行make install的話,對於尋找安裝的文件會很有用。

你的Makefile支持所有的標准的目標,例如clean、dist、uninstall等等。

要得到一個程序的開發版本,需要重新運行configure,生成一個支持調試的makefile。

[python]
  1. ./configure --enable-debug=full

然後運行:

[python]
  1. make

這樣,編譯的程序就包含了調試信息。因此,可執行文件也會比之前編譯的大很多。現在你就可以在調試器中運行你的程序了。


6. 比較復雜的應用

6.1. 帶有子目錄的應用

你需要在頂層目錄(myapplication)和每個子目錄(src、doc、img)都有一個makefile.am。像myapplication/CVS這樣的子目錄不算發布包的一部分,必須跳過。相應目錄的直接子目錄必須像下面這樣在makefile.am中列出了:

[python]
  1. SUBDIRS = subdir1 subdir2 subdir3

不需要在SUBDIRS中指定子目錄下的目錄。每個子目錄下的makefile.am只需指定本目錄下的直接子目錄。

例如,頂層目錄是myapplication,CVS子目錄用於管理CVS,src是源碼,doc是文檔,img是圖片,myapplication目錄下的頂級makefile.am就應該是這樣:

[python]
  1. ##Process this file with automake to create Makefile.in
  2. SUBDIRS = src doc img

提供一個好主意,為大多數autoXXX工具創建和使用的文件使用用一個叫做admin的單獨目錄。這會使頂層目錄更具可讀性。你要做的就是在AC_INIT後面直接添加:

[python]
  1. AC_CONFIG_AUX_DIR(admin)
然後在手動創建一個admin目錄,它就可以被automake使用了。

[python]
  1. mkdir admin

源文件通常被列在myapplication_SOURCES列表。但是,這次的源文件在src目錄下,所以要把它們列在myapplication/src/makefile.am文件中。二進制文件列表bin_PROGRAMS也在這個文件中指定。如下:

[python]
  1. ##Process this file with automake to create Makefile.in
  2. bin_PROGRAMS = myapplication
  3. myapplication_SOURCES = main.c

對於其他的非源代碼文件,如果想將它們包含在發布包中,就必須作為EXTRA_DIST文件列出。如果doc目錄中包含一個index.html文件,你必須將它添加到myapplication/doc/makefile.am文件的EXTRA_DIST列表中:

[python]
  1. ##Process this file with automake to create Makefile.in
  2. EXTRA_DIST = index.html page1.html

下面是myapplication/img目錄下的makefile.am文件:

[python]
  1. ##Process this file with automake to create Makefile.in
  2. EXTRA_DIST = image1.png image2.bmp

運行autoscan,並按照3.3節描述的那樣編輯configure.scan文件。在文件末尾的AC_CONFIG_FILES宏中為每個要包含在發布包的子目錄列一個makefile文件。在頂層目錄(myapplication)下運行:

[python]
  1. aclocal
  2. autoconf
  3. autoheader
  4. automake -a

那麼,automake將為每個makefile.in創建一個makefile.am。

6.2. 庫的應用

6.2.1. 靜態庫

靜態庫的構建很���應用,可是,目標要用_LIBRARIES變量指定。mylib庫可以用下面的這些方式指定:

如果它要被安裝在全局庫目錄下(默認:/usr/lib):

[python]
  1. lib_LIBRARIES = mylib.a

如果它要被安裝在應用的lib目錄下(默認:/usr/myapplication/lib):

[python]
  1. pkglib_LIBRARIES = mylib.a

如果它只是在構建的過程中使用,不需要安裝:

[python]
  1. noinst_LIBRARIES = mylib.a

6.2.2. 共享庫

構建共享庫是一個比較復雜的問題,你最好參考一下automake和libtool的文檔。這裡介紹一種簡單情況下工作方式:對於用libtool構建的庫使用_LTLIBRARIES宏。庫的名字要以lib開頭並以.la結尾(例如libmylib.la)。使用_SOURCES宏時,la前面的點(.)必須用下劃線(_)代替。對於要安裝到lib目錄下的mylib庫來說,它的宏可以這樣寫:

[python]
  1. lib_LTLIBRARIES = libmylib.la
  2. libmylib_la_SOURCES = mylib.c
在configure.ac文件中的AC_PROG_CC後面添加AC_PROG_LIBTOOL宏。這樣的話,autoconf就會為configure腳本增加libtool支持。

運行automake之前,先運行libtoolize,會添加一些automake所需的文件。


7. 參考文獻

1. Gary Vaughan, Ben Elliston, Tom Tromey, Ian Taylor: “GNU Autoconf, Automake and Libtool”, New Riders Publishing, 2000, also available online at www.gnu.org

2. GNU Automake

http://www.gnu.org/software/automake/manual/automake.html

3. GNU Autoconf

http://www.gnu.org/software/autoconf/manual/autoconf-2.57/autoconf.html

4. Libtool

5. The GNU Coding Standards

http://www.gnu.org/prep/standards/standards.html

Copyright © Linux教程網 All Rights Reserved