最近在拼接一個純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文件,其他類似。
所必須的軟件: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型,也就是說我們要做挑戰性的事情:)。注:我們的測試程序是基於多線程的簡單程序。
首先進入 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的流程,如圖所示:
當我們利用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]),該宏的含義如下:
其中,LIBS是link的一個選項,詳細請參看後續的Makefile文件。由於我們在程序中使用了讀寫鎖,所以我們測試pthread庫中是否存在pthread_rwlock_init函數。
由於我們是基於deep類型來創建makefile文件,所以我們需要在四處創建Makefile文件。即:project目錄下,lib目錄下,core和shell目錄下。 Autoconf提供了很多內置宏來做相關的檢測,限於篇幅關係,我們在這裏對其他宏不做詳細的解釋,具體請參看參考文獻1和參考文獻2,也可參看autoconf信息頁。
Makefile.am是一種比Makefile更高層次的規則。只需指定要生成什麼目標,它由什麼源文件生成,要安裝到什麼目錄等構成。
表一列出了可執行文件、靜態庫、頭文件和數據文件,四種書寫Makefile.am文件個一般格式。
對於可執行文件和靜態庫類型,如果只想編譯,不想安裝到系統中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。
Makefile.am還提供了一些全局變量供所有的目標體使用:
在Makefile.am中儘量使用相對路徑,系統預定義了兩個基本路徑: