Autoconf和Automake生成Makefile

一、    相關概念的介紹

什麼是Makefile?怎麼書寫Makefile?竟然有工具可以自動生成Makefile?怎麼生成啊?開始的時候,我有這麼多疑問,所以,必須得先把基本的概念搞個清楚。

 

1. Makefile

  makefile用來定義整個工程的編譯規則。一個工程中的源文件計數,其按類型、功能、模塊分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因爲 makefile就像一個Shell腳本一樣,其中也可以執行操作系統的命令。

  makefile帶來的好處就是——“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。make是一個命令工具,是一個解釋makefile中指令的命令工具,一般來說,大多數的IDE都有這個命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可見,makefile都成爲了一種在工程方面的編譯方法。

 

2. Autoconf

       Autoconf是一個用於生成可以自動地配置軟件源代碼包以適應多種Unix類系統的 shell腳本的工具。由Autoconf生成的配置腳本在運行的時候與Autoconf是無關的, 就是說配置腳本的用戶並不需要擁有Autoconf。

       對於每個使用了Autoconf的軟件包,Autoconf從一個列舉了該軟件包需要的,或者可以使用的系統特徵的列表的模板文件中生成配置腳本。在shell代碼識別並響應了一個被列出的系統特徵之後,Autoconf允許多個可能使用(或者需要)該特徵的軟件包共享該特徵。 如果後來因爲某些原因需要調整shell代碼,就只要在一個地方進行修改; 所有的配置腳本都將被自動地重新生成以使用更新了的代碼。

 

3. Automake

       Automake是一個從文件`Makefile.am'自動生成`Makefile.in' 的工具。每個`Makefile.am'基本上是一系列make的宏定義 (make規則也會偶爾出現)。生成的`Makefile.in'服從GNU Makefile標準。GNU Makefile標準文檔長、複雜,而且會發生改變。Automake的目的就是解除個人GNU維護者維護Makefile的負擔 (並且讓Automake的維護者來承擔這個負擔)。典型的Automake輸入文件是一系列簡單的宏定義。處理所有這樣的文件以創建 `Makefile.in'。在一個項目(project)的每個目錄中通常包含一個 `Makefile.am'。Automake在幾個方面對一個項目做了限制;例如它假定項目使用Autoconf並且對`configure.in'的內容施加了某些限制。

       Automake支持三種目錄層次: “flat”、“shallow”和“deep”。一個flat(平)包指的是所有文件都在一個目錄中的包。爲這類包提供的`Makefile.am' 缺少宏SUBDIRS。這類包的一個例子是termutils。一個deep(深)包指的是所有的源代碼都被儲存在子目錄中的包;頂層 目錄主要包含配置信息。GNU cpio 是這類包的一個很好的例子,GNU tar也是。deep包的頂層`Makefile.am'將包括 宏SUBDIRS,但沒有其它定義需要創建的對象的宏。一個shallow(淺)包指的是主要的源代碼儲存在頂層目錄中,而 各個部分(典型的是庫)則儲存在子目錄中的包。Automake本身就是這類包(GNU make也是如此,它現在已經不使用automake)。

 

下面,就以這三種目錄層次結構給大家介紹

二、    Flat目錄結構:

1. 目錄結構:

Helloworld

|-mytest.h

|-mytest.c

|-mymain.c

  頂級目錄helloworld,該目錄下存在三個文件。mytest.h頭文件聲明瞭sayhello()方法;mytest.c中實現了sayhello()方法;mymain.c中的main調用了sayhello()方法。

2. 執行步驟:

2.1. Autoscan

   在helloworld目錄下執行autoscan命令,其中生成一個configure.scan的文件。

2.2. 將configure.scan文件更名爲configure.in文件

2.3. 打開configure.in文件,修改文件內容


 1 #                                               -*- Autoconf -*-
 2 # Process this file with autoconf to produce a configure script.
 3 
 4 #AC_INIT([2.68])
 5 AC_INIT([hello], [1.0], [**@126.com])
 6 AC_CONFIG_SRCDIR([mymain.c])
 7 #AC_CONFIG_HEADERS([config.h])
 8 
 9 AM_INIT_AUTOMAKE(hello, 1.0)
10 
11 # Check for programs
12 AC_PROG_CC
13 
14 # Check for libraries
15 # Check for header files
16 # Check for typedefs, structures, and compiler characteristics.
17 # Check for library functions.
18 
19 AC_OUTPUT(Makefile)

2.4. 然後分別執行以下兩個命令:

aclocal

autoconf

2.5. 在helloworld文件夾下創建一個名爲Makefile.am的文件,並輸入一下內容:   

1 AUTOMAKE_OPTIONS=foreign
2 bin_PROGRAMS=hello
3 hello_SOURCES=mymain.c mytest.c mytest.h

2.6. 執行命令“automake --add-missing”,automake 會根據Makefile.am 文件產生一些文件,其中包含最重要的Makefile.in

2.7. 執行“./configure”命令生成Makefile文件

2.8. 執行“make”命令來編譯hello.c程序,從而生成可執行程序hello。生成可執行程序hello後,執行“./hello”。

 

 哈哈,一定看到你想要的結果了吧。

 

三、    shallow目錄結構

1. 目錄結構

helloworld

|-mymain.c

|head

||-mytest.h

||-mytest.c

   頂級目錄helloworld,該目錄下存在一個主文件mymain.c和一個目錄head。head目錄中,mytest.h頭文件聲明瞭sayhello()方法;mytest.c中實現了sayhello()方法;mymain.c中的main調用了sayhello()方法。

2. 執行步驟:

2.1. 在頂層目錄下運行autoscan產生configure.scan文件

2.2. 將configure.scan文件更名爲configure.in文件

2.3. 打開configure.in文件,修改文件內容


 1 #                                               -*- Autoconf -*-
 2 # Process this file with autoconf to produce a configure script.
 3  
 4 #AC_INIT([2.68])
 5 AC_INIT([hello], [1.0], [**@126.com])
 6 AC_CONFIG_SRCDIR([mymain.c])
 7 #AC_CONFIG_HEADERS([config.h])
 8  
 9 AM_INIT_AUTOMAKE(hello, 1.0)
10  
11 # Check for programs
12 AC_PROG_CC
13 #使用靜態庫編譯,需要此宏定義
14 AC_PROG_RAMLIB
15 
16 # Check for libraries
17 # Check for header files
18 # Check for typedefs, structures, and compiler characteristics.
19 # Check for library functions.
20 
21 AC_OUTPUT(Makefile head/Makefile)

2.4. 然後分別執行以下兩個命令:

aclocal

autoconf

2.5. 在head文件夾下創建Makefile.am文件,內容如下:

1 AUTOMAKE_OPTIONS=foreign
2 noinst_LIBRARIES=libmytest.a
3 libmytest_a_SOURCES=mytest.h mytest.c

2.6. 在helloworld文件夾下創建Makefile.am文件,內容如下:


1 AUTOMAKE_OPTIONS=foreign
2 SUBDIRS=head
3 bin_PROGRAMS=hello
4 hello_SOURCES=mymain.c
5 hello_LDADD=head/mytest.a

2.7. 執行命令“automake –add-missing”,automake會根據Makefile.am 文件產生一些文件,其中包含最重要的Makefile.in

2.8. 執行“./configure”命令生成Makefile文件

2.9. 執行“make”命令來編譯hello.c程序,從而生成可執行程序hello。生成可執行程序hello後,執行“./hello”。

 

哈哈,shallow的目錄結構也搞定了哦~~

 

四、    Deep目錄結構

1. 目錄結構

helloworld

|head

||-mytest.h

||-mytest.c

|src

||-mymain.c

 

  頂級目錄helloworld,該目錄下存在兩個目錄src和head。Head目錄中,mytest.h頭文件聲明瞭sayhello()方法;mytest.c中實現了sayhello()方法;src目 錄中的mymain.c中的main調用了sayhello()方法。

