- 版本問題
- Auto Make 例子
- 新版的automake變化
- autotools系列工具作用
- 怎麼能讓automake生成的makefile裏面包含有我指定的庫
- 製作 configure 腳本
- 使用 automake
- autoconf手冊
- 利用libtool自動生成動態庫的Makefile的生成方法
- autoconf 和automake生成Makefile文件
- 幾個重要的宏
- 三種一般需求
版本問題
不同的automake,autoconf,autoscan之間存在着一定的不兼容性。這裏推薦 autoscan 2.59和 automake 1.9配合使用。如果你是debian或者ubuntu,那麼可你可以簡單按照下面的方式安裝
apt-get install autoconf apt-get remove automake1.4 apt-get install automake1.9
Auto Make 例子
現在google Makefile 和 automake就能找到一些文章。以一個Hello 程序描述爲一個project生成Makefile的過程。
這個例子其實在 Info automake 裏能看到。大家把它翻成中文的,不錯。
但實際上按照這個例子來做的話,步驟都對,就是太簡單,一些常用的設置需要寫進去,但是沒有提到,還是要自己info, google, try.
步驟總述
- autoscan 生成configure.scan .
- 在configure.scan基礎上手動編輯,主要要添加的 :
AM_INIT_AUTOMAKE(myprojectname , version) AC_OUTPUT( 最後要生成的Makefile , 包括 子目錄中的,中間用空格隔開) , 例如 AC_OUTPUT(Makefile subdir/Makefile subdir1/Makefile) AC_PROG_RANLIB (意義見第四條末尾)
- aclocal
- autoconf 生成configure腳本。
- 就是在每個最後需要生成Makefile的目錄中,寫一個Makefile.am .
最上層的要寫明
AUTOMAKE_OPTIONS = foreign
如果這個目錄沒有要編譯的文件 ,只包含了子目錄,則只寫個
SUBDIRS = dir1
就ok了。
例如我的工程,最上層只是包含了源碼目錄,於是就寫了
AUTOMAKE_OPTIONS=foreign SUBDIRS=src
如果有文件要編譯,則要指明target 先。比如我的src目錄底下既有文件,又有目錄,而src的這層目錄中的文件最後是要編譯成一個可執行文件,則src目錄下的Makefile.am這麼寫。
bin_PROGRAMS= myprogram SUBDIRS= sub1 myprogram_SOURCES= / a.cpp/ b.cpp/ # 要編譯的源文件。這兒的_SOURCES是關鍵字 EXTRA_DIST= / a.h / b.h # 不用編成.o,但生成target myprogram也需要給編譯器處理的頭文件放這裏 myprogram_LDADD = libsub1.a 這個_LDADD是關鍵字, # 最後生成myprogram這個執行文件,還要link src/sub1這個目錄中的內容編成的一個lib :libsub1.a, myprogram_LDFLAGS = -lpthread -lglib-2.0 -L/usr/bin $(all_libraries) # myprogram還要link系統中的動態so,以此類推,需要連自編譯的so,也寫到這個關鍵字 _LDFLAGS後面就好了。 AM_CXXFLAGS = -D_LINUX # 傳遞給g++編譯器的一些編譯宏定義,選項, INCLUDES=-IPassport -Isub1/ -I/usr/include/glib-2.0/ -I/usr/lib/glib-2.0/include $(all_includes) # 傳遞給編譯器的頭文件路徑。
下面是sub1種生成lib的Makefile.am
noinst_LIBRARIES = libprotocol.a # 不是生成可執行文件,而是靜態庫,target用noinst_LIBRARIES libprotocol_a_SOURCES = / alib.cpp EXTRA_DIST = mylib.h/ alib.h INCLUDES= -I../ $(all_includes) AM_CXXFLAGS = -D_LINUX -DONLY_EPOLL -D_SERVER
ok ,最後補上AC_PROG_RANLIB涵義,如果要自己生成lib,然後link到最終的可執行文件中,則要加上這個宏,否則不用。
[討論] 每個目錄至少都要有一個target,或者是可執行文件或者是lib,似乎對目錄的劃分帶來點侷限。
比如我的目錄結構如果是這樣
./Src ./Src/sub1 ./Src/sub2
而我想這樣,sub1,sub2都沒有target,目錄劃分只是爲了區別代碼的不同模塊,然後把兩個目錄中編譯出的中間文件一起link ,得到最後需要的 myprogram 。
似乎在Src/Makefile.am中要這麼寫
myprogram_SOURCES = sub1/a.cpp / sub2/b.cpp
可以實現,但我沒試,:P
當然和設成先編譯出libsub1.a libsub2.a 最後Link得到myprogram 沒有本質區別了。
- automake --add-missing
Ok , Makefile.in應該放到各個目錄下了。
- 最後,運行configure腳本,生成 各個目錄下的Makefile .......
- 再最後 ,make .......
新版的automake變化
軟件版本間的不兼容總是會帶來不少麻煩。
首先我對比了網上的一些文章和gnu的autoconf文檔,發現差別很大,新版本和老版本有很多不同,當然大部分特性新版本還是兼容老版本的,令人鬱悶的是automake的文檔中對configure.in的描述還是針對autoconf老版本的。
軟件版本: autoscan 2.59 automake 1.9.5 參考文檔: automake 1.7.8 doc http://www.gnu.org/software/automake/manual/html_node/ autoconf 2.59 doc http://www.gnu.org/software/autoconf/manual/
- 建立程序:
cd ~/src mkdir hello 編輯文件hello.c
- 運行autoscan,產生錯誤: autom4te: configure.ac: no such file or directory
不予理會,生成了文件configure.scan
cp configure.scan configure.ac
修改configure.ac的內容如下:
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(hello, 1.0, [email protected]) AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE(hello,1.0) AC_CONFIG_HEADER([config.h]) # 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_CONFIG_FILES([Makefile]) AC_OUTPUT
這裏說明一下的是,老版本的autotools使用configure.in作爲輸入,後來新版本改爲configure.ac,但configure.in也可以。
- 運行aclocal,生成文件aclocal.m4
- 運行autoheader,聲稱文件config.h.in
- 編輯文件Makefile.am 內容如下:
bin_PROGRAMS = hello hello_SOURCES = hello.c
- 運行automake --add-missing,提示少了文件README NEWS AUTHORS ChangeLog
touch README NEWS AUTHORS ChangeLog 建立這些文件
- 再次運行automake --add-missing [注意] 若在Makefile.am中加上AUTOMAKE_OPTIONS= foreign 則不會提示缺少文件。
- 運行autoconf, 生成了configure腳本
- 執行./configure,生成Makefile
- 運行make,編譯通過。
autotools系列工具作用
1.autoscan (autoconf): 掃描源代碼以搜尋普通的可移植性問題,比如檢查編譯器,庫,頭文件等,生成文件configure.scan,它是configure.ac的一個雛形。
2.aclocal (automake):根據已經安裝的宏,用戶定義宏和acinclude.m4文件中的宏將configure.ac文件所需要的宏集中定義到文件 aclocal.m4中。aclocal是一個perl 腳本程序,它的定義是:“aclocal - create aclocal.m4 by scanning configure.ac”
user input files optional input process output files ================ ============== ======= ============ acinclude.m4 - - - - -. V .-------, configure.in ------------------------>|aclocal| {user macro files} ->| |------> aclocal.m4 `-------' 3.autoheader(autoconf): 根據configure.ac中的某些宏,比如cpp宏定義,運行m4,聲稱config.h.in user input files optional input process output files ================ ============== ======= ============ aclocal.m4 - - - - - - - . (acconfig.h) - - - -. | V V .----------, configure.in ----------------------->|autoheader|----> config.h.in `----------'
4.automake: automake將Makefile.am中定義的結構建立Makefile.in,然後configure腳本將生成的Makefile.in文件轉換爲Makefile。如果在configure.ac中定義了一些特殊的宏,比如AC_PROG_LIBTOOL,它會調用libtoolize,否則它會自己產生config.guess和config.sub
user input files optional input processes output files ================ ============== ========= ============ .--------, | | - - -> COPYING | | - - -> INSTALL | |------> install-sh | |------> missing |automake|------> mkinstalldirs configure.in ----------------------->| | Makefile.am ----------------------->| |------> Makefile.in | |------> stamp-h.in .---+ | - - -> config.guess | | | - - -> config.sub | `------+-' | | - - - -> config.guess |libtoolize| - - - -> config.sub | |--------> ltmain.sh | |--------> ltconfig `----------'
5.autoconf:將configure.ac中的宏展開,生成configure腳本。這個過程可能要用到aclocal.m4中定義的宏。
user input files optional input processes output files ================ ============== ========= ============ aclocal.m4 - - - - - -. V .--------, configure.in ----------------------->|autoconf|------> configure `--------'
References: http://sourceware.org/autobook/autobook/autobook_276.html
怎麼能讓automake生成的makefile裏面包含有我指定的庫
INCLUDES = -I/include LIBS = -lm -lcrypt
製作 configure 腳本
autoconf 是用來生成自動配置軟件源代碼腳本(configure)的工具。configure 腳本獨立於 autoconf 運行,而且在運行的過程中,不需要用戶的干預,通常不需要附帶參數。它是用來檢驗軟件必須的參數的。autoconf 從一個列舉編譯軟件時所需要各種參數的模板文件中創建 configure。autoconf 需要 GNU m4 來生成該腳本。
由 autoconf 生成的腳本一般起名爲 configure。當運行時,configure 創建了多個文件,並對這些文件中的配置參數賦予適當的值。由 configure 創建生成的文件有:
- 一個或多個 Makefile,在軟件源代碼的每個目錄中都生成一個 Makefile。
- 還可選的生成 C 頭文件——configurable,包含了各種 #define 聲明。
- 一個名爲 config.status 的腳本,當運行時,重新生成上面的文件。
- 一個名爲 config.cache 的腳本,保存運行檢測的結果。
- 一個名爲 config.log 的文件,保存有編譯器生成的信息,用於調試 configure。
爲了讓 autoconf 生成 configure 腳本,需要以 configure.in 爲參數調用 autoconf。如果要檢測自己的各種參數,以作爲對 autoconf 的補充,則需要寫 aclocal.m4 和 acsite.m4 的文件。如果要使用 C 頭文件,需要寫 acconfig.h,並且將 autoconf 生成的 config.h.in 同軟件一起發行。
your source files --> [autoscan*] --> [configure.scan] --> configure.in configure.in --. .------> autoconf* -----> configure +---+ [aclocal.m4] --+ `---. [acsite.m4] ---' | +--> [autoheader*] -> [config.h.in] [acconfig.h] ----. | +-----' [config.h.top] --+ [config.h.bot] --' Makefile.in -------------------------------> Makefile.in Files used in configuring a software package: .-------------> config.cache configure* ------------+-------------> config.log | [config.h.in] -. v .-> [config.h] -. +--> config.status* -+ +--> make* Makefile.in ---' `-> Makefile ---'
編輯 configure.in 文件:
configure.in 文件中包含了對 autoconf 宏的調用,這些宏是用來檢測軟件所必須的各項參數的。爲了能夠得到 configure.in 文件,需要使用 autoscan。 configure.in 文件中,在進行各項檢測前,必須在最開始調用 AC_INIT,在最後調用 AC_OUTPUT。另外有些宏由於檢測的關係是和在文件中的位置相關的。最好每一個宏佔用一行。
使用 autoscan 創建 configure.in 文件
可以將目錄做爲參數調用 autoscan,如果不使用參數的化,則認爲是當前目錄。 autoscan 將檢查指定目錄中的源文件,並創建 configure.scan 文件。在將 configure.scan 改名爲 configure.in 文件前,需要手工改動它以進行調整。
使用 autoconf 創建 configure 腳本
不帶任何參數的運行 autoconf。autoconf 將使用 m4 宏處理器和 autoconf 宏,來處理處理 configure.in 中的宏。
configure.in 中的宏:
AC_INIT(在源代碼中唯一的一個文件):configure 將檢查該文件是否存在,並檢查包含它的目錄是否存在。 AC_OUTPUT(文件):指定創建的輸出文件。在 configure.in 文件中調用一次。文件名間用空格分開。比如:AC_OUTPUT(Makefile:templates/top.mk lib/Makefile:templates/lib.mk)
在 configure.in 中,有一些被 autoconf 宏預先定義的變量,重要的有如下幾個:
bindir:安裝可執行文件的目錄。 includedir:C 頭文件目錄。 infodir:info 頁安裝目錄。 mandir:安裝手冊頁的目錄。 sbindir:爲管理員運行該該程序提供的安裝路徑。 srcdir:爲 Makefile 提供的源代碼路徑。 top_srcdir:源代碼的最上層目錄。 LIBS:給連接程序的 -l 選項 LDFLAGS:給連接程序的 stripping(-s)和其他一些選項。 DEFS:給 C 編譯器的 -D 選項。 CFLAGS:給 C 編譯器的 debug 和優化選項。當調用了 AC_PROG_CC 纔有效。 CPPFLAGS:頭文件搜索路徑(-I)和給 C 預處理器和編譯器的其他選項。 CXXFLAGS:給 C++ 編譯器的 debug 和優化選項。當調用了 AC_PROG_CXX 纔有效。
如果在同一個目錄下編譯多個程序的話,使用 AC_CONFIG_SUBDIRS 宏,它的語法是:
AC_CONFIG_SUBDIRS(DIR....):
其他重要的宏:
AC_PROG_CC:選擇 C 編譯器。如果在環境中不設置 CC 的話,則檢測 gcc。 AC_PROG_CXX:選擇 C++ 編譯器。
使用 automake
一般操作 Automake 工作時,讀取一個叫'Makefile.am'的文件,並生成一個'Makefile.in'文件。Makefile.am中定義的宏和目標,會指導 automake生成指定的代碼。例如,宏'bin_PROGRAMS'將導致編譯和連接的目標被生成。 Makefile.am中包含的目標和定義的宏被拷貝到生成的文件中去,這允許你添加任意代碼到生成的Makefile.in文件中去。例如,使一個Automake發佈中包含一個非標準的dvs-dist目標,Automake的維護者用它來從它的源碼控制系統製作一個發佈。 請注意,GNU生成的擴展名不被Automake所識別,在一個'Makefile.am'中使用這樣一個擴展名會導致錯誤。 Automake試圖以一種聰明的方式將相鄰的目標(或變量定義)註釋重組。 通常,Makefile.am中定義的目標會覆蓋任何由automake自動生成的有相似名字的這樣的目標。儘管這是種被支持的屬性,但最好避免這麼做,因爲有些時候,生成的規則很嚴格。 類似的,Makefile.am中定義的變量會覆蓋任何由automake自動生成的變量定義。這一特性經常要比目標定義的覆蓋能力更常用。請注意,很多automake生成的變量只用於內部使用,在將來發布時他們的名字可能會變化。 當測試一個變量定義時,Automake降遞歸的測試在定義中引用的變量。例如,如果Automake看到這段snippet程序中的'foo_SOURCES': xs = a.c b.c foo_SOURCES = c.c $(xs) 它將使用文件:'a.c','b.c'和'c.c' 作爲foo_SOURCES的內容. Automake 也允許不被拷貝到輸出的註釋形式,所有以'##'開頭的行將被Automake 完全忽略. 深度 Automake 支持三種目錄層次:'flat', 'shallow', 'deep'. flat: 所有的文件都在一個目錄中. 相應的Makefile.am中缺少SUBDIRS宏. termutils 是一個例子. deep: 所有的資源都在子目錄中,指定曾目錄主要包含配置信息.GNU cpio 是一個很好的例子.GNU tar.相應的最頂層Makefile.am中將包含一個SUBDIR宏,但沒有其他的宏來定義要創建的對象. shallow: 主資源存在於最頂層目錄,而不同的部分(典型的,庫函數)在子目錄中.Automake 就是這樣的一個包. 嚴格性 當Automake 被GNU包維護者使用時,它的確努力去適應,但不要試圖使用所有的GNU慣例. 目前,Automake 支持三種嚴格性標準: foreign:Automake 將只檢查絕對必須的東西. gnu:Automake 將儘可能多的檢查以適應GNU標準, 這是默認項. gnits:Automake 將進行檢查,以適應“尚未成文”的Gnits標準。 他們基於GNU標準,但更詳盡。除非您是Gnits標準的制定者。建議您最好避免這個選項,指導該標準正式發佈。 統一命名規範 Automake變量一般遵循一套統一的命名規範以很容易的決定如何創建和安裝程序(和其他派生對象)。給規範還支持configure時動態決定創建規則。 在make時,一些變量被用於決定那些對象要被創建。寫變量叫做primary variables。例如,PROGRAM變量包括一個要被編譯和連接的程序列表。 另一個變量集用於決定被創建變量被安裝到哪裏。這些變量以相應的主變量命名,但加一個前綴,表示那些標準目錄應被用作安裝路徑。這些標準目錄的名稱規定在GNU標準中。Automake用pkglibdir, pkgincludedir 和 pkgdatadir來展開這一列表。他們和沒有pkg前綴的版本一樣,只不過有‘@PACHAGE@’擴展,PKGLIBDIR被定義爲 $(DATADIR)/@PACKAGE@. 對每一個主變量,有一個EXTRA_前綴的變量。這個變量用於列出所有對象,至於哪些變量被創建,哪些變量不被創建則取決於 configure。之所以需要這個變量,是因爲Automake必須靜態的指導要創建對象的完整列表以便生成一個‘Makefile。in’文件。 例如,cpio 在configure時決定創建那些程序。一些程序被安裝在bindir,一些被安裝在sbindir: EXTRA_PROGRAMS = mt rmt bin_PROGRAMS = cpoi pax sbin_PRGRAMS = @PROGRAMS@ 定義沒有前綴的主變量是錯誤的(如:PROGRAMS)。值得注意的是,“dir”在作爲構成變量名時會被忽略。一次,我們寫成bin_PROGRAMS 而不是bindir_PROGRAMS. 不是每一種對象都得以安裝在每個目錄下。Automake 將標記那些他認爲是錯誤的嘗試,他也能夠診斷一些明顯的目錄名拼寫錯誤。 有時標準目錄--被Automake使用的--不過用。特別的,有時爲了清晰,將對象安裝在一些預定義的子目錄,是很有用的。 Automake允許你增加安裝目錄。如果以一個變量名(如,zar)加上dir的另一個變量(如,zardir)被定義了,那麼他也是合法的。 例如,如果HTML沒支持Automake的一下部分,你就可以用他來安裝HTML源文件: htmldir = $(prefix)/html html_DATA = automake.html “noinst”前綴專門指定有問題的對象不被安裝。 “check”前綴表示有問題的對象知道make check命令被執行猜被創建。 可用的主變量是 'PROGRAMS','LIBRARIES','LISP','SCRIPTS','DATA','HEADERS','MANS'和'TEXINFOS' 導出變量是如何命名的 有時一個Makefile變量名有一些用戶支持的文本導出。例如程序名被重寫進Makefile宏名稱。Automake讀取這些文本,所以他不必遵循命名規則。當生成後引用時名稱中的字符除了字母,數字,下劃線奪回被轉換爲下劃線。例如,如果你的程序裏有sniff-glue,則導出變量名將會是sniff_glue_SOURCES,而不是sniff-glue_SOURCES. 一些例子 一個完整簡單的例子 假設你寫了一個名爲zardoz的程序。 第一步,更新你的configure.in文件以包含automake所需的命令。最簡單的辦法就是在AC_INIT後加一個AM_INIT_AUTOMAKE調用: AM_INIT_AUTOMAKE(zardoz, 1.0) 如果你的程序沒有任何複雜的因素。這是最簡單的辦法。 現在,你必須重建‘configure’文件。這樣做,你必須告訴autoconf如何找到你所用的新宏。最簡單的方式是使用 aclocal程序來 生成你的‘aclocal.m4’.aclocal讓你將你的宏加進‘acincluide.m4’,所以你只需重命名並運行他 mv aclocal.m4 acinclude.m4 aclocal autoconf 現在是爲你的zardoz寫Makefile.am的時候了。zardoz是一個用戶程序,所以逆向將他安裝在其他用戶程序安裝的目錄。zardoz還有一些Texinfo文檔。你的configure.in腳本使用AC_REPLACE_FUNCS,所以你需要鏈接‘@LIBOBJS@’ bin_PROGRAMS = zardoz zardoz_SOURCES = main.c head.c float.c vortex9.c gun.c zardoz_LDADD = @LIBOBJS@ info_TEXINFOS = zardoz.texi 現在你可以運行Automake以生成你的Makefile.in文件。 一個經典的程序 hello 以其簡單和多面幸而聞名。着一段將顯示在Hello包Automake如何被使用。 下面是 dnl用 autoconf 處理它以產生一個 configure 腳本. AC_INIT(src/hello.c) AM_INIT_AUTOMAKE(hello, 1.3.11) AM_CONFIG_HEADER(config.h) dnl Set of available languages ALL_LINGUAS="de fr es ko nl no pl pt sl sv" dnl Checks for programs. AC_PROG_CC AC_ISC_POSIX dnl Checks for libraries. dnl Checks for header files. AC_STDC_HEADERS AC_HAVE_HEADERS(string.h fcntl.h sys/file.h sys/param.h) dnl Checks for library functions. AC_FUNC_ALLOCA dnl Check for st_blksize in struct stat AC_ST_BLKSIZE dnl internationalization macros AM_GNU_GETTEXT AC_OUTPUT([Makefile doc/Makefile intl/Makefile po/Makefile.in / src/Makefile tests/Makefile tests/hello], [chmod +x tests/hello]) 'AM_'宏由Automake(或Gettext 庫)提供;其餘的是Autoconf標準宏。 top-level ‘Makefile.am’: EXTRA_DIST = BUGS ChangeLog.O SUBDIRS = doc intl po src tests --如你所見,這裏所有的工作時在子目錄中真正完成的. --'po' 和 'intl'目錄是用 gettextize自動生成的,這裏不做進一步討論. 在'doc/Makefile.am'文件中我們看到: info_TEXINFOS = hello.texi hello_TEXINFOS = gpl.texi --這已足以創建,安裝和發佈手冊. 這裏是'tests/Makefile.am'文件: TESTS = hello EXTRA_DIST = hello.in testdata --腳本'hello'被configure創建,並且是唯一的測試.make check將運行它. 最後是,'src/Makefile.am',所有的真正的工作是在這裏完成的: bin_PROGRAMS = hello hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h hello_LDADD = @INTLLIBS@ @ALLOCA@ localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=/"$(localedir)/" 創建一個'Makefile.in'文件 要爲一個包創建所有的'Makefile.in',在頂層目錄運行automake不帶參數的程序.automake將自動查找每個適當的'Makefile.am'文件,並聲稱相應的'Makefile.in'文件.請注意,automake會簡要的察看一下包的構成;它假定一個包在頂層只有一個'configure.in'文件.如果你的包有多個'configure.in'文件,那麼你必須在每一個含有 'configure.in'文件的目錄運行一次'automake'程序. 你可以隨意送給automake一個參數;'.am'會加到變量名的後面,並且作爲輸入文件的文件名.這一特性通常被用來自動重建一個'過時的''Makefile.in'文件.注意,automake必須在最頂級的目錄運行,及時僅僅爲了重新生成某個子目錄中的 'Makefile.in'文件. automake接受以下可選參數: -a --add-missing 在某些特殊情況下,Automake需要某些公共文件存在.例如,如果'configure.in'運行 AC_CANONICAL_HOST時,就需要'config.guess'.Automake需要幾個這樣的文件,這一選項會讓automake自動的將一些缺失文件加進包中(如果可能的話).一般的,如果Automake告訴你某個文件不存在,你可以試一試這個選項. --amdir = dir 在dir所制定的目錄而不是安裝目錄下尋找Automake的數據文件,經常用於調試. --build-dir = dir 告訴Automake創建目錄在哪裏.這一選項只用於將'dependencies'加進一個由make dist生成的'Makefile.in'文件中. --cygnus 將使得所生成的'Makefile.in'文件遵循Cygnus規則,而不是GNU或Gnits規則. --foreign 設置全局嚴格性爲'gnits'. --gnu 設置全局嚴格性爲'gnu'. --help 幫助 -i --include-deps 將所有自動創建時的依賴信息包括在'Makefile.in'中.通常在製作發行時用到. --generate-deps 創建一個'.dep_segment'文件,它合併了所有的自動生成時的依賴信息,通常用於製作發行.這在維護'SMakefile'或其他平臺上的'Makefile'(如Makefile.Dos)時非常有用.它只能與--include-deps, --srcdir-name和 --build-dir 聯合使用.注意這一選項不作其他任何處理. --no-force 一般的,automake創建在'configure.in'中提及的所有'Makefile.in'文件.這一選項將導致,automake只更新那些對於與自身相關的東西過了時的'Makefile.in'文件. -o dir --output-dir = dir 將生成的'Makefile.in'放在指定的dir目錄中.通常,'Makefile.in'放在與之相對應的'Makefile.am'所在目錄中的.在製作發佈時使用. --srcdir-name = dir 告訴Automake與當前創建動作相關的源文件目錄的名字.個選項僅被用於將自動創建時的依賴信息包括在'Makefile.in'中. -v --verbose 時Automake打印出正在讀取或創建的文件的信息. --version 打印Automake的版本號. 掃描'configure.in'文件 Automake掃描包的'configure.in'文件來決定某些關於包的信息.'configure.in'中必須定義一些變量並且需要一些autoconf 宏.Automake也會利用'configure.in'文件的信息來定製它的輸出. Automake還支持一些autoconf宏以使維護更爲簡單. 配置需求 滿足Automake基本要求的最簡單方法是使用'AM_INIT_AUTOMAKE'宏.但如果你願意,你可以手工來做. 自動生成 aclocale.m4 Automake包括很多Autoconf宏,其中有些在某些情況下游Automake使用,這些宏必須被定義在你的'aclocal.m4'中.否則,autoconf將看不到他們. acloal程序將根據'configure.in'自動生成'aclocal.m4'.這提供了一個方便的途徑來得到Automake提供的宏. Automake所支持的Autoconf宏 AM_CONFIG_HEADER AM_CYGWIN32 AM_FUNC_STRTOD AM_FUNC_ERROR_AT_LINE AM_FUNC_MKTIME AM_FUNC_OBSTACK AM_C_PROTOTYPES AM_HEADER_TOCGWINSZ_NEEDS_SYS_IOCTL AM_INIT_AUTOMAKE AM_PATH_LISPDIR AM_PROG_CC_STDC AM_PROG_INTALL AM_PROG_LEX AM_SANITY_CHECK AM_SYS_POSIX_TERMIOS AM_TYPE_PTRDIFF_T AM_WITH_DMALLOC AM_WITH_REGEX 編寫你自己的aclocal宏 Aclocal並沒有特定的宏機制,因此你可以用你自己的宏來擴展它.這以特性經常被用以製作做那些想讓自己的Autoconf宏被其他應用程序使用的庫.例如,gettext庫支持一個AM_GNU_GETTEXT宏,它可以被任何使用gettext庫的包所使用.當該庫被安裝後,它會安裝這個宏,這樣,aclocal就能夠找到他了. 宏的名稱應以'.m4'結尾,這樣的文件將被安裝在'$(datadir)/aclocal'中. 最頂層'Makefile.am' 在non-flat包中,頂層'Makefile.am'必須告訴Automake哪些子目錄將被創建.這是通過SUBDIRS變量定義的. SUBDIRS宏包含一個子目錄列表,以規定各種創建的過程.'Makefile'中很多目標(如,all)將不止運行所在目錄中,還要運行於所有指定的子目錄中.注意,在SUBDIRS中列出的目錄並不需要包含'Makefile.am'文件而只需要'Makefile'文件. 這將允許包含位於不使用Automake的包(如,gettext)中的庫.另外,SUBDIRS之中的目錄必須是當前目錄的直接子目錄.比如,你不能在 SUBDIRS中指定'src/subdir'. 在deep型的包中,頂層'Makefile.am'文件通常非常短.例如,下面是HELLO發佈中的'Makefile.am': EXTRA_DIST = BUGS ChangeLog.O README-alpha SUBDIRS = doc intl po src tests 如果你只想創建一個包的子集,你可以覆蓋SUBDIRS(就如同GNU inetutils的情形)在你的'Makefile.am'中包括: SUBDIRS = @SUBDIRS@ 讓後在你的'configure.in'中你可以指定: SUBDIRS = "src doc lib po" AC_SUBST(SUBDIRS) 這樣做的結果是automake被欺騙了,它會在指定目錄創建包,但並不真正綁定那個列表直到運行configure. SUBDIRS可以包含配置的替代(如,'@DIRS@');Automake 自己並不真正檢測這一變量的內容. 如果 SUBDIRS 被定義了,那麼你的'configure.in' 就必須包含AC_PROG_MAKE_SET. SUBDIRS 的使用並不侷限於頂層'Makefile.am'.Automake 可被用來構造任意深度的包. 參考文獻 Automake.htm
autoconf手冊
對普通函數的檢查 這些宏被用於尋找沒有包括在特定函數測試宏中的函數。如果函數可能出現在除了缺省C庫以外的庫中,就要首先爲這些庫調用AC_CHECK_LIB。如果你除了需要檢查函數是否存在之外,還要檢查函數的行爲,你就不得不爲此而編寫你自己的測試(參見編寫測試)。 宏: AC_CHECK_FUNC (function, [action-if-found [, action-if-not-found]]) 如果可以使用C函數function,就運行shell命令action-if-found,否則運行 action-if-not-found。如果你只希望在函數可用的時候定義一個符號,就考慮使用 AC_CHECK_FUNCS。由於C++比C更加標準化,即使在調用了AC_LANG_CPLUSPLUS 的時候,本宏仍然用C的連接方式對函數進行檢查。(關於爲測試選擇語言的詳情,請參見 對語言的選擇) 宏: AC_CHECK_FUNCS (function... [, action-if-found [, action-if-not-found]]) 對於每個在以空格分隔的函數列表function中出現的函數,如果可用,就定義HAVE_function (全部大寫)。如果給出了action-if-found,它就是在找到一個函數的時候執行的附加的shell代碼。你可以給出 `break'以便在找到第一個匹配的時候跳出循環。如果給出了action-if-not-found,它就在找不到某個函數的時候執行。 宏: AC_REPLACE_FUNCS (function...) 本宏的功能就類似於以將`function.o'添加到輸出變量LIBOBJS的shell 代碼爲參數action-if-not-found,調用AC_CHECK_FUNCS。你可以通過用 `#ifndef HAVE_function'包圍你爲函數提供的替代版本的原型來聲明函數。如果系統含有該函數,它可能在一個你應該引入的頭文件中進行聲明,所以你不應該重新聲明它,以避免聲明衝突。 頭文件 下列宏檢查某些C頭文件是否存在。如果沒有爲你需要檢查的頭文件定義特定的宏,而且你不需要檢查它的任何特殊屬性,那麼你就可以使用一個通用的頭文件檢查宏。 對特定頭文件的檢查 這些宏檢查特定的系統頭文件--它們是否存在,以及在某些情況下它們是否定義了特定的符號。 宏: AC_DECL_SYS_SIGLIST 如果在系統頭文件,`signal.h'或者`unistd.h',中定義了變量sys_siglist,就定義SYS_SIGLIST_DECLARED。 宏: AC_DIR_HEADER 類似於調用AC_HEADER_DIRENT和AC_FUNC_CLOSEDIR_VOID,但爲了指明找到了哪個頭文件而定義了不同的一組C預處理器宏。本宏和它定義的名字是過時的。它定義的名字是: `dirent.h' DIRENT `sys/ndir.h' SYSNDIR `sys/dir.h' SYSDIR `ndir.h' NDIR 此外,如果closedir不能返回一個有意義的值,就定義VOID_CLOSEDIR。 宏: AC_HEADER_DIRENT 對下列頭文件進行檢查,並且爲第一個找到的頭文件定義`DIR',以及列出的C預處理器宏: `dirent.h' HAVE_DIRENT_H `sys/ndir.h' HAVE_SYS_NDIR_H `sys/dir.h' HAVE_SYS_DIR_H `ndir.h' HAVE_NDIR_H 源代碼中的目錄庫聲明應該以類似於下面的方式給出: #if HAVE_DIRENT_H # include # define NAMLEN(dirent) strlen((dirent)->d_name) #else # define dirent direct # define NAMLEN(dirent) (dirent)->d_namlen # if HAVE_SYS_NDIR_H #include # endif # if HAVE_SYS_DIR_H #include # endif # if HAVE_NDIR_H #include # endif #endif 使用上述聲明,程序應該把變量定義成類型struct dirent,而不是struct direct,並且應該通過把指向struct direct的指針傳遞給宏NAMLEN來獲得目錄項的名稱的長度。 本宏還爲SCO Xenix檢查庫`dir'和`x'。 宏: AC_HEADER_MAJOR 如果`sys/types.h'沒有定義major、minor和makedev,但`sys/mkdev.h'定義了它們,就定義MAJOR_IN_MKDEV;否則,如果`sys/sysmacros.h'定義了它們,就定義MAJOR_IN_SYSMACROS。 宏: AC_HEADER_STDC 如果含有標準C(ANSI C)頭文件,就定義STDC_HEADERS。特別地,本宏檢查`stdlib.h'、`stdarg.h'、`string.h'和 `float.h';如果系統含有這些頭文件,它可能也含有其他的標準C頭文件。本宏還檢查`string.h'是否定義了memchr (並據此對其他mem函數做出假定),`stdlib.h'是否定義了free(並據此對malloc和其他相關函數做出假定),以及`ctype.h' 宏是否按照標準C的要求而可以用於被設置了高位的字符。 因爲許多含有GCC的系統並不含有標準C頭文件,所以用STDC_HEADERS而不是__STDC__ 來決定系統是否含有服從標準(ANSI-compliant)的頭文件(以及可能的C庫函數)。 在沒有標準C頭文件的系統上,變種太多,以至於可能沒有簡單的方式對你所使用的函數進行定義以使得它們與系統頭文件聲明的函數完全相同。某些系統包含了 ANSI和BSD函數的混合;某些基本上是標準(ANSI)的,但缺少`memmove';有些系統在`string.h'或者`strings.h'中以宏的方式定義了BSD函數;有些系統除了含有`string.h'之外,只含有BSD函數;某些系統在`memory.h' 中定義內存函數,有些在`string.h'中定義;等等。對於一個字符串函數和一個內存函數的檢查可能就夠了;如果庫含有這些函數的標準版,那麼它就可能含有其他大部分函數。如果你在`configure.in' 中安放了如下代碼: AC_HEADER_STDC AC_CHECK_FUNCS(strchr memcpy) 那麼,在你的代碼中,你就可以像下面那樣放置聲明: #if STDC_HEADERS # include #else # ifndef HAVE_STRCHR #define strchr index #define strrchr rindex # endif char *strchr (), *strrchr (); # ifndef HAVE_MEMCPY #define memcpy(d, s, n) bcopy ((s), (d), (n)) #define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif 如果你使用沒有等價的BSD版的函數,諸如memchr、memset、strtok 或者strspn,那麼僅僅使用宏就不夠了;你必須爲每個函數提供一個實現。以memchr爲例,一種僅僅在需要的時候(因爲系統C庫中的函數可能經過了手工優化)與你的實現協作的簡單方式是把實現放入 `memchr.c'並且使用`AC_REPLACE_FUNCS(memchr)'。 宏: AC_HEADER_SYS_WAIT 如果`sys/wait.h'存在並且它和POSIX.1相兼容,就定義HAVE_SYS_WAIT_H。如果`sys/wait.h'不存在,或者如果它使用老式BSD union wait,而不是 int來儲存狀態值,就可能出現不兼容。如果`sys/wait.h'不與POSIX.1兼容,那就不是引入該頭文件,而是按照它們的常見解釋定義 POSIX.1宏。下面是一個例子: #include #if HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif 宏: AC_MEMORY_H 在`string.h' 中,如果沒有定義memcpy, memcmp等函數,並且`memory.h' 存在,就定義NEED_MEMORY_H。本宏已經過時;可以用AC_CHECK_HEADERS(memory.h)來代替。參見爲 AC_HEADER_STDC提供的例子。 宏: AC_UNISTD_H 如果系統含有`unistd.h',就定義HAVE_UNISTD_H。本宏已經過時;可以用 `AC_CHECK_HEADERS(unistd.h)'來代替。 檢查系統是否支持POSIX.1的方式是: #if HAVE_UNISTD_H # include # include #endif #ifdef _POSIX_VERSION /* Code for POSIX.1 systems.*/ #endif 在POSIX.1系統中包含了`unistd.h'的時候定義_POSIX_VERSION。如果系統中沒有`unistd.h',那麼該系統就一定不是POSIX.1系統。但是,有些非POSIX.1(non-POSIX.1)系統也含有`unistd.h'。 宏: AC_USG 如果系統並不含有`strings.h'、rindex、bzero等頭文件或函數,就定義USG。定義USG就隱含地表明瞭系統含有`string.h'、strrchr、memset等頭文件或函數。 符號USG已經過時了。作爲本宏的替代,參見爲AC_HEADER_STDC提供的例子。 對普通頭文件的檢查 這些宏被用於尋找沒有包括在特定測試宏中的系統頭文件。如果你除了檢查頭文件是否存在之外還要檢查它的內容,你就不得不爲此而編寫你自己的測試(參見編寫測試)。 宏: AC_CHECK_HEADER (header-file, [action-if-found [, action-if-not-found]]) 如果系統頭文件header-file存在,就執行shell命令action-if-found,否則執行action-if-not-found。如果你只需要在可以使用頭文件的時候定義一個符號,就考慮使用 AC_CHECK_HEADERS。 宏: AC_CHECK_HEADERS (header-file... [, action-if-found [, action-if-not-found]]) 對於每個在以空格分隔的參數列表header-file出現的頭文件,如果存在,就定義 HAVE_header-file(全部大寫)。如果給出了action-if-found,它就是在找到一個頭文件的時候執行的附加shell代碼。你可以把`break'作爲它的值以便在第一次匹配的時候跳出循環。如果給出了action-if-not-found,它就在找不到某個頭文件的時候被執行。 結構 以下的宏檢查某些結構或者某些結構成員。爲了檢查沒有在此給出的結構,使用AC_EGREP_CPP (參見檢驗聲明)或者使用AC_TRY_COMPILE (參見檢驗語法)。 宏: AC_HEADER_STAT 如果在`sys/stat.h'中定義的S_ISDIR、S_ISREG等宏不能正確地工作(返回錯誤的正數),就定義 STAT_MACROS_BROKEN。這種情況出現在Tektronix UTekV、 Amdahl UTS和Motorola System V/88上。 宏: AC_HEADER_TIME 如果程序可能要同時引入`time.h'和`sys/time.h',就定義 TIME_WITH_SYS_TIME。在一些老式系統中,`sys/time.h'引入了`time.h',但`time.h'沒有用多個包含保護起來,所以程序不應該顯式地同時包含這兩個文件。例如,本宏在既使用struct timeval或 struct timezone,又使用struct tm程序中有用。它最好和 HAVE_SYS_TIME_H一起使用,該宏可以通過調用AC_CHECK_HEADERS(sys/time.h)來檢查。 #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H #include # else #include # endif #endif 宏: AC_STRUCT_ST_BLKSIZE 如果struct stat包含一個st_blksize成員,就定義HAVE_ST_BLKSIZE。 宏: AC_STRUCT_ST_BLOCKS 如果struct stat包含一個st_blocks成員,就定義HAVE_ST_BLOCKS。否則,就把`fileblocks.o'添加到輸出變量LIBOBJS中。 宏: AC_STRUCT_ST_RDEV 如果struct stat包含一個st_rdev成員,就定義HAVE_ST_RDEV。 宏: AC_STRUCT_TM 如果`time.h'沒有定義struct tm,就定義TM_IN_SYS_TIME,它意味着引入`sys/time.h'將得到一個定義得更好的struct tm。 宏: AC_STRUCT_TIMEZONE 確定如何獲取當前的時區。如果struct tm有tm_zone成員,就定義HAVE_TM_ZONE。否則,如果找到了外部數組tzname,就定義HAVE_TZNAME。 類型定義 以下的宏檢查C typedefs。如果沒有爲你需要檢查的typedef定義特定的宏,並且你不需要檢查該類型的任何特殊的特徵,那麼你可以使用一個普通的typedef檢查宏。 對特定類型定義的檢查 這些宏檢查在`sys/types.h'和`stdlib.h'(如果它存在)中定義的特定的C typedef。 宏: AC_TYPE_GETGROUPS 把GETGROUPS_T定義成getgroups的數組參數的基類型gid_t或者int。 宏: AC_TYPE_MODE_T 如果沒有定義mode_t,就把mode_t定義成int。 宏: AC_TYPE_OFF_T 如果沒有定義off_t,就把off_t定義成long。 宏: AC_TYPE_PID_T 如果沒有定義pid_t,就把pid_t定義成int。 宏: AC_TYPE_SIGNAL 如果`signal.h'把signal聲明成一個指向返回值爲void的函數的指針,就把RETSIGTYPE定義成void;否則,就把它定義成int。 把信號處理器(signal handler)的返回值類型定義爲RETSIGTYPE: RETSIGTYPE hup_handler () { ... } 宏: AC_TYPE_SIZE_T 如果沒有定義size_t,就把size_t定義成unsigned。 宏: AC_TYPE_UID_T 如果沒有定義uid_t,就把uid_t定義成int並且把 gid_t定義成int。 對普通類型定義的檢查 本宏用於檢查沒有包括在特定類型測試宏中的typedef。 宏: AC_CHECK_TYPE (type, default) 如果`sys/types.h'或者`stdlib.h'或者`stddef.h'存在,而類型 type沒有在它們之中被定義,就把type定義成C(或者C++)預定義類型 default;例如,`short'或者`unsigned'。 C編譯器的特徵 下列宏檢查C編譯器或者機器結構的特徵。爲了檢查沒有在此列出的特徵,使用AC_TRY_COMPILE (參見檢驗語法)或者AC_TRY_RUN (參見檢查運行時的特徵) 宏: AC_C_BIGENDIAN 如果字(word)按照最高位在前的方式儲存(比如Motorola和SPARC,但不包括Intel和VAX,CPUS),就定義 WORDS_BIGENDIAN。 宏: AC_C_CONST 如果C編譯器不能完全支持關鍵字const,就把const定義成空。有些編譯器並不定義 __STDC__,但支持const;有些編譯器定義__STDC__,但不能完全支持 const。程序可以假定所有C編譯器都支持const,並直接使用它;對於那些不能完全支持const的編譯器,`Makefile'或者配置頭文件將把const定義爲空。 宏: AC_C_INLINE 如果C編譯器支持關鍵字inline,就什麼也不作。如果C編譯器可以接受__inline__或者__inline,就把inline定義成可接受的關鍵字,否則就把inline定義爲空。 宏: AC_C_CHAR_UNSIGNED 除非C編譯器預定義了__CHAR_UNSIGNED__,如果C類型char是無符號的,就定義 __CHAR_UNSIGNED__。 宏: AC_C_LONG_DOUBLE 如果C編譯器支持long double類型,就定義HAVE_LONG_DOUBLE。有些C編譯器並不定義__STDC__但支持long double類型;有些編譯器定義 __STDC__但不支持long double。 宏: AC_C_STRINGIZE 如果C預處理器支持字符串化操作符(stringizing operator),就定義HAVE_STRINGIZE。字符串化操作符是 `#'並且它在宏定義中以如下方式出現: #define x(y) #y 宏: AC_CHECK_SIZEOF (type [, cross-size]) 把SIZEOF_uctype 定義爲C(或C++)預定義類型type的,以字節爲單位的大小,例如`int' or `char *'。如果編譯器不能識別`type',它就被定義爲0。 uctype就是把type中所有小寫字母轉化爲大寫字母,空格轉化成下劃線,星號轉化成`P' 而得到的名字。在交叉編譯中,如果給出了cross-size,就使用它,否則configure就生成一個錯誤並且退出。 例如,調用 AC_CHECK_SIZEOF(int *) 在DEC Alpha AXP系統中,把SIZEOF_INT_P定義爲8。 宏: AC_INT_16_BITS 如果C類型int是16爲寬,就定義INT_16_BITS。本宏已經過時;更常見的方式是用 `AC_CHECK_SIZEOF(int)'來代替。 宏: AC_LONG_64_BITS 如果C類型long int是64位寬,就定義LONG_64_BITS。本宏已經過時;更常見的方式是用`AC_CHECK_SIZEOF(long)'來代替。 Fortran 77編譯器的特徵 下列的宏檢查Fortran 77編譯器的特徵。爲了檢查沒有在此列出的特徵,使用AC_TRY_COMPILE (參見檢驗語法)或者AC_TRY_RUN (參見檢驗運行時的特徵),但首先必須確認當前語言被設置成 Fortran 77 AC_LANG_FORTRAN77(參見對語言的選擇)。 宏: AC_F77_LIBRARY_LDFLAGS 爲成功地連接Fotran 77或者共享庫而必須的Fortran 77內置函數(intrinsic)和運行庫確定連接選項(例如,`-L'和`-l')。輸出變量FLIBS被定義爲這些選項。 本宏的目的是用於那些需要把C++和Fortran 77源代碼混合到一個程序或者共享庫中的情況(參見GNU Automake中的`Mixing Fortran 77 With C and C++'節)。 例如,如果來自C++和Fortran 77編譯器的目標文件必須被連接到一起,那麼必須用C++編譯器/連接器來連接(因爲有些C++特定的任務要在連接時完成,這樣的任務有調用全局構造函數、模板的實例化、啓動例外(exception)支持,等等)。 然而,Fortran 77內置函數和運行庫也必須被連接,但C++編譯器/連接器在缺省情況下不知道如何添加這些 Fortran 77庫。因此,就創建AC_F77_LIBRARY_LDFLAGS宏以確認這些Fortran 77庫。 系統服務 下列宏檢查操作系統服務或者操作系統能力。 宏: AC_CYGWIN 檢查Cygwin環境。如果存在,就把shell變量CYGWIN設置成`yes'。如果不存在,就把CYGWIN設置成空字符串。 宏: AC_EXEEXT 根據編譯器的輸出,定義替換變量EXEEXT,但不包括.c、.o和.obj文件。對於Unix來說典型的值爲空,對Win32來說典型的值爲`.exe'或者`.EXE'。 宏: AC_OBJEXT 根據編譯器的輸出,定義替換變量OBJEXT,但不包括.c文件。對於Unix來說典型的值爲`.o',對Win32來說典型的值爲`.obj'。 宏: AC_MINGW32 檢查MingW32編譯環境。如果存在,就把shell變量MINGW32設置成`yes'。如果不存在,就把MINGW32設置成空。 宏: AC_PATH_X 試圖找到X Window系統的頭文件和庫文件。如果用戶給出了命令行選項`--x-includes=dir'和 `--x-libraries=dir',就使用這些目錄。如果沒有給出任一個選項,或者都沒有給出,就通過運行xmkmf以處理一個測試 `Imakefile',並且檢查它所生成的`Makefile',來得到沒有給出的目錄。如果這失敗了(比如說,xmkmf不存在),就在它們通常存在的幾個目錄中尋找。如果任何一種方法成功了,就把shell變量x_includes和x_libraries設置成相應的位置,除非這些目錄就在編譯器搜索的缺省目錄中。 如果兩種方法都失敗了,或者用戶給出命令行選項`--without-x',就把shell變量no_x 設置成`yes';否則就把它設置成空字符串。 宏: AC_PATH_XTRA AC_PATH_X的增強版。它把X需要的C編譯器選項添加到輸出變量X_CFLAGS,並且把 X的連接選項添加到X_LIBS。如果不能使用X系統,就把`-DX_DISPLAY_MISSING' 設置成X_CFLAGS。 本宏還檢查在某些系統中爲了編譯X程序而需要的特殊庫。它把所有系統需要的庫添加到輸出變量X_EXTRA_LIBS。並且它檢查需要在`-lX11'之前被連接的特殊X11R6庫,並且把找到的所有庫添加到輸出變量X_PRE_LIBS。 宏: AC_SYS_INTERPRETER 檢查系統是否支持以形式爲`#! /bin/csh'的行開頭的腳本選擇執行該腳本的解釋器。在運行本宏之後,configure.in中的shell代碼就可以檢查shell變量 interpval;如果系統支持`#!',interpval將被設置成`yes',如果不支持就設置成`no'。 宏: AC_SYS_LONG_FILE_NAMES 如果系統支持長於14個字符的文件名,就定義HAVE_LONG_FILE_NAMES。 宏: AC_SYS_RESTARTABLE_SYSCALLS 如果系統自動地重新啓動被信號所中斷的系統調用,就定義HAVE_RESTARTABLE_SYSCALLS。 UNIX變種 下列宏檢查對於有些程序來說需要特殊處理的一些操作系統,這是因爲它們的頭文件或庫文件中含有特別怪異的東西。這些宏不討人喜歡;它們將根據它們所支持的函數或者它們提供的環境,被更加系統化的方法所代替。 宏: AC_AIX 如果在AIX系統中,就定義_ALL_SOURCE。允許使用一些BSD函數。應該在所有運行C編譯器的宏之前調用本宏。 宏: AC_DYNIX_SEQ 如果在Dynix/PTX (Sequent UNIX)系統中,就把`-lseq'添加到輸出變量LIBS中。本宏已經過時;用AC_FUNC_GETMNTENT來代替。 宏: AC_IRIX_SUN 如果在IRIX(Silicon Graphics UNIX)系統中,就把`-lsun'添加到輸出變量LIBS中。本宏已經過時。如果你用本宏來獲取getmntent,就用 AC_FUNC_GETMNTENT來代替。如果你爲了口令(password)和組函數的NIS版本而使用本宏,就用`AC_CHECK_LIB (sun, getpwnam)'來代替。 宏: AC_ISC_POSIX 如果在POSIX化(POSIXized) ISC UNIX系統中,就定義_POSIX_SOURCE,並且把`-posix' (對於GNU C編譯器)或者`-Xp'(對於其他C編譯器)添加到輸出變量CC中。本宏允許使用 POSIX工具。必須在調用AC_PROG_CC之後,在調用其他任何運行C編譯器的宏之前,調用本宏。 宏: AC_MINIX 如果在Minix系統中,就定義_MINIX和_POSIX_SOURCE,並且把_POSIX_1_SOURCE 定義成2。本宏允許使用POSIX工具。應該在所有運行C編譯器的宏之前調用本宏。 宏: AC_SCO_INTL 如果在SCO UNIX系統中,就把`-lintl'添加到輸出變量LIBS。本宏已經過時;用AC_FUNC_STRFTIME來代替。 宏: AC_XENIX_DIR 如果在Xenix系統中,就把`-lx'添加到輸出變量LIBS。還有,如果使用了`dirent.h',就把`-ldir'添加到LIBS。本宏已經過時;用AC_HEADER_DIRENT來代替。
利用libtool自動生成動態庫的Makefile的生成方法
# # 利用libtool自動生成動態庫 # 1. autoscan命令在當前目錄生成configure.scan文件, 內容爲: # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS) AC_CONFIG_SRCDIR([src/bot.h]) AC_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CXX AC_PROG_CC # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([limits.h malloc.h stdlib.h string.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL AC_C_CONST AC_C_INLINE # Checks for library functions. AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([memset strcasecmp strchr strdup]) AC_OUTPUT 將其該名爲configure.ac 然後修改: configure.ac 文件是 autoconf 的輸入文件,經過 autoconf 處理,展開裏面的 m4宏, 輸出的是 configure 腳本。 第 4 行聲明本文件要求的 autoconf 版本,因爲本例使用了新版本 2.57,所以在此註明。 第 5 行 AC_INIT 宏用來定義軟件的名稱和版本等信息 AC_INIT([test], 1.0, [email][email protected][/email]) 增加版本信息(爲生成lib庫做準備) lt_major=1 lt_age=1 lt_revision=12 dist_version=0.1.12 AM_INIT_AUTOMAKE(test, $dist_version) //自動生成Makefile文件 增加宏, 打開共享庫 AC_PROG_LIBTOOL # Check for dl DL_PRESENT="" AC_CHECK_LIB( dl, dlopen, DL_PRESENT="yes",, $DL_LIBS -ldl ) if test "x$DL_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBDL, 1, [Define if DL lib is present]) DL_LIBS="-ldl" AC_SUBST(DL_LIBS) fi # Check for libm M_PRESENT="" AC_CHECK_LIB( m, sin, M_PRESENT="yes",, $M_LIBS -lm ) if test "x$M_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBM, 1, [Define if libm is present]) M_LIBS="-lm" AC_SUBST(M_LIBS) fi 增加依賴庫 # Check for pthread PTHREAD_PRESENT="" AC_CHECK_LIB( pthread, pthread_create, PTHREAD_PRESENT="yes",, $PTHREAD_LIBS -lpthread ) if test "x$PTHREAD_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if libpthread is present]) PTHREAD_LIBS="-lpthread" AC_SUBST(PTHREAD_LIBS) fi 要生成項目工程目錄和其它目錄下的Makefile 文件, 必需加入 AM_CONFIG_FILES的宏: 例如: AC_CONFIG_FILES([Makefile src/Makefile data/Makefile docs/Makefile]) 修改完後Makefile.ac如下: # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) AC_INIT([test],[1.0],[[email][email protected][/email]]) AM_CONFIG_HEADER(config.h) lt_major=1 lt_age=1 lt_revision=12 dist_version=0.1.12 AM_INIT_AUTOMAKE(test, $dist_version) AC_SUBST(lt_major) AC_SUBST(lt_revision) AC_SUBST(lt_age) # Checks for programs. #AC_PROG_CC #AC_PROG_INSTALL #AC_PROG_LN_S #AC_PROG_LIBTOOL AM_PROG_LIBTOOL # Checks for libraries. pkg_modules="gtk+-2.0 >= 2.0.0" PKG_CHECK_MODULES(GTK_PACKAGE, [$pkg_modules], HAVE_GTK2="yes", HAVE_GTK2="no" ) AC_SUBST(GTK_PACKAGE_CFLAGS) AC_SUBST(GTK_PACKAGE_LIBS) # Check for dl DL_PRESENT="" AC_CHECK_LIB( dl, dlopen, DL_PRESENT="yes",, $DL_LIBS -ldl ) if test "x$DL_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBDL, 1, [Define if DL lib is present]) DL_LIBS="-ldl" AC_SUBST(DL_LIBS) fi # Check for libm M_PRESENT="" AC_CHECK_LIB( m, sin, M_PRESENT="yes",, $M_LIBS -lm ) if test "x$M_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBM, 1, [Define if libm is present]) M_LIBS="-lm" AC_SUBST(M_LIBS) fi # Check for pthread (如示例中檢測pthread,在生成的Makefile就會自動添加-lpthread) PTHREAD_PRESENT="" AC_CHECK_LIB( pthread, pthread_create, PTHREAD_PRESENT="yes",, $PTHREAD_LIBS -lpthread ) if test "x$PTHREAD_PRESENT" = "xyes"; then AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if libpthread is present]) PTHREAD_LIBS="-lpthread" AC_SUBST(PTHREAD_LIBS) fi # Checks for header files. #AC_HEADER_DIRENT #AC_HEADER_STDC #AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/time.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics. #AC_TYPE_PID_T #AC_TYPE_SIZE_T #AC_HEADER_TIME # Checks for library functions. #AC_FUNC_CLOSEDIR_VOID #AC_FUNC_MALLOC #AC_CHECK_FUNCS([memset strstr]) AC_CONFIG_FILES([Makefile src/Makefile data/Makefile doc/Makefile]) AC_OUTPUT 2.生成各目錄下的Makefile.am文件 ./Makefile.am //工程目錄下 SUBDIR = src data doc ../src/Makefile.am //源碼目錄下 MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I../include CPPFLAGS=-DINSTALL_PREFIX="/"$(prefix)/"" lib_LTLIBRARIES = libtest.la libtest_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@ libtest_la_SOURCES = / test.c / test_private.h / check_match.c / check_match.h / test_helpers.c / test_helpers.h / debug.h libtest_la_LIBADD = / @DL_LIBS@ / @M_LIBS@ 3. 生成autogen.sh腳本, 內容 #! /bin/sh set -x aclocal autoheader automake --foreign --add-missing --copy autoconf 保存後修改權限 chmod a+x autogen.sh 3.運行腳本./autogen.sh, 生成configure腳本. 這裏可能會遇到錯誤, 可以根據錯誤提示作相應修改. 4.運行./configure腳本.自動生成src目錄下的makefile文件 5. 切換到目錄src, 運行make 自動在當前目錄下建立.libs文件, 編程生成的庫文件就保存在該目錄下. make install 安裝在默認目錄 /usr/local/lib/下. 6.如果要生成其它的安裝目錄,Makefile.am就要這樣寫 MAINTAINERCLEANFILES = Makefile.in INCLUDES = -I../include lib_LTLIBRARIES = libtt.la libdir = $(prefix)/lib/test libtt_la_LDFLAGS = -version-info @lt_major@:@lt_revision@:@lt_age@ libtt_la_LIBADD = @PTHREAD_LIBS@ libtt_la_SOURCES = / tt.c / video.c / video.h
autoconf 和automake生成Makefile文件
原文鏈接:http://www-128.ibm.com/developerworks/cn/linux/l-makefile/
幾個重要的宏
幾個重要的宏從前面可以看出重點有兩個:修改configure.in和編輯Makefile.am 事實上,它們都是用一些宏來獲取相關信息。重要的宏有:
configure.in中
- AC_INIT([xxx],[yyy],[zzz],[aaa])
可以有四個參數,前三個必須。第一個是軟件包的名字,一個字符串(可以用空格,不需用引號);第二個是版本,如0.6;地三個是報告bug的email;地四個是make dist時創建的tar的名字。如果不填(前面的逗號也去掉)的話默認爲xxx(但是會有變化,例如xxx爲My hello則創建my-hello.tar.gz) - AC_OUTPUT([xxx])
指出運行configure後輸出那些文件,一般就是每個文件夾下的Makefile,如AC_OUTPUT([Makefile, src/Makefile, doc/Makefile]) - AC_CHECK_LIB([xxx],[yyy],[zzz],[aaa])
這個用來檢查系統中是否安裝了某個庫。xxx是庫名去掉前面的lib後面的擴展名;yyy是庫xxx中的任一函數名;zzz是當存在時做什麼操作,建議留空([]也去掉),因爲默認情況就是把該庫加入到LIBS變量中,即加入-lxxx,如果改了的話就不加了;aaa是當不存在時的操作,可以用 AC_MSG_ERROR([xxx is needed]),它將在運行configure時打印“xxx is needed”並退出。 - AM_INIT_AUTOMAKE(xxx, yyy)
可以不加參數(同時去掉括號),xxx指包名(這裏的包名不能有空格,就算用引號也不管用),yyy指版本號
Makefile.am中
- AUTOMAKE_OPTIONS=xxx
xxx爲gnu,foreign,和gnits。指用什麼風格的工程,如果是gnu則必須要自己寫AUTHOR,NEWS等文件;一般用foreign,在automake時會給你照搬一套默認的AUTHOR,NEWS等文件。 - bin_PROGRAMS=xxx
指定最後生成的可執行文件的名字,即Makefile的目標,不一定要和包名相同。指定了這個之後,make install會把該目標拷貝到prefix/bin目錄下。很明顯類似的有sbin_PROGRAMS,lib_LIBRARIES, sysconf_DATA,man_MANS等,這個在《GNU編碼標準》中有列表,automake做了一些擴展,但是一些簡單應用只要知道這幾個就行了;例如指定man_MANS=hello.man.3則會把該文件安裝到prefix/man目錄下,指定sysconf_DATA= hello.conf就會把配置文件放到prefix/etc目錄下。xxx_SOURCES=yyy 這裏指定所有與xxx有關的源文件。注意,不要把其他目錄下的文件放進去。例如,如果xxx用到了../comm目錄下的debug.c,不要加到後面,這樣會在本目錄下產生debug.o文件。標準做法是把../comm中的東西做成libcomm.a,然後用xxx_LDADD=.. /comm/libcomm.a加入。 - xxx_LDADD=path/libyyy.a
如果xxx用到了某個lib,則用這個來指定。如果想指定全局lib則直接用LDADD=就行了。
三種一般需求
源代碼的目錄結構一般有三種:flat型,即所有的文件都在一個目錄下;deep型,即頂層目錄沒有源文件,源文件分裝在子目錄如src,doc,test等;shallow型,即頂層目錄中也有源文件,但大部分源文件在子目錄中,例如lib,include等
- 第一種:前面已經提到。
- 第二種:目錄結構如下:其中src中需要用到comm中的東西
test |-- comm | |-- debug.c | `-- debug.h |-- doc | |-- test.conf | `-- test.man.3 `-- src |-- test.c `-- test.h
- 進入test, 運行autoscan得到configure.scan
- mv configure.scan configure.in,不一樣的改動是
AC_OUTPUT([Makefile comm/Makefile src/Makefile doc/Makefile]) AC_PROG_RANLIB 因爲用了lib
- 運行aclocal
- 運行autoconf
- 爲每個需要Makefile的文件夾創建文件Makefile.am。這裏是Makefile.am,comm/Makefile.am, src/Makefile.am,doc/Makefile.am
頂層的Makefile.am內容如下SUBDIRS = doc comm src test 這裏注意把comm放在src前面
comm/Makefile.am內容如下:noinst_LIBRARIES=libcomm.a noinst指的是該庫不要install到prefix/lib目錄下,因爲只是一個臨時的 libcomm_a_lib=debug.h debug.c 注意命名
src/Makefile.am內容如下bin_PROGRAMS=test hello_SOURCES=test.h test.c
doc/Makefile.am內容如下man_MANS=test.man.3 sysconf_DATA=test.conf
- autoheader
- automake --add-missing --copy
- 完成。
需要說明的是,如果還有一個目錄lib裏裝的是一些用於做成libtest.a的文件,而且libtest.a還用到了comm中的東西,這時不能在lib/Makefile.am中使用libtest_a_LIBADD=../comm/libcomm.a。這樣回到之libtest.a中有未解析符號,應該用libtest_a_LIBADD=../comm/debug.o(原因不明,但感覺不應該是這樣的,這樣太土了)
- 第三種:感覺於第二種沒有什麼區別——直接把src目錄中的東西放到頂層目錄就是了。但我想應該不是如此簡單。