使用autoconf和automake工具來幫助我們自動地生成符合自由軟體慣例的 Makefile。
最初的原版沒找到,找到了幾個較詳述的部落格。按照部落格一步一步實驗並記錄在‘範例’中。
Configure,Makefile.am, Makefile.in, Makefile檔案之間關係(轉) - 一個人的天空@ - 部落格園
automake的理解和實踐總結_yihongxiaoxiang的專欄-CSDN部落格_automake視訊
Makefile是用於自動編譯和鏈接的 ,一個工程有很多檔案組成,每一個檔案的改變都會導致工程的重新鏈接,但是不是 所有的檔案都需要重新編譯,Makefile中紀錄有檔案的資訊,在 make時會決定在鏈接的時候需要重新編譯哪些檔案.
Makefile的宗旨就是 :讓編譯器知道要編譯一個檔案需要依賴其他的 哪些檔案.當那些依賴檔案有了改變,編譯器會自動的發現最終的生成檔案已經過時,而重新編譯相應的 模組.
Makefile的 基本結構不是 很複雜,但當一個程式開發人員開始寫Makefile時,經常會懷疑自己寫的 是 否符合慣例,而且自己寫的 Makefile經常和自己的 開發環境相關聯,當系統環境變數或路徑發生了變化後,Makefile可能還要跟着修改.這樣就造成了手工書寫Makefile的 諸多問題,automake恰好能很好地幫助我們解決這些問題.
使用automake,程式開發人員只需要寫一些簡單的 含有預定義宏的 檔案,由autoconf根據一個宏檔案生成configure,由automake根據另一個宏檔案生成Makefile.in,再使用configure依據Makefile.in來生成一個符合慣例的 Makefile.下面 下麪我們將詳細介紹Makefile的 automake生成方法.
autoscan是用來掃描原始碼目錄生成configure.scan檔案。autoscan可以用目錄名做爲參數,但如果你不使用參數的話,那麼autoscan將認爲使用的是當前目錄.autoscan將掃描你所指定目錄中的原始檔,並建立configure.scan檔案.
掃描原始碼以搜尋普通的可移植性問題,比如檢查編譯器,庫,標頭檔案等,生成檔案configure.scan,它是configure.ac的一個雛形。
根據已經安裝的宏,使用者定義宏和acinclude.m4檔案中的宏將configure.ac檔案所需要的宏集中定義到檔案 aclocal.m4中。aclocal是一個perl 指令碼程式,它的定義是:「aclocal - create aclocal.m4 by scanning configure.ac」
根據configure.ac中的某些宏,比如cpp宏定義,執行m4,聲稱config.h.in
automake將Makefile.am中定義的結構建立Makefile.in,然後configure指令碼將生成的Makefile.in檔案轉換 爲Makefile。如果在configure.ac中定義了一些特殊的宏,比如AC_PROG_LIBTOOL,它會呼叫libtoolize,否則它 會自己產生config.guess和config.sub
我們使用automake --add-missing來產生Makefile.in.
選項–add-missing的 定義是 「add missing standard files to package」,它會讓automake加入一個標準的軟體包所必須的一些檔案.
我們用automake產生出來的Makefile.in檔案是符合GNU Makefile慣例的 ,接下來我們只要執行configure這個shell 指令碼就可以產生合適的Makefile檔案了.
Makefile.am是用來生成Makefile.in的 ,需要你手工編寫。Makefile.am中定義了一些內容:
AUTOMAKE_OPTIONS
AUTOMAKE_OPTIONS是 automake的 選項。在執行automake時,它會檢查目錄下是否存在標準GNU軟體包中應具備的各種檔案,例如AUTHORS.ChangeLog.NEWS等檔案。我們將其設定成foreign時,automake會改用一般軟體包的標準來檢查.
bin_PROGRAMS
bin_PROGRAMS是指定我們所要產生的 可執行檔案的檔名.如果你要產生多個可執行檔案,那麼在各個名字間用空格隔開.
helloworld_SOURCES
helloworld_SOURCES是指定產生"helloworld"時所需要的原始碼.如果它用到了多個原始檔,那麼請使用空格符號將它們隔開.
#比如需要helloworld.h, helloworld.c
helloworld_SOURCES= helloworld.h helloworld.c.
如果你在 bin_PROGRAMS定義了多個可執行檔案,則對應每個可執行檔案都要定義相對的filename_SOURCES
AUTOMAKE_OPTIONS = foreign
# 定義包含哪些子目錄
SUBDIRS = avl thread httpp net log timing
# 定義生成的可執行檔案
bin_PROGRAMS = icecast
# install時不被導出的標頭檔案
noinst_HEADERS = admin.h cfgfile.h logging.h sighandler.h connection.h \
global.h util.h slave.h source.h stats.h refbuf.h client.h
# 生成icecast所需要的原始檔
icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \
util.c slave.c source.c stats.c refbuf.c client.c
# 依賴的庫
icecast_DEPENDENCIES = @ICECAST_OPTIONAL@ net/libicenet.la thread/libicethread.la \
httpp/libicehttpp.la log/libicelog.la avl/libiceavl.la timing/libicetiming.la
icecast_LDADD = $(icecast_DEPENDENCIES) @XIPH_LIBS@ @KATE_LIBS@
AUTOMAKE_OPTIONS = foreign
# 生成不需要install的lib
noinst_LTLIBRARIES = libicethread.la
noinst_HEADERS = thread.h
# lib的原始檔
libicethread_la_SOURCES = thread.c
將configure.ac中的宏展開,生成 configure指令碼。這個過程可能要用到aclocal.m4中定義的宏。
autoconf用來產生configure檔案。configure是一個指令碼,它能設定源程式來適應各種不同的操作系統平臺,並且根據不同的系統來產生合適的Makefile,從而可以使你的原始碼能在不同的操作系統平臺上被編譯出來。
configure.in檔案的內容是一些宏,這些宏經過autoconf 處理後會變成檢查系統特性、環境變數、軟體必須的參數的shell指令碼。configure.in檔案中的宏的順序並沒有規定,但是你必須在所有宏的最前面和最後面分別加上AC_INIT宏和AC_OUTPUT宏.
我們在使用automake時,實際上還需要用到其他的一些宏,但我們可以用aclocal來幫我們自動產生.執行aclocal後我們會得到aclocal.m4檔案.
產生了configure.in和aclocal.m4兩個宏檔案後,我們就可以使用autoconf來產生configure檔案了.
./configure的過程
在符合GNU Makefiel慣例的 Makefile中,包含了一些基本的預先定義的操作:
yum install automake autoconf
還會自動安裝一些依賴包(perl)
按照慣例從helloworld開始。
命令執行順序:
整個過程中:
helloworld.c
Makefile.am
configure.scan
檔案修改爲 configure.in
mkdir helloAutoMake
cd helloAutoMake/
#include <stdio.h>
int main(){
printf("Hello automake!\n");
return 0;
}
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 4
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
autoscan會掃描原始碼以搜尋普通的可移植性問題,比如檢查編譯器、庫、標頭檔案等,生成檔案configure.scan,它是configure.ac或者configure.in的雛形。
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# autoscan
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ls
autoscan.log configure.scan helloworld.c
執行後在 hellowrold目錄下會生成一個檔案:configure.scan,我們可以拿它作爲configure.in的 藍本.(生成了configure.scan,autoscan.log檔案)
將configure.scan 修改爲 configure.in
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# mv configure.scan configure.in
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ls
autoscan.log configure.in helloworld.c
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([helloworld.c])
# AC_CONFIG_HEADERS([config.h]) #這行不註釋,則需要執行autoheader
AM_INIT_AUTOMAKE(helloworld, 1.0) # 新增名稱和版本資訊
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
# AC_OUTPUT
AC_OUTPUT(Makefile) # 需要輸出Makefile檔案
aclocal 是一個perl 指令碼程式。aclocal 根據configure.in 檔案的內容,自動生成aclocal.m4 和autom4te.cache檔案。但是使用configure.in時會提示一個warning,爲避免這個warning可以命名爲configure.ac
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# aclocal
aclocal: warning: autoconf input should be named 'configure.ac', not 'configure.in'
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 52
-rw-r--r-- 1 root root 37794 Aug 12 20:15 aclocal.m4
drwxr-xr-x 2 root root 4096 Aug 12 20:15 autom4te.cache
-rw-r--r-- 1 root root 0 Aug 12 20:02 autoscan.log
-rw-r--r-- 1 root root 529 Aug 12 20:14 configure.in
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# mv configure.in configure.ac
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# aclocal
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 52
-rw-r--r-- 1 root root 37794 Aug 12 20:15 aclocal.m4
drwxr-xr-x 2 root root 4096 Aug 12 20:17 autom4te.cache
-rw-r--r-- 1 root root 0 Aug 12 20:02 autoscan.log
-rw-r--r-- 1 root root 529 Aug 12 20:14 configure.ac
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
autoheader是建立configure標頭檔案模板的操作,這一步執不執行與在configure.ac/configure.in中是否定義AC_CONFIG_HEADERS([config.h])有關,如果沒有定義就不需要執行,如果定義了就一定需要執行。
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# autoconf
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 188
-rw-r--r-- 1 root root 37794 Aug 12 20:15 aclocal.m4
drwxr-xr-x 2 root root 4096 Aug 12 20:35 autom4te.cache
-rw-r--r-- 1 root root 0 Aug 12 20:02 autoscan.log
-rwxr-xr-x 1 root root 137628 Aug 12 20:35 configure
-rw-r--r-- 1 root root 529 Aug 12 20:14 configure.ac
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
生成 configure (根據 configure.in, 和 aclocal.m4)
autoconf從configure.in這個列舉編譯軟體時所需要各種參數的 模板檔案中建立configure.
autoconf需要GNU m4宏處理器來處理aclocal.m4,生成configure指令碼.
m4是 一個宏處理器.將輸入拷貝到輸出,同時將宏展開.宏可以是 內嵌的 ,也可以是 使用者定義的 .除了可以展開宏,m4還有一些內建的 函數,用來參照檔案,執行命令,整數運算,文字操作,回圈等.m4既可以作爲編譯器的 前端,也可以單獨作爲一個宏處理器.
在這裏插入程式碼片
AUTOMAKE_OPTIONS= foreign
bin_PROGRAMS= helloworld
helloworld_SOURCES= helloworld.c
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# automake --add-missing
configure.ac:8: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see:
configure.ac:8: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_005fINIT_005fAUTOMAKE-invocation
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 216
-rw-r--r-- 1 root root 37794 Aug 12 20:15 aclocal.m4
drwxr-xr-x 2 root root 4096 Aug 12 20:41 autom4te.cache
-rw-r--r-- 1 root root 0 Aug 12 20:02 autoscan.log
-rwxr-xr-x 1 root root 137628 Aug 12 20:35 configure
-rw-r--r-- 1 root root 529 Aug 12 20:14 configure.ac
lrwxrwxrwx 1 root root 32 Aug 12 20:41 depcomp -> /usr/share/automake-1.13/depcomp
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
lrwxrwxrwx 1 root root 35 Aug 12 20:41 install-sh -> /usr/share/automake-1.13/install-sh
-rw-r--r-- 1 root root 84 Aug 12 20:43 Makefile.am
-rw-r--r-- 1 root root 22764 Aug 12 20:43 Makefile.in
lrwxrwxrwx 1 root root 32 Aug 12 20:41 missing -> /usr/share/automake-1.13/missing
./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
生成 Makefile, config.log, 和 config.status
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ll
total 284
-rw-r--r-- 1 root root 37794 Aug 12 20:15 aclocal.m4
drwxr-xr-x 2 root root 4096 Aug 12 20:41 autom4te.cache
-rw-r--r-- 1 root root 0 Aug 12 20:02 autoscan.log
-rw-r--r-- 1 root root 9022 Aug 12 20:53 config.log
-rwxr-xr-x 1 root root 29045 Aug 12 20:53 config.status
-rwxr-xr-x 1 root root 137628 Aug 12 20:35 configure
-rw-r--r-- 1 root root 529 Aug 12 20:14 configure.ac
lrwxrwxrwx 1 root root 32 Aug 12 20:41 depcomp -> /usr/share/automake-1.13/depcomp
-rw-r--r-- 1 root root 79 Aug 12 19:38 helloworld.c
lrwxrwxrwx 1 root root 35 Aug 12 20:41 install-sh -> /usr/share/automake-1.13/install-sh
-rw-r--r-- 1 root root 22828 Aug 12 20:53 Makefile
-rw-r--r-- 1 root root 84 Aug 12 20:43 Makefile.am
-rw-r--r-- 1 root root 22764 Aug 12 20:52 Makefile.in
lrwxrwxrwx 1 root root 32 Aug 12 20:41 missing -> /usr/share/automake-1.13/missing
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# make
gcc -DPACKAGE_NAME=\"FULL-PACKAGE-NAME\" -DPACKAGE_TARNAME=\"full-package-name\" -DPACKAGE_VERSION=\"VERSION\" -DPACKAGE_STRING=\"FULL-PACKAGE-NAME\ VERSION\" -DPACKAGE_BUGREPORT=\"BUG-REPORT-ADDRESS\" -DPACKAGE_URL=\"\" -DPACKAGE=\"helloworld\" -DVERSION=\"1.0\" -I. -g -O2 -MT helloworld.o -MD -MP -MF .deps/helloworld.Tpo -c -o helloworld.o helloworld.c
mv -f .deps/helloworld.Tpo .deps/helloworld.Po
gcc -g -O2 -o helloworld helloworld.o
[root@iZ2ze2y6fwj9mvujtsiya4Z helloAutoMake]# ./helloworld
Hello automake!