autoconf 和 automake 生成 Makefile 文件學習

最近在拼接一個純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的廬山真面目:

 

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

 

上面的調用次序只是建議性質的,但我們還是強烈建議不要隨意改變對宏調用的次序。

現在就開始修改該文件:

 

修改後的結果如下:

其中要將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


 

發佈了42 篇原創文章 · 獲贊 6 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章