【原】automake工具,幫你做軟件架構,管理你的Makefile


Makefile 管理工具 — Automake and Autoconf

 

該工程下載路徑:http://files.cnblogs.com/iTsihang/hello-2.0.zip

automake 參考資料:http://www.linuxforum.net/books/automake.html

autoconf 參考資料:http://www.linuxforum.net/books/autoconf.html

automake源碼下載:ftp://ftp.gnu.org/gnu/automake/

autoconf源碼下載:ftp://ftp.gnu.org/gnu/autoconf/

 

Automake支持的目錄結構

目前automake支持三種目錄層次:flat、shallow和deep。

  • flat(平),指的是所有文件都位於同一個目錄中

      就是所有源文件、頭文件以及其他庫文件都位於當前目錄中,且沒有子目錄。Termutils就是這一類。

  • shallow(淺),指的是主要的源代碼都儲存在頂層目錄,其他各個部分則儲存在子目錄中

      就是主要源文件在當前目錄中,而其它一些實現各部分功能的源文件位於各自不同的目錄。automake本身就是這一類。

  • deep(深),指的是所有源代碼都被儲存在子目錄中;頂層目錄主要包含配置信息

本例子目錄結構如圖所示,屬於deep類:

 1 hello-2.0  2 ├── aclocal.m4  3 ├── AUTHORS  4 ├── autom4te.cache  5 │ ├── output.0  6 │ ├── output.1  7 │ ├── requests  8 │ ├── traces.0  9 │ └── traces.1 10 ├── autoscan.log 11 ├── ChangeLog 12 ├── configure 13 ├── configure.in 14 ├── COPYING -> /usr/share/automake-1.11/COPYING 15 ├── depcomp -> /usr/share/automake-1.11/depcomp 16 ├── home 17 │ ├── li 18 │ │ ├── inc 19 │ │ │ └── li.h 20 │ │ └── src 21 │ │ ├── li.c 22 │ │ ├── Makefile.am 23 │ │ └── Makefile.in 24 │ ├── wang 25 │ │ ├── inc 26 │ │ │ └── wang.h 27 │ │ └── src 28 │ │ ├── Makefile.am 29 │ │ ├── Makefile.in 30 │ │ └── wang.c 31 │ └── zhang 32 │ ├── inc 33 │ │ └── zhang.h 34 │ └── src 35 │ ├── Makefile.am 36 │ ├── Makefile.in 37 │ └── zhang.c 38 ├── INSTALL -> /usr/share/automake-1.11/INSTALL 39 ├── install-sh -> /usr/share/automake-1.11/install-sh 40 ├── main 41 │ ├── main.c 42 │ ├── Makefile.am 43 │ └── Makefile.in 44 ├── Makefile.am 45 ├── Makefile.in 46 ├── missing -> /usr/share/automake-1.11/missing 47 ├── NEWS 48 ├── park 49 │ ├── Makefile.am 50 │ ├── Makefile.in 51 │ ├── public.c 52 │ └── public.h 53 └── README 54 55 13 directories, 39 files

這是一個基本的架構結構,可以形成一個比較成熟的軟件框架。

 

例子介紹

如上圖所示為該例子的結構層次,有主目錄main,家目錄home和公園目錄part。home下根據姓氏分了三家:li家,wang家和zhang家,每家都有相同的結構:src和inc;part是三家共同擁有的公共目錄,里面包含了三家共用的接口;main目錄是我們的主目錄,存放執行入口。每家的人(程序)做一件事情,那就是依次在入口(main)中說一句:hello。

 1 int main(void)  2 {  3  4 /* access home li */  5  lisayhello();  6  7 /* access home wang */  8  wangsayhello();  9 10 /* access home zhang */ 11  zhangsayhello(); 12 13 return 0; 14 }

 

步驟    

分別在每個目錄下創建Makefile.am文件,並編輯

在使用autoconf和automake自動工具生成Makefile的時候,該工具會在工程目錄下查找Makefile.am文件,有該文件的目錄下會自動生成相應的Makefile文件。當然也可以后期手動添加。一般的生成順序是:

1> 根據工程結構,在需要生成Makefile的目錄下創建Makefile.am文件。

我們需要生成Makefile的目錄有home/li/src/,home/wang/src/,home/zhang/src/和main/,所以我們共需創建4個Makefile.am文件。

