++++++++++++++++++++++++++++ 第二部分 Automake的標準工程組織:+++++++++++++++++++++++++++
一、總體上的目錄:
一般會有如下目錄和檔案,這些自己建立(見二)或用acmkdir自動產生:
1. 目錄:
(1) 必選:
m4: 第三方或自己寫的用於configure.in中的宏
doc: 各種文檔
src: 源碼頂層目錄(裡面怎麼細分是自己的事)
config: 放置configure過程中的一些檔案,使得頂層目錄不那麼多檔案
(2) 可選:
include: 可選目錄,你願意的話,可以用configure將所有的標頭檔連結到這個目錄下。一般不用。
lib: 可選目錄,你願意的話,可以將對系統調用的實現(針對有些平台上沒有實現的調用),常用的小代碼(你可能覺得太小,對每個工程都常用,不應該放src裡做為庫)放在這個目錄下。
2. 檔案:
如:README, AUTHORS, NEWS, ChangeLog, INSTALL, COPYING 有些是automake需要的,必須要存在,除非你用了automake --foreign 選項,就可以不用添加它們。
二、一步步建立工程:
(這個用到我的例子,其說明見每一步,不單獨說明例子了)
1. 建立必須目錄:
mkdir src config doc m4
2. 建立configure.in 檔案:
AC_INIT([kid], # 工程名
[0.1], # 版本號碼
[Yi Feng yifengcn@gmail.com], # 名字和郵箱
[kid]) # make dist/distcheck的打包名
AC_CONFIG_AUX_DIR(config) # 表示將configure產生的一些檔案,放在這裡(使得上層整潔些)
AM_CONFIG_HEADER(config.h) # 配置標頭檔名為config.h
AM_INIT_AUTOMAKE([dist-bzip2]) # 這裡面當然很多參數,而[dist-bzip2]表示make dist/distcheck打包按bz2打包,預設是gz
AC_PROG_CC # 檢測用什麼C編譯器
AC_PROG_CXX # 檢測用什麼C++編譯器
AC_PROG_INSTALL # 產生安裝指令碼 install-sh
AC_PROG_RANLIB # 產生靜態庫要用它(產生庫索引)
AC_PROG_LIBTOOL # 如果只產生靜態庫,用ranlib即可。動態庫得用libtool
AC_PROG_MAKE_SET # 沒見到有無這個選項的差異,加上吧。
AC_CONFIG_FILES([ # configure.in也是給automake用的,automake會在下面這些地方去把你寫的Makefile.am/xxx.pc.in轉成Makefile.in模板/xxx.pc。下面這些檔案.am/.pc.in都得自己寫。
Makefile # 它來自頂層Makefile.am,就是SUBDIRS,指定下m4, src, doc
src/Makefile # 來自src目錄(源檔案)下的總Makefile.am,也是指定下SUBDIRS
src/libhello/Makefile # 這來自src下libhello子目錄下的Makefile.am,提供libhello庫
src/libhello/hello-1.0.pc # 因為這個庫要安裝,這個檔案安裝後供pkg-config使用
src/bin/Makefile # 這來自src下bin子目錄,是可運行程式,使用libhello庫
doc/Makefile # 這裡展示了Man檔案的安裝方法,道理一樣。
m4/Makefile # 如果你在裡面放了自己的configure.in宏,就要這樣。
])
AC_OUTPUT
說明:
(1) 產生庫
ranlib是以前給靜態庫產生索引時用的,所以要用之。但是後來,出現了libtool,這個工具專門產生“庫”,包括靜態和動態,所以,可以不必再用ranlib了。但是,如果僅僅產生靜態庫的話,就用ranlib即可,AC_PROG_LIBTOOL使得configure時間很長:( 另外,libtool的用法,單獨的我沒使用過(它獨立於autoconf和automake,是GNU為瞭解決不同平台,動態庫是否實現,要加什麼參數等等不同,而製做的一個介面統一的工具,使用者產生庫時不再關係這些不同),但是它和automake結合起來非常好用,見下面,它預設的就會同時產生靜態庫和動態庫。且如果你的程式,有個主程式,還有個動態庫,要用主程式連庫,它會預設串連動態庫。而你將他們make install後,你ldd一下主程式,會發現,它依賴的動態庫,是個全路徑的庫!這樣避免了ld.so的一套動態庫搜尋機制,你不用做任何設定(比如ldconfig),你的程式就可以運行。
看看命令列輸出,其實是gcc在連結庫(libhello.so)的時候,加了-Wl等參數,截取如下:
gcc -Wall -g -O3 -g -O2 -o .libs/kid main.o -lm ../../src/libhello/.libs/libhello.so -Wl,--rpath -Wl,/home/echo/tmp/echo//lib
還得提一句,就是libtool的介面為什麼是統一的,見下面的Makefile.am檔案就知道了,它抽象為:你只用寫一種庫,尾碼為.la。然後後自動產生符合該平台要求的動態庫(如.so)和靜態庫(如.a)
(2) .pc.in
一般,如果你要安裝庫的話,為了方便使用,最好提供xxx.pc.in檔案,這個檔案內容在下面會看到。但是,同任何一個需要安裝的目標一樣,你都得在它所在層次的Makefile.am中指定“Primitive”。即:
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = hello-1.0.pc
以知道安裝路徑和由.pc.in產生方法.pc檔案的方法。
(.pc檔案也可以做參數直接給pkg-config 用的,你用 pkg-config xxx.pc --libs --cflags試試)
.pc檔案的安裝路徑,一般都是$(libdir)下的pkgconfig,這裡$(libdir) = $(prefix)/lib.
3. 把你的源檔案放入相應目錄,並按照configure.in中指定的Makefile位置,建立各個Makefile.am:
首先給出寫Makefile.am的總原則 ──── “寫Makefile是寫規則,而寫Makefile.am是一些賦值而已”
(1) 上層的 Makefile.am 只用寫 SUBDIRS 和 EXTRA_DIST:
你哪個地方想要產生xx(比如由源檔案產生庫),安裝xx(比如doc中的man檔案),都得有Makefile.am。如果按照層次組織的話,則每一級目錄都得寫Makefile.am,上層點的目錄會有子目錄,則上層目錄中的Makefile.am只需寫SUBDIRS = sub1 sub2 sub3即可。這裡還有個關鍵是: 靠 sub1 sub2 sub3的順序,指定了編譯順序!! 如果sub1 sub2是庫,sub3是程式要用它們,那麼這樣指定是正確的!
而EXTRA_DIST = file1 file2 的目的只是:如果你有特別的檔案(即不是Makefile.am管的,也不是autotools體系的東西)要保留到make dist產生的髮型版中,則要用EXTRA_DIST指明,否則是不會帶之的。比如你為了省事寫的./reconf檔案(包含libtoolize aclocal autconf autoheader 和 automake)就要用EXTRA_DIST指明保留。
(2) 下層點的(即源碼目錄,或其他待產生(如xxx.pc),待安裝檔案(如man)所在的目錄中)Makefile.am要寫清楚的是各個變數的賦值!如AM_CPPFLAGS就是automake的一個變數。詳細的變數列表參見automake.htm(GNU首頁的文檔)的 Variable Index 附錄。
------------ a. 全域:--------------
AM_CPPFLAGS = -I... -D... #給前置處理器的參數(而INCLUDES是老的用法了,新的已建議用AM_CPPFLAGS)
AM_LDFLAGS = -L #就是給-L用的,可能有其他的用途。
LDADD = -lm -lhello #給-l用的
AM_CFLAGS #對上面三個的補充,你願意加什麼加什麼,如 -Wall -O3 -g
說明:
全域的意思是:對本檔案有效。目前我不用,也沒找過像Makefile中export之類的傳遞變數的方法。現在我在Makefile.am中採取的方法,仍然是不集中在上層目錄的Makefile.am放置共用變數,如標頭檔位置(很多-I)集中放在上層。其實分散放,每個單元可獨立起來,也挺好的。
加AM的意思是:不加AM的對應的變數,設計給包的使用者用的,即使用者可以這樣:./configure CFLAGS='-Wall'。如果你在Makefile.am中也用CFLAGS的話也可以,只不過會被使用者的覆蓋。所以,你要加個AM_首碼,表示這是給開發人員用的變數,不會被使用者定義的覆蓋。LDADD 用於加-l的,這個與使用者無關,所以沒有AM_首碼的用法。
這裡提到的四個變數,將會用在本Makefile.am相關的所有預先處理,編譯和連結。
----------- b. 元素: -------------
在很多情況下,可以理解為用 “位置_製做安裝方法 = primitive1 primitive2” 來定義元素 primitive1 和primitive2。元素,就是要編譯,產生(如xxx.pc)或安裝(如man檔案)的目標。這告訴我們,primitive1 和 primitive2 將會安裝到 $(prefix)/位置,並且製做和安裝方法按照你指定的來。來看幾個非程式的例子:
=== 如:你要安裝cow.1到man1下,那麼這樣寫Makefile.am:
man1_MANS = cow.1
就行了。man1表示將會把這個檔案安裝到$(prefix)/share/man/man1中(別扣說為什麼沒有寫出share到元素中),而MANS則指出了cow.1是一個man檔案,無須做什麼處理,當使用者make install時,直接放到$(prefix)/share/man/man1中即可。但是這樣寫 man1_MANS = cow.1 ,不會再寫什麼屬性了(見下 c. 屬性),但是automake的一個規則是,如果你要在 make dist中包含什麼程式檔案,應該再寫 xx_SOURCES 指明有哪些檔案要編譯和打包,或者用EXTRA_DIST = 來指明包含的檔案。由於 man_MANS 對應的東西,如果寫cow_1_SOURCES,文法上是錯的,因為沒有MANS對應的SOURCES,而 automake 預設,對man1_MANS = cow.1這種形式,不會包含cow.1到 make dist打好的包裡。那怎麼辦呢?automake提供了 dist_ 首碼,和nodist_首碼對應,表示這個元素,不必寫出 SOURCES 類似的東西,直接將和它名字相同的檔案,放到make dist裡即可。
所以,最終形式是: dist_man1_MANS = cow.1
=== 再如:你要安裝hello-1.0.pc,那麼只需要在Makefile.am中寫:
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = hello-1.0.pc
注意到,這裡光指出pkgconfig_DATA中的pkgconfig,是不能確定安裝位置的,這裡pkgconfig和上面的man1的區別是:man1是automake定義的,它當然知道你寫了這個就表示要裝到哪裡 ──── 實際上,一個叫mandir的變數被預設定義了,它就等於 $(prefix)/share/man。但是你自己寫的pkgconfig不是automake內建的,沒有相應的dir變數,所以你必須自己指明 pkgconfigdir = $(libdir)/pkgconfig,這樣才能讓automake知道,你要裝到這裡!這裡libdir就是automake定義的變數,直接寫即可,它對應於lib_XXX(如lib_LIBRARIES)元素定義。至於這裡 _DATA的目的,就是說明,hello-1.0.pc.in 怎麼樣處理:如果你在裡面引用了如prefix,那麼configure指令碼會在啟動並執行時候,將hello-1.0.pc.in中的變數替換,以產生hello-1.0.pc。比如你自己指定了./configure --prefix=...。
下面列舉出常用的 元素定義 方式,這些都是automake的“變數”,全面的變數列表參見automake.htm(GNU首頁的文檔)的 Variable Index 附錄。
EXTRA_PROGRAMS = # 這裡要列出,由使用者./configure來決定是否要產生的目標。
bin_PROGRAMS = kid # 這是定義程式元素的方式,bin由automake預設定義了bindir=$(prefix)/bin,下面的同理。
sbin_PROGRAMS = # 如果你想裝到sbin下的話。
lib_LIBRARIES = libhello.a # 定義靜態庫元素的方式,這裡由LIBRARIES指明了,要編譯成靜態庫。
pkglib_LIBRARIES = # 凡是加上pkgxxx的,表示只是安裝的時候加上包名,即pkglibdir=$(prefix)/lib/@PACKAGE@ 其中PACKAGE應該會被用configure.in中你寫的那個替換掉。
include_HEADERS = # 這是列出你要安裝的標頭檔,這一般是用於你製做了一個庫,然後這裡給出你要安裝的標頭檔。
pkginclude_HEADERS = # 同pkglib意義。
noinst_PROGRAMS = # noinst_表明,產生的東西,不安裝。這裡表明產生的程式,make install不會安裝
noinst_LIBRARIES = # 這是常用的,因為你可能在子目錄下,產生一個供自己程式使用的靜態庫。
lib_LTLIBRARIES = libhello.la # 這個太常用了,產生動態庫,要藉助libtool(LT),這裡LTLIBRARIES表明了要使用libtool。注意:這樣寫的話,動態庫的libhello和靜態庫的都會產生!如果你寫的是noinst_LTLIBRARIES,則只產生靜態庫的!! 所以,實際上,上面的noinst_LIBRARIES已經意義不大了(但是它卻讓configure的時候時間快得多)
xmldir = $(datadir)/xml # 這裡是自己定義 元素定義 的例子,你要安裝到“xml目錄”下,這個目錄被指定為$(datadir)/xml,其中$(datadir)不再多說,是系統定義的。如果沒有手冊的話,你make install一次,就知道其預設值了。
xml_DATA = file.xml # 接上面的,這裡得指出 製做方式按 DATA。再說明一下:DATA的概念很廣,很多不知道怎麼分類的檔案,都可以用這個來裝。但是如果你需要檔案中的內容,被configure來調整的話,那麼先產生.in 檔案,在檔案中用 @var@來引用變數(你見到的很多變數都可以用),把這個.in 放 configure.in 中,這一切參見 .pc.in 的做法。
man1_MANS = # automake定義的安裝man的方式
data_DATA = # automake定義的安裝資料檔案(如 xxx.pc)的方式。
pkgdata_DATA = # 有pkg首碼的同上pkglib意義。
下面列出完整的預先定義的安裝路徑:(其中一些對應的aaa_BBB中的BBB是啥,得查手冊了)
1. Program-related files are installed in one of the following locations:
bindir = $(exec_prefix)/bin
sbindir = $(exec_prefix)/sbin
libexecdir = $(exec_prefix)/libexec
libdir = $(exec_prefix)/lib
includedir = $(prefix)/include
2. Data files should be installed in one of the following directories:
datadir = $(prefix)/share
sysconfdir = $(prefix)/etc
sharedstatedir = $(prefix)/com
localstatedir = $(prefix)/var
3. Documentation should be installed in the following directories:
infodir = $(prefix)/info
mandir = $(prefix)/man
man1dir = $(prefix)/man1
4. Then there are some directories for developing various eccentric types of files:
lispdir = $(datadir)/emacs/site-lisp
m4dir = $(datadir)/aclocal
5. Some Subdirectories for convenience:
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkgdatadir = $(datadir)/@PACKAGE@
--------------- c. 屬性:------------------
顯然,定了上面 元素 是不夠的。元素有其屬性。給屬性賦值的方式是 “元素_屬性”。其中“元素”含.的話,要用_代替。
== 庫元素的屬性有以下:(假設上面 元素定義 是 lib_LTLIBRARIES = libhello.la)
libhello_la_SOURCES = hello1.c hello2.c hello.h
# set the soname : libhello-2.1.3.so.3.0.0
libhello_la_LDFLAGS = -release 2.1.3 -version-info 3:3:3
# 其中兩個版本號碼,可以不用的。但是正規的都要用。release是你自己規定的,你愛怎麼寫怎麼寫。而version是有規定的,上網查吧,首先形式是 a:b:c,冒號不能為.號,然後每個號有意義,均是對庫介面變化情況的描述。我不知道為什麼這裡指定了3:3:3,上面是3.0.0,可能3:3:3不合法呵呵。
libhello_a_LIBADD = obj1.o sub/libsub.la # 添加一些已有的.o/ .a /.la /.so,目的是彙總。
libhello_a_DEPENDENCIES = dep1 # 這個依賴的意思是:它需要在dep1後才編譯。不是LIBADD的彙總意思。沒用過,因為直接在上層目錄的Makefile.am的SUBDIRS裡指定目錄順序,編譯順序就按那個來。
== 程式元素的屬性有以下:(假設上面 元素定義 是 bin_PROGRAMS = kid)
kid_SOURCES = a.c b.c a.h b.h # 列出所有的檔案!!包括標頭檔。因為只有這裡列出的,才能被包含到make dist/distcheck產生的包中去。
kid_LDFLAGS = # -L 等選項。
kid_LDADD = # -l 選項
kid_DEPENDENCIES = # 同庫元素屬性例子。
注意:這裡的_LDFLAGS等,是上面AM_LDFLAGS等的局部變數,只對這一條有效。
4. 本例子的檔案夾和檔案詳細:(緊接上面2步之後該添加的東西)
(1) $(top_srcdir)/reconf
這個檔案,用於簡化當configure.in, Makefile.am非檔案清單部分 等檔案改動後,需要重建工程的時候的命令集合。
內容如下:
#!/bin/bash
echo '- libtoolize'
libtoolize --force # 這個是和libtool配合的,如果你要產生動態庫,才用這個。
echo '- aclocal -I m4'
aclocal -I m4 # 給configure.in中的宏產生實際指令碼。
echo '- autoconf'
autoconf # autoconf 將 configure.in 轉化為configure
echo '- autoheader'
autoheader # 產生 config.h.in 模板
echo '- automake --add-missing --foreign'
automake --add-missing --foreign # 將你在configure.in中,指定的各個Makefile.am,轉成Makefile.in模板。
(2) $(top_srcdir)/Makefile.am
這個是頂層的Makefile.am,內容如下:
EXTRA_DIST = reconf configure # 在make dist產生的包中,包含本來可能不會包含的reconf 和 configure(configure會包含的,這裡不寫也可以)
SUBDIRS = m4 src doc # 三個目錄(其中m4用於放使用者自己定義的configure.in宏,我一般不用)
(3) $(top_srcdir)/m4/Makefile.am
因為這裡我沒用m4目錄,所以在裡面建立一個內容為空白的Makefile.am檔案即可。
(4) $(top_srcdir)/doc/Makefile.am
在doc中,我放了一個man檔案,叫做cow.1(內容為空白),其Makefile.am內容如下:
dist_man1_MANS = cow.1
# (加dist原因上面已述,因為這隻寫了元素 cow.1 沒有寫其屬性,比如有哪些檔案,而automake預設對這種可能是不會加到 make dist 的打包檔案中的。所以,前面加個 dist_ 首碼,表示,把cow.1當作檔案名稱,並且把這個檔案加到make dist 打包檔案中)
(5) $(top_srcdir)/src/Makefile.am
這個檔案是src目錄的總Makefile,src目錄就包含libhello和bin兩個目錄。Makefile.am內容如下:
SUBDIRS = libhello bin # 其中,libhello放在前面,讓它先編譯。否則bin沒法編譯。
(6) $(top_srcdir)/src/libhello/Makefile.am
這個檔案是 libhello目錄的總Makefile,內容如下:
AM_CFLAGS = -Wall -g -O3
lib_LTLIBRARIES = libhello.la
include_HEADERS = hello.h # 為庫配套安裝的標頭檔是這個
libhello_la_SOURCES = hello1.c hello2.c hello.h
libhello_la_LDFLAGS = -release 2.1.3 -version-info 3:3:3 # set the soname: libhello-2.1.3.so.3.0.0
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = hello-1.0.pc
------ 其他檔案內容為:------
hello-1.0.pc.in 內容(這是通用模板,改下Name, Description, Version, Libs即可,更全面的模板man pkg-config,在末尾一點):
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: hello
Description: say hello library
Requires:
Version: @1.0@
Libs: -L${libdir} -lhello
Cflags: -I${includedir} -I${libdir}
源檔案 hello1.c:
#include "hello.h"
void hello1(int times)
{
int i = 0;
for (i = 0; i < sqrt(times); i++) {
printf("hello kid1!/n");
}
}
源檔案 hello2.c:
#include "hello.h"
void hello2(int times)
{
int i = 0;
for (i = 0; i < sqrt(times); i++) {
printf("hello kid2!/n");
}
}
源檔案 hello.h:
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
#include <math.h>
void hello1(int times);
void hello2(int times);
#endif
(7) $(top_srcdir)/src/bin/Makefile.am
這是bin程式目錄的主Makefile,內容如下:
AM_CPPFLAGS = -I$(top_srcdir)/src/libhello
AM_LDFLAGS = -L$(top_builddir)/src/libhello
LDADD = -lhello -lm
AM_CFLAGS = -Wall -g -O3
bin_PROGRAMS = kid
kid_SOURCES = main.c
源檔案 main.c 內容:
#include "hello.h"
int main(int argc, char *argv[])
{
hello1(4);
hello2(16);
return 0;
}
5. make distcheck檢驗 和 打包:
用make dist可以打包。用make distcheck可以類比使用者使用來檢測,並打包。
我這個例子,原先用make distcheck最後在main.o -lhello時報錯(雖然make是好的)。但是產生的打包檔案,解開後,使用是正常的。後來才意識到,make distcheck會檢查VPATH方式的build,這個出錯正是VPATH方式的build通不過。
即:有一種編譯方式是,比如進到$(top_srcdir)目錄後,你不是./configure,而是建立一個build目錄,然後在目錄中 ../configure; make; make install,這樣,原$(top_srcdir)目錄下的所有東西,不會受到影響,產生的檔案,全部在 build下了!包括所有Makefile.am所在的分類樹。
VPATH來源於GNU Make,實質也就是,在一個目錄下make,但是允許其檔案來自其他地方。
後來,查閱 autotools_tutorial.html 發現, 6.7 General Automake principles 有提到,如果要支援VPATH,那麼一些寫法上還要注意: 導致我這裡錯誤的是以下兩個變數:
$(top_srcdir) 只能用於你自己原有的檔案。
$(top_builddir) 必須用於產生的檔案,如系統產生了一個庫,那麼 -L.. 路徑,就要用 $(top_builddir)引出。
我當時,正是由於 bin中的Makefile.am 中的 AM_LDFLAGS = -L$(top_builddir)/src/libhello 用的是 $(top_srcdir) 而導致的錯。
但是要注意的是:“理解上”,都將這兩個變數認為是 Project的頂層目錄來做,就是src所在的目錄層次。
6. 使用:
下面列出一些使用方法:
(1) 在Makefile.am中添加,刪除,變更檔名,只需要make即可。如果改的是其他的東西,多半要重新automake,然後再make。但也一般沒有必須要重複走libtoolize;aclocal;autoconf;autohead 步驟。
如果修改了configure.in檔案,如果Makefile還在,多半直接make就行,它會自動重走./reconf和./configure
(2) 上面多次提到的 prefix,以及exec-prefix,使用者在configure中配置方法為:
configure --prefix=/home/echo --exec-prefix=/home/echo/linux
exec-prefix預設設定等於prefix,但是如果你設定了它其他路徑,則所有的二進位檔案(即本平台相關)檔案會被安裝到exec-prefix指定的路徑下,其他檔案照常裝到prefix指定的路徑下。這是因為,你可能有這樣的要求:你會編譯很多平台的二進位檔案,放到不同的exec-prefix下,然後自己做為網路伺服器,供不同平台的人使用。
另外,用configure配置使用者變數的用法為(使用者變數,就是與上面提到的AM_變數想對應的):configure CFLAGS='-Wall -O3 -g'
(3) wildcards ?
automake 不支援 $(wildcards ...),別想了。不僅不支援,還要想理由讓你覺得應該不支援。見GNU官方automake文檔的27.3 Why doesn't Automake support wildcards?。如果你要實現這點,自己寫指令碼來處理吧。
(4) 安裝和取消安裝:
如果你要安裝到自己目錄,用./configure --prefix=..吧。make install時,用自己使用者即可。一些子目錄,如bin,lib等會被自動產生。
像一些動態庫,如果你要安裝到自己目錄,又不想要root去配置ldconfig等,可以讓 gcc 產生執行檔案,在連結你的庫時,用 -Wl 指定絕對路徑,上面有介紹。僅僅依靠放在相同目錄下是不夠的。不過,這個一般automake就給你做了。
make uninstall可以刪除已安裝的東西。
7. 更多主題:
(1) 顯然,“元素” 定義,並不能解決一切,因為除了MANS,除了DATA等,我們可能對 元素的產生有自己的看法!而且,在一些對源檔案編譯的場合,也許我們也有自己的看法。所以,automake 允許你在Makefile.am裡面寫 Makefile的規則!!
例子參加 autotools_tutorial.html的 6.13 Scripts with Automake ,這裡介紹的是如果你想安裝一些指令碼。
(2) Doxygen的支援:
這需要在m4中添加一個宏,然後還有些配置,之後,makefile中會自動有個產生doxygen文檔的目標。