autotools —— autoconf和automake生成Makefile檔案(原始檔位於多個子資料夾)

ztguang發表於2016-02-01

http://blog.csdn.net/koala002/article/details/6370548

最近在拼接一個純C的多核模擬器multi2sim和C++的DRAM模擬器dramsim時,用到了使用autoconf/automake自動生成Makefile,所以這裡總結記錄一下,以便以後方便找到。

1、首先,autoscan生成configure.scan,修改生成configure.in檔案,裡面主要是一些庫、環境的檢測。

2、其次,使用者只需要手動寫Makefile.am,Makefile.am是比Makefile更高的一個層次。書寫時需要需要寫出目標、原始檔、遞迴子資料夾、所需要標頭檔案、連結庫、路徑等資訊。

3、aclocal、autoconf、automake等命令,具體見流程。特別是換另一臺機器時有時需要aclocal。

4、Makefile.am裡面可以設定如CC、CXX、AM_CFLAGS、AM_CPPFLAGS等變數,並且一個模組內預設的是.c檔案用CC編譯器,.cpp檔案用CXX編譯器編譯。這樣就可以一個模組內C/C++混合編譯了。

5、有一次編譯過程中,報錯moesi.o需要的moesi.c找不到,不過我已經把Makefile.am中依賴改成moesi.cpp,重新 automake依然無效,後來發現資料夾下會有一個.deps資料夾,指示依賴檔案,如果發生上面問題,把這個.deps資料夾刪除重新 automake等步驟即可。

6、C/C++互相呼叫時extern "C"的使用。

7、gcc編譯cpp檔案時-lstdc++的使用。gcc工具集好像是根據字尾名來判斷檔案型別的。

8、有時候編譯過程很詭異,這時候只能是關注一些事情,比如5、6、7這些。

 

以下關於生成Makefile內容轉自《例解 autoconf 和 automake 生成 Makefile 檔案》

引子

無論是在Linux還是在Unix環境中,make都是一個非常重要的編譯命令。不管是自己進行專案開發還是安裝應用軟體,我們都經常要用到 make或 make install。利用make工具,我們可以將大型的開發專案分解成為多個更易於管理的模組,對於一個包括幾百個原始檔的應用程式,使用make和 makefile工具就可以輕而易舉的理順各個原始檔之間紛繁複雜的相互關係。但是如果通過查閱make的幫助文件來手工編寫Makefile,對任何程 序員都是一場挑戰。幸而有GNU 提供的Autoconf及Automake這兩套工具使得編寫makefile不再是一個難題。

本文將介紹如何利用 GNU Autoconf 及 Automake 這兩套工具來協助我們自動產生 Makefile檔案,並且讓開發出來的軟體可以像大多數原始碼包那樣,只需"./configure", "make","make install" 就可以把程式安裝到系統中。

 


模擬需求

假設原始檔按如下目錄存放,如圖1所示,運用autoconf和automake生成makefile檔案。

 

假設src是我們原始檔目錄,include目錄存放其他庫的標頭檔案,lib目錄存放用到的庫檔案,然後開始按模組存放,每個模組都有一個對應的目 錄,模組下再分子模組,如apple、orange。每個子目錄下又分core,include,shell三個目錄,其中core和shell目錄存 放.c檔案,include的存放.h檔案,其他類似。

圖 1檔案目錄結構

file


工具簡介

所必須的軟體:autoconf/automake/m4/perl/libtool(其中libtool非必須)。

autoconf是一個用於生成可以自動地配置軟體原始碼包,用以適應多種UNIX類系統的shell指令碼工具,其中autoconf需要用到 m4,便於生成指令碼。automake是一個從Makefile.am檔案自動生成Makefile.in的工具。為了生成 Makefile.in,automake還需用到perl,由於automake建立的釋出完全遵循GNU標準,所以在建立中不需要perl。 libtool是一款方便生成各種程式庫的工具。

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

1) flat指的是所有檔案都位於同一個目錄中。

就是所有原始檔、標頭檔案以及其他庫檔案都位於當前目錄中,且沒有子目錄。Termutils就是這一類。

2) shallow指的是主要的原始碼都儲存在頂層目錄,其他各個部分則儲存在子目錄中。

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

3) deep指的是所有原始碼都被儲存在子目錄中;頂層目錄主要包含配置資訊。

就是所有原始檔及自己寫的標頭檔案位於當前目錄的一個子目錄中,而當前目錄裡沒有任何原始檔。 GNU cpio和GNU tar就是這一類。

flat型別是最簡單的,deep型別是最複雜的。不難看出,我們的模擬需求正是基於第三類deep型,也就是說我們要做挑戰性的事情:)。注:我們的測試程式是基於多執行緒的簡單程式。


 

生成 Makefile 的來龍去脈

首先進入 project 目錄,在該目錄下執行一系列命令,建立和修改幾個檔案,就可以生成符合該平臺的Makefile檔案,操作過程如下:

1) 執行autoscan命令

2) 將configure.scan 檔案重新命名為configure.in,並修改configure.in檔案

3) 在project目錄下新建Makefile.am檔案,並在core和shell目錄下也新建makefile.am檔案

4) 在project目錄下新建NEWS、 README、 ChangeLog 、AUTHORS檔案