2> 編輯Makefile.am文件,指出需要在該目錄下完成的工作,如編譯一些源文件,鏈接某些庫文件等等;

這里有三類Makefile.am,現在分類介紹其在整個工程目錄中實現的功能。  

家目錄下的Makefile.am主要用來編譯同目錄下的源文件。例如,編輯home/li/src/Makefile.am如下:

1 noinst_PROGRAMS= li #生成的目標 2 li_SOURCES= li.c #生成目標依賴的源 3 4 li_LDADD= #可能需要加載的其他的目標 5 li_LDFLAGS= #加載目標需要的配置參數 6 li_a_LIBADD= #可能需要加載的其他的庫 7 8 DEFS += -D_GNU_SOURCE

同理編輯其他兩個姓氏目錄以及公園目錄下的Makefile.am文件,替換相應字段即可。

主目錄下的Makefile.am主要用來生成最終的可執行目標程序,它需要家目錄下的姓氏提供方法。編輯如下:

 1 # executable file last created  2  3 noinst_PROGRAMS= hello  4  5 # main entry file  6  7 hello_SOURCES= main.c  8  9 # object file that needed 10 11 OBJECTS= $(top_srcdir)/home/li/src/li.o\ 12 13 $(top_srcdir)/home/zhang/src/zhang.o\ 14 15 $(top_srcdir)/home/wang/src/wang.o 16 17 # load object file when linking 18 19 hello_LDADD= $(OBJECTS) 20 21 # flags of libs 22 23 hello_LDFLAGS= -D_GNU_SOURCE 24 25 DEFS += -D_GNU_SOURCE 26 27 #LIBS= -lpthread

篇幅有限,每行的具體含義,請自行查看相關文檔,或者我提供的鏈接可能對你有幫助。

頂層目錄Makefile.am給automake工具提供工程下各個子目錄的路徑。在make的時候,告訴automake應該進哪些目錄執行makefile,執行過程按照SUBDIRS 定義順序來。編輯如下:

 1 SUBDIRS= home/li/src\  2  3 home/zhang/src\  4  5 home/wang/src\  6  7  park\  8  9  main 10 11 # automake need known where it is 12 13 CURRENTPATH= $(shell pwd) 14 15 # head files while linking 16 17 INCLUDES= -I$(CURRENTPATH)/park/include -I$(CURRENTPATH)/home/li/inc -I$(CURRENTPATH)/home/wang/inc -I$(CURRENTPATH)/home/zhang/inc 18 19 export INCLUDES

 

運行autoscan命令,生成configure.scan文件

 1 # -*- Autoconf -*-  2  3 # Process this file with autoconf to produce a configure script.  4  5 AC_PREREQ([2.68])  6  7 AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])  8  9 AC_CONFIG_SRCDIR([home/zhang/src/zhang.c]) 10 11 AC_CONFIG_HEADERS([config.h]) 12 13 # Checks for programs. 14 15 AC_PROG_CC 16 17 # Checks for libraries. 18 19 # Checks for header files. 20 21 # Checks for typedefs, structures, and compiler characteristics. 22 23 # Checks for library functions. 24 25 AC_CONFIG_FILES([Makefile 26 27 home/li/src/Makefile 28 29 home/wang/src/Makefile 30 31 home/zhang/src/Makefile 32 33 park/Makefile 34 35 main/Makefile]) 36 37 AC_OUTPUT

通過上面的步驟,可以發現,autoscan工具會自動查找工程目錄,包括子目錄,在發現有Makefile.am存在的目錄下為即將創建的Makefile指明工程路徑。當然,可以根據自己的需要,指定該文件,如下。

 

修改configure.scan文件

$ mv configure.scan configure.in(老版本支持configure.ac,我沒用過)

修改如下部分:

 1 AC_CONFIG_SRCDIR([main/main.c]) #指明目錄源文件,特指主方法所在源文件  2  3 #AC_CONFIG_HEADERS([config.h])  4  5 AM_INIT_AUTOMAKE("hello", "2.0.0") #最終生成的目標文件和版本,版本一般在打包的時候用  6  7 # Checks for programs.  8  9 AC_PROG_CC 10 11 # Checks for libraries. 12 13 # Checks for header files. 14 15 # Checks for typedefs, structures, and compiler characteristics. 16 17 # Checks for library functions. 18 19 AC_OUTPUT([Makefile 20 21 home/li/src/Makefile 22 23 home/wang/src/Makefile 24 25 home/zhang/src/Makefile 26 27 park/Makefile 28 29 main/Makefile])

 

