GNU裏的強大工具還真是不少,本文將主要關注於GNU Autotools,包括:autoconf, automake等。簡要闡述一下如何利用這些工具的強大功能來爲linux下的軟件開發服務。在linux系統上,有人將autoconf,automake視爲與gcc同等重要。
1 概念
首先說明一下什麼是GNU Autotools(autoconf, automake, libtool)。
autoconf是一個用於生成可以自動地配置軟件源碼包,用以適應多種UNIX類系統的shell腳本工具,其中autoconf需要用到m4,便於生成腳本。
automake是一個從Makefile.am文件自動生成Makefile.in的工具。爲了生成Makefile.in,automake還需用到perl,由於automake創建的發佈完全遵循GNU標準,所以在創建中不需要perl。libtool是一款方便生成各種程序庫的工具。
直觀上來說,autoconf實現工程配置,automake自動生成工程的Makefile,而且這種makefile是層次式的。
目前automake支持三種目錄層次:flat、shallow和deep:
flat指的是所有文件都位於同一個目錄中。就是所有源文件、頭文件以及其他庫文件都位於當前目錄中,且沒有子目錄。我們在開發簡單的應用的時候,應該多數都屬於這一類;
shallow指的是主要的源代碼都儲存在頂層目錄,其他各個部分則儲存在子目錄中。就是主要源文件在當前目錄中,而其它一些實現各部分功能的源文件位於各自不同的目錄。gcc中就有類似的目錄層次,而且automake本身就是這一類。
deep指的是所有源代碼都被儲存在子目錄中;頂層目錄主要包含配置信息。就是所有源文件及自己寫的頭文件位於當前目錄的一個子目錄中,而當前目錄裏沒有任何源文件。 GNU cpio和GNU tar就是這一類。
此外,關於以上工具的詳細介紹以及使用方法可以參考下面這本書:http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool,如果習慣於看中文材料的話,也可以參考IBM的內部文檔:http://www.ibm.com/developerworks/cn/linux/l-makefile/。這篇文章以一個示例工程出發較爲詳細的闡述瞭如何使用以上GNU的工具爲其生成配置文件以及Makefile,本文的部分圖例也是引自該文。本文將以一個更爲簡單的例子出發,簡要敘述一下使用上述工具的流程。
2 示例
我們新建一個簡單的工程,命名爲“simple”,該工程的層次結構採用deep的方式:
在simple中包含子目錄src,用於存儲所有的源文件
src目錄又包含子目錄:include(用於存放公用頭文件),core(核心部分源文件),lib(
存放用於生成靜態鏈接庫的源文件),lib_so(存放用於生成動態鏈接庫的源文件)
所以需要創建Makefile.am的源文件目錄包括:core, lib, lib_so
3 基本流程:
流程圖:
實例:
1)在當前目錄"simple"下運行autoscan命令:將會掃描當前工程內的源文件信息,生成文件configure.scan
2)將configure.scan 文件重命名爲configure.in,並修改configure.in文件:
configure.in內的基本結構如下,有<--標記的爲在本實例中需要修改的參數:
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(simple_ccm, 0.1, [email protected]) <-- 初始化配置信息
AC_CONFIG_SRCDIR([src/core/ccm.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(ccm, 0.1) <-- 新添加的與automake相關的參數
dnl Checking for compiler llvmc
# Checks for programs. # 檢查編譯器
AC_PROG_CC <-- 可以在此處指定默認的編譯器
# Checks for libraries. # 檢查庫
AC_CHECK_LIB([pthread],[pthread_create]) <-- 指定需要檢查的庫以及庫函數
AC_PROG_RANLIB <-- 指定檢查ranlib
# Checks for header files. #檢查系統頭文件
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics. #檢查類型定義,數據結構以及編譯器的一些特徵
# Checks for library functions. #檢查庫函數
AC_OUTPUT([ #configure的輸出
Makefile <-- 標註出當前工程中所有需要生成Makefile的子目錄
src/core/Makefile
src/lib/Makefile
src/lib_so/Makefile
])
3)在simple目錄下新建Makefile.am文件,並在src/core, src/lib, src/lib_so目錄下也新建makefile.am文件
首先修改simple目錄下的Makefile.am,內容如下:
SUBDIRS=src/lib src/lib_so src/core # 標註當前工程中有源文件需要編譯的子目錄
CURRENTPATH=$(shell /bin/pwd) # 得到當前路徑
INCLUDES=-I$(CURRENTPATH)/src/include # 預先定義編譯時包含頭文件的路徑,並export到子目錄
export INCLUDES
修改個分目錄下的Makefile.am,這裏需要注意的是,三個分目錄分別生成不同類型的文件:
src/core中生成可執行文件,Makefile.am內容如下:
bin_PROGRAMS=ccm #指定可執行文件名
ccm_SOURCES=ccm.c xxx.c xxx1.c #生成可執行文件依賴的源文件
#AM_LDFLAGS = -L $(top_srcdir)/src/lib
ccm_LDADD = $(top_srcdir)/src/lib/libccm.a $(top_srcdir)/src/lib_so/libccm.so # 編譯鏈接時需要的庫文件
DEFS += -D_GNU_SOURCE
LIBS = -lpthread #指定要鏈接的庫,此信息也可以在configure.in的AC_CHECK_LIB參數中指定
上述的$(top_srcdir)指的是simple目錄,bin_PROGRAMS表明是生成可安裝的可執行文件,也可以修改前綴用noinst_PROGRAMS表明不安裝。
----------------------------------------
src/lib中生成靜態鏈接庫,Makefile.am內容如下:
noinst_LIBRARIES=libccm.a #指定生成不安裝的靜態鏈接庫,同時指定庫名稱
libccm_a_SOURCES = warn.c decl.c #指定生成該鏈接庫依賴的源文件列表
INCLUDES = -I$(top_srcdir)/src/include
-----------------------------------------
4)在simple目錄下新建NEWS、 README、 ChangeLog 、AUTHORS文件
5)將/usr/share/automake-1.X/目錄下的depcomp和complie文件拷貝到simple目錄下
6)運行aclocal命令
7)運行autoconf命令
8)運行automake -a命令
9)運行./confiugre腳本
或者也可以將第6到第9項命令封裝到一個腳本文件autogen.sh中批量執行。
4 總結
以上簡單闡述了一下autoconf以及automake的使用方法以及爲一個工程進行配置和自動生成makefile的流程,libtool的使用未在此文中列出,這部分內容還待補充。總體來說,autotool的使用方便了程序員在linux系統上的開發流程:一方面,它使得程序員可以簡捷方便的對一個工程總攬全局,Makefile.am提供了比makefile更加高層的抽象和更強大的功能,程序員不需要痛苦地在每一個分目錄下去編寫複雜的Makefile; 另一方面,它使得對一個工程的維護也更加方便,如果在當前工程中新添加一個模塊,只需要修改工程目錄下的configure.in和Makefile.am,以及新模塊目錄下的Makefile.am即可將新模塊集成到工程中。