2. 執行步驟

2.1.  在頂層目錄下運行autoscan產生configure.scan文件

2.2.  將configure.scan文件更名爲configure.in文件

2.3.  打開configure.in文件,修改文件內容


 1 #                                               -*- Autoconf -*-
 2 # Process this file with autoconf to produce a configure script.
 3  
 4 #AC_INIT([2.68])
 5 AC_INIT([hello], [1.0], [**@126.com])
 6 AC_CONFIG_SRCDIR([src/mymain.c])
 7 #AC_CONFIG_HEADERS([config.h])
 8  
 9 AM_INIT_AUTOMAKE(hello, 1.0)
10  
11 # Check for programs
12 AC_PROG_CC
13 #使用靜態庫編譯,需要此宏定義
14 AC_PROG_RAMLIB
15 
16 # Check for libraries
17 # Check for header files
18 # Check for typedefs, structures, and compiler characteristics.
19 # Check for library functions.
20 
21 AC_OUTPUT(Makefile head/Makefile src/Makefile)

2.4.  然後分別執行以下兩個命令: 

aclocal

autoconf

2.5.  在head文件夾下創建Makefile.am文件,內容如下:

1 AUTOMAKE_OPTIONS=foreign
2 noinst_LIBRARIES=libmytest.a
3 libmytest_a_SOURCES=mytest.h mytest.c

2.6.  在src文件夾下創建Makefile.am文件,內容如下:

1 AUTOMAKE_OPTIONS=foreign
2 bin_PROGRAMS=hello
3 hello_SOURCES=mymain.c
4 hello_LDADD=../head/libmytest.a

2.7.  在helloworld文件夾下創建Makefile.am文件,內容如下:

1 AUTOMAKE_OPTIONS=foreign
2 SUBDIRS=head src

2.8.  執行命令“automake –add-missing”,automake會根據Makefile.am 文件產生一些文件,其中包含最重要的Makefile.in

2.9.  執行“make”命令來編譯hello.c程序,從而生成可執行程序hello。生成可執行程序hello後,執行“./hello”。

 

 哈哈,deep目錄下的編譯與鏈接也搞定了!

 

五、    總結:

歸納一下以上所有例子的流程:

(1)在存放源代碼的頂層目錄下執行autoscan命令生成configure.scan文件。

(2)將configure.scan文件改名爲configure.in,並對其默認配置進行修改。

(3)執行aclocal、autoconf兩個命令,分別生成aclocal.m4、configure文件。

(4)在每個目錄下創建一個名爲Makefile.am的文件,並輸入相應的內容。

(5)執行automake --add-missing,它根據Makefile.am文件,生成Makefile.in。

(6)執行./configure腳本文件,它根據Makefile.in文件,生成最終的Makefile文件。

(7)生成Makefile之後,執行“make”編譯工程並且生成可執行程序。

autoconf,automake生成makefile的流程

 

六、    能力進階

以上的的程序還只是處於初級階段,並且生成的是 靜態庫 。我們可以發現,用autoconf和automake生成Makefile的關鍵在於configure.in和Makefile.am的文件的書寫。所以,要想使自己的功力更上一層,需要熟悉autoconf和automake這兩個工具的使用,其中有很多重要的宏需要我們瞭解。這裏時具體的參考手冊:

autoconf手冊

       英文版:http://www.gnu.org/software/autoconf/manual/autoconf.html

       中文版:http://www.linuxforum.net/books/autoconf.html

automake手冊

       中文版:http://www.linuxforum.net/books/automake.html

 

七、    Configure.in文件解析

autoconf是用來產生“configure”文件的工具。“configure”是一個Shell腳本,它可以自動設定一些編譯參數使程序能夠在不同平臺上進行編譯。autoconf讀取configure.in 文件然後產生’configure’這個Shell腳本。

configure.in 文件的內容是一系列GNU m4 的宏,這些宏經autoconf處理後會變成檢查系統特性的Shell腳本。configure.in文件中宏的順序並沒有特別的規定,但是每一個configure.in 文件必須以宏AC_INIT開頭,以宏AC_OUTPUT結束。一般可先用autoscan這個工具掃描原始文件以產生一個configure.scan 文件,再對configure.scan 作些修改,從而生成 configure.in 文件。

 

configure.in 文件中一些宏的含義如下

#或dnl

#或dnl後面的內容作爲註釋不會被處理,它們是註釋的起始標誌

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

 

AM_INIT_AUTOMAKE(PACKAGE,VERSION)

這個是後面運行automake命令所必需的宏,PACKAGE指明要產生軟件的名稱,VERSION 是其版本號

AC_PROG_CC

檢查系統可用的C編譯器,若源代碼是用C語言編寫的就需要這個宏

AC_OUTPUT(FILE)

設置configure命令所要產生的文件。我們最終期望產生Makefile

這個文件,因此一般將其設置爲AC_OUTPUT(Makefile)

 

在運行automake命令時,還需要一些其他的宏,這些額外的宏由aclocal產生。執行aclocal會產生aclocal.m4文件,如果沒有特別的要求,無需修改它。用 aclocal產生的宏將會提示automake如何動作。

 

另一個重要的文件是Makefile.am。automake根據configure.in中的宏並在perl的幫助下把Makefile.am轉成Makefile.in文件。Makefile.am 文件定義所要產生的目標。

 

八、    Makefile.am

 

 

 

 

  對於可執行文件和靜態庫類型,如果只想編譯,不想安裝到系統中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。

 

automake設置了默認的安裝路徑:

1) 標準安裝路徑

默認安裝路徑爲:$(prefix) = /usr/local,可以通過./configure --prefix=<new_path>的方法來覆蓋。

其它的預定義目錄還包括:bindir = $(prefix)/bin, libdir = $(prefix)/lib, datadir = $(prefix)/share, sysconfdir = $(prefix)/etc等等。

2) 定義一個新的安裝路徑

比如test, 可定義builddir = $(prefix)/build, 然後test_LIBRARIES =mytest.h mytest.c,則mytest.h mytest.c 會作爲靜態庫安裝到$(prefix)/build目錄下。

 

九、    如何使用產生的Makefile文件

執行configure腳本文件所產生的Makefile文件有幾個預定的選項可供使用:

make all:產生設定的目標,即生成所有的可執行文件。使用make也可以達到此目的。

make clean:刪除之前編譯時生成的可執行文件及目標文件(形如*.o的中間文件)。

make distclean:除了刪除可執行文件和目標文件以外,把configure所產生的 Makefile文件也清除掉。通常在發佈軟件前執行該命令。

make install:將使用make all或make命令產生的可執行文件以軟件的形式安裝到系統中。若使用bin_PROGRAMS宏,程序將會被安裝到 /usr/local/bin下,否則安裝到預定義的目錄下。

make dist:將程序和相關的文檔包裝爲一個壓縮文檔以供發佈。執行完該命令,在當前目錄下會產生一個名爲PACKAGE-VERSION.tar.gz的文件。PACKAGE 和 VERSION 這兩個參數是來自configure.in文件中的AM_INIT_AUTOMAKE(PACKAGE,

VERSION)。如在上個例子中執行make dist命令,會產生名爲“hello-1.0.tar.gz”的文件。

make distcheck:與make dist類似,但是加入了檢查包裝以後的壓縮文件是否正常。

 

十、    動態庫編譯

需要在Makefile.am中指定:

lib_LTLIBRARIES=libhello.al

libhello_al_SOURCES=mytest.h mytest.c

在根目錄下的configure.in中加AC_PROG_LIBTOOL

 

動態庫編譯之前,需要安裝libtool工具:apt-get install libtool。

若出現:“required file `./ltmain.sh' not found”錯誤,是因爲libtool的配置問題。

解決方法:

$libtoolize --automake --debug --copy –force

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章