在工程目錄下創建:NEWS、 README、 ChangeLog 、AUTHORS

touch NEWS README ChangeLog AUTHORS

 

將/usr/share/automake-1.X/目錄下的 depcomp 和 complie 文件拷貝到本目錄下

1 cp /usr/share/automake-1.x/depcomp . 2 cp /usr/share/automake-1.x/compile  .

 

運行aclocal命令

根據 configure.in 的配置,生成 aclocal.m4 文件和 autom4te.cache 目錄

 

運行autoconf

根據configure.in的配置生成配置腳本 — configure。

 

運行automake --add-missing

運行automake后,就從各個目錄下的Makefile.am中讀取make的宏定義和目標或者更多參數,根據這些配置自動生成新的文件 — Makefile.in。例如,在Makefile.am中定義了要生成的目標文件,同時可能會定義生成目標所需的源文件,依賴文件—包括依賴的頭文件,目標文件,目標庫等,同時也指定軟件的加載標志。

當然,為了符合GNU 發布軟件的標准,首次運行該命令后會提示缺少:AUTHORS,ChangeLog,NEWS,README。這些文件,你可以手動創建,如果不發布無需編輯。同時,也會生成install-sh,missing,INSTALL,COPYING 鏈接文件,這些鏈接文件分別指向auto工具默認安裝路徑:/usr/share/automake-1.XX/目錄下的相應文件。

此外,最重要的文件就是生成了除過上面的Makefile.in文件外,還生成了我們需要的configure文件。

 

配置

配置工程安裝和運行環境,通過該步驟可以向工程傳遞配置和安裝信息等,最后生成Makefile。

 

編譯

 執行Makefile ,編譯工程,鏈接文件,生成目標執行程序。

 

問題探討

指定的install-sh,missing,INSTALL,COPYING文件的鏈接錯誤

這根據自己系統當前安裝的工具而定,你可以將這些鏈接重新指向automake安裝目錄下的相應文件,也可以將automake安裝目錄下的文件拷貝到工程目錄。但是考慮GNU 風格的完整性,建議大家執行拷貝步驟,這樣也省去重新鏈接的麻煩,更主要的是不會像鏈接那樣對安裝路徑和版本的依賴那么高,拷貝會一勞永逸。

 

如果因為任何原因修改了configure.in,修改后如果不執行autoconf命令,那么是不會生成新的configure

在編譯的時候,出現類似 “In function `_start'”的錯誤

我們知道,automake要求在每個具有源程序的目錄下都要創建Makefile.am。但是automake編譯完成后,該工具會自動執行鏈接過程,即將編譯的目標文件自動鏈接成同名的可執行程序,可是源程序中沒有指定的入口(在Linux中為”main”方法),所以在鏈接的時候無法找到入口而產生 “鏈接錯誤”。

修改方法:此時該目錄下已經生成Makefile.in,編輯找到鏈接執行出,屏蔽掉。例如本例中屏蔽掉home/li/src/Makefile.in的189行:

#   $(li_LINK) $(li_OBJECTS) $(li_LDADD) $(LIBS)

其他類似問題都做相同處理。

 

各個目標之間的依賴處理

編譯的時候,可能會遇到依賴問題。所謂依賴問題,如下:

      A → B

      B → C

      …...

A依賴B, B依賴C,那么在生成目標A的時候,就需要將B和C同時告知A。在本例子中,生成目標hello的時候需要li.o,wang.o,zhang.o目標,所以在最終鏈接的時候需要將這些目標鏈接進去。

現在有個問題我沒解決,如果編譯目標文件(而非最終的可執行文件)的時候,如果存在上面的依賴關系,怎么處理?在這個例子工程的park/public.c文件,如果里面的廣播方法被某一家調用,那么這塊的Makefile.am怎么寫(我沒搞定)?

最后,如果因需要,或者任何原因修改了Makefile.am,那么需要運行automake更新makefile.in

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM