一、 相關概念的介紹
什么是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的關鍵在於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
zz http://www.cnblogs.com/ericdream/archive/2011/12/09/2282359.html