5) 將/usr/share/automake-1.X/目錄下的depcomp和complie檔案拷貝到本目錄下

6) 執行aclocal命令

7) 執行autoconf命令

8) 執行automake -a命令

9) 執行./confiugre指令碼

可以通過圖2看出產生Makefile的流程,如圖所示:

圖 2生成Makefile流程圖

makefile


 

Configure.in的八股文

當我們利用autoscan工具生成confiugre.scan檔案時,我們需要將confiugre.scan重新命名為confiugre.in檔案。confiugre.in呼叫一系列autoconf巨集來測試程式需要的或用到的特性是否存在,以及這些特性的功能。

下面我們就來目睹一下confiugre.scan的廬山真面目:

[python] view plaincopy
  1. # Process this file with autoconf to produce a configure script.  
  2. AC_PREREQ(2.59)  
  3. AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)  
  4. AC_CONFIG_SRCDIR([config.h.in])  
  5. AC_CONFIG_HEADER([config.h])  
  6. # Checks for programs.  
  7. AC_PROG_CC  
  8. # Checks for libraries.  
  9. # FIXME: Replace `main' with a function in `-lpthread':  
  10. AC_CHECK_LIB([pthread], [main])  
  11. # Checks for header files.  
  12. # Checks for typedefs, structures, and compiler characteristics.  
  13. # Checks for library functions.  
  14. AC_OUTPUT  
  15.    

 

每個configure.scan檔案都是以AC_INIT開頭,以AC_OUTPUT結束。我們不難從檔案中看出confiugre.in檔案的一般佈局:

[c-sharp] view plaincopy
  1. AC_INIT  
  2.  測試程式  
  3.  測試函式庫  
  4.  測試標頭檔案  
  5.  測試型別定義  
  6.  測試結構  
  7.  測試編譯器特性  
  8.  測試庫函式  
  9.  測試系統呼叫  
  10. AC_OUTPUT  

 

上面的呼叫次序只是建議性質的,但我們還是強烈建議不要隨意改變對巨集呼叫的次序。

現在就開始修改該檔案:

[python] view plaincopy
  1. $mv configure.scan configure.in  
  2. $vim configure.in  

 

修改後的結果如下:

[python] view plaincopy
  1.           
  2. #                                -*- Autoconf -*-  
  3. # Process this file with autoconf to produce a configure script.  
  4.   
  5. AC_PREREQ(2.59)  
  6. AC_INIT(test, 1.0, normalnotebook@126.com)  
  7. AC_CONFIG_SRCDIR([src/ModuleA/apple/core/test.c])  
  8. AM_CONFIG_HEADER(config.h)  
  9. AM_INIT_AUTOMAKE(test,1.0)  
  10.   
  11. # Checks for programs.  
  12. AC_PROG_CC  
  13. # Checks for libraries.  
  14. # FIXME: Replace `main' with a function in `-lpthread':  
  15. AC_CHECK_LIB([pthread], [pthread_rwlock_init])  
  16. AC_PROG_RANLIB  
  17. # Checks for header files.  
  18. # Checks for typedefs, structures, and compiler characteristics.  
  19. # Checks for library functions.  
  20. AC_OUTPUT([Makefile  
  21.         src/lib/Makefile  
  22.         src/ModuleA/apple/core/Makefile  
  23.         src/ModuleA/apple/shell/Makefile  
  24.         ])  

其中要將AC_CONFIG_HEADER([config.h])修改為:AM_CONFIG_HEADER(config.h), 並加入AM_INIT_AUTOMAKE(test,1.0)。由於我們的測試程式是基於多執行緒的程式,所以要加入AC_PROG_RANLIB,不然運 行automake命令時會出錯。在AC_OUTPUT輸入要建立的Makefile檔名。

由於我們在程式中使用了讀寫鎖,所以需要對庫檔案進行檢查,即AC_CHECK_LIB([pthread], [main]),該巨集的含義如下:

macro
其中,LIBS是link的一個選項,詳細請參看後續的Makefile檔案。由於我們在程式中使用了讀寫鎖,所以我們測試pthread庫中是否存在pthread_rwlock_init函式。

由於我們是基於deep型別來建立makefile檔案,所以我們需要在四處建立Makefile檔案。即:project目錄下,lib目錄 下,core和shell目錄下。 Autoconf提供了很多內建巨集來做相關的檢測,限於篇幅關係,我們在這裡對其他巨集不做詳細的解釋,具體請參看參考文獻1和參考文獻2,也可參看 autoconf資訊頁。


實戰Makefile.am

Makefile.am是一種比Makefile更高層次的規則。只需指定要生成什麼目標,它由什麼原始檔生成,要安裝到什麼目錄等構成。

表一列出了可執行檔案、靜態庫、標頭檔案和資料檔案,四種書寫Makefile.am檔案個一般格式。

表 1Makefile.am一般格式

makefile.am1
 

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

Makefile.am還提供了一些全域性變數供所有的目標體使用:

 

表 2 Makefile.am中可用的全域性變數

makefile.am2
 

 

在Makefile.am中儘量使用相對路徑,系統預定義了兩個基本路徑:

 

表 3Makefile.am中可用的路徑變數

makefile.am3


 

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
閱讀(162) | 評論(0) | 轉發(0) |
給主人留下些什麼吧!~~
評論熱議

相關文章