Autoconf/Automake/libtool的使用例子

 Autoconf/Automake/libtool的使用例子  

現在有環境 t/,下面有4個源碼目錄分別是client/ lib/ daemon/ module/,要達到的目標是
1、將lib/ module/ daemon/ 一起編譯,編成可執行文件 mydaemon
2、將 lib/ client/ 一起編譯,編成動態庫libmylib.so 
3、將 lib/ client/ 一起編譯,與目標2不同的是,在編譯client/下的源文件時要帶上預編譯-D__DEBUG_MAIN__選項,最後編譯成test1、test2、test3、test4,這個功能常用來生成一個測試的程序或工具。
4、make all要求把以上3個目標都編譯出來,make install的時候只安裝mydaemon和libmylib.so
5、除了常見make all和make install以外,增加make newiled make libnewfile.so make 以及make install-newfiled make install-libnewfile 。
步驟如下:
1、確保機器上安裝以下軟件 aclocal autoconf libtoolize automake 。編寫一個腳本init.sh,把以下程序的加進去,如下:
touch NEWS
touch README
touch AUTHORS
touch ChangeLog
aclocal
autoconf
libtoolize --force --automake --copy
automake --copy --add-missing --gnu
2、通過autoscan生成configure.ac,然後將它改名configure.in,然後作如下幾處修改。
a、AC_INIT(mysoft,1.0,[email protected])
b、AC_INIT_AUTOMAKE(mysoft,1.0)
c、AC_PREFIX_DEFAULT(/usr/local/mysoft) 這裏添上安裝文件的路徑,比如/usr/local/mysoft/
d、增加LIBTOOL=”$LIBTOOL --silent”
e、AC_OUTPUT(Makefile lib/Makefile client/Makefile module/Makefile daemon/Makefile) 這裏列出你要生成的全部的Makefile。
3、這步是關鍵,爲每個目錄添加一個叫Makfile.am的文件,具體如下:
a、在t/目錄下,由於這個目錄下本身沒有源文件(源文件都在它的子目錄裏面),所以這個目錄下的Makefile..am很簡單,只要寫下面一句
SUBDIRS lib module client daemon
注意編譯時的先後次序。
b、在lib/目錄下,由於這個目錄下的源文件是爲其它目錄的源文件服務的,所以在lib目錄下,我們編譯出一下.a文件,以供別的目錄使用。在Makefile.am中寫如下內容:
noinst_LIBRARIES = libcompat.a
libcompat_a_SOURCES = a.c b.c c.c d.c
libcompat_a_CFLAGS = -I../include  -I/usr/local

noinst_LIBRARIES的意思是生成的庫是不會被make install 所安裝的。庫的名字可以隨便取。
libcompat_a_CFLAGS是編譯時要帶的一些選項
c、module/目錄和功能和lib/的功能相似,因此Makefile.am也相似,如下
noinst_LIBRARIES = libmodule.a
libmodule_a_SOURCES = a.c b.c c.c d.c
libmodule_a_CFLAGS = -I../daemon  -I.../include
d、client目錄的Makefile.am較複雜,因爲1:它要完成目標2,編譯出一個動態庫。2:它又要完成目標3,編譯出一些可執行文件出來。
LDADD = ../lib/libcompat.a
AM_CFLAGS = -D__DEBUG_MAIN__  -I../include  -I../usr/local/include
AM_LDFLAGS = -lpthread –lssl –L/usr/local/lib
(LDADD指的是編譯這個目錄的時候,會用到這個.a。AM_CFLAGS是全局的選項,當某個程序prog有prog_CFLAGS時,AM_CFLAGS會被替換掉。)
noinst_PROGRAMS = test1 test2 test3 test4
(因爲在目標4中要求make install的時候不安裝這些程序,所以是noinst。
這裏沒有指明編譯這些程序的源文件,所以默認會去找test1.c test2.c test3.c test4.c
這裏沒有指明編譯選項,所以在編譯這些程序時,會使用AM_CFLAGS。)
lib_LTLIBRARIES = libmylib.la
libmylib_la_SOURCE = a.c b.c c.c d.c
libmylib_la_LDFLAGS = -lpthread
libnewfile_la_CFLAGS = -I../include
include_HEADERS = ../include/mylib.h

(lib_LTLIBRARIES 是說明要生成的動態庫名稱,因爲是使用libtool,所以這裏用的是la,生成動態庫的過程由libtool去自動完成。 libmylib_la_LDFLAGS說明的是要連接的時候用到的一些庫,libnewfile_la_CFLAGS是在編譯libmylib.la時 用到的選項。include_HEADERS是指在安裝libmylib時,要把這個頭文件也安裝到include裏面)
e、daemon/目錄。將如下內容寫到Makefile.am中
LDADD = ../module/libmodule.a ../lib/libcompat.a
libexec_PROGRAMS = mydaemon
mydaemon_SOURCES = a.c b.c c.c d.c e.c
mydaemon_CFLAGS = -I../include
mydaemon_LDFLAGS = -lpthread –L/usr/local/lib

(libexec_PROGRRAMS, 指的是要生成的程序名,並且暗示程序安裝的路徑,這裏用的是libexec_ 原因是mydaemon是一個daemon,按照freebsd上的通用做 會是把daemon放在libexec/下。同理,如果你寫成bin_PROGRRAMS,程序會被安裝到bin/)。
f、到目前爲止, init.sh應該可以遠行了,然後./configure 然後make all make install。但還沒有完成我們全部的任務,因爲還有最 後一個目標5,爲了增加make的target,我們的作法是直接在最頂部目錄t/Makefile.am中按照Makefile的寫法,手工增加 target。之所以可以這樣做有兩個原因,第一、是因爲automake自動會把Makefile.am的內容原封不動地拷到新生成的Makefile 中,所以在Makefile.am中增加target也就相當於在新生成的Makefile中增加。第二、在默認情況下,Makefile.am中的每個 要生成的程序都可以在相應目錄中單獨去make,也就是說automake會爲每個要生成的程序寫一個target。比如在client目錄中,我們可以 make test1 make libmylib,這些都可以成功執行。
知道了上述兩個原因,我們就可以開始修改t/Makefile.am,增加下列內容:
mydaemon: lib/*.c module/*.c daemon/*.c
$(MAKE) –C lib
$(MAKE) –C module
$(MAKE) mydaemon –C daemon
libmylib: lib/*.c client/*.c
$(MAKE) –C lib
$(MAKE) libmylib.la –C client
test: lib/*.c client/*.c
$(MAKE) –C lib
$(MAKE) test1 –C lib
$(MAKE) test2 –C lib
$(MAKE) test3 –C lib
$(MAKE) test4 –C lib
install-libmylib: client/libmylib.la
$(mkinstalldirs) $(libdir)
$(LIBTOOL) --mode=install /usr/local/install  -c client/libmylib.la $(libdir)/libnewfile.la
install-test: client/*.c
$(mkinstalldirs) $(bindir)
$(LIBTOOL)  --mode=install /usr/local/install –c client/test1  $(bindir)/test1
$(LIBTOOL)  --mode=install /usr/local/install –c client/test2  $(bindir)/test2
$(LIBTOOL)  --mode=install /usr/local/install –c client/test3  $(bindir)/test3
$(LIBTOOL)  --mode=install /usr/local/install –c client/test4  $(bindir)/test4
install-mydaemon daemon/mydaemon
$(mkinstalldirs) $(DESTDIR)$(libexecdir)
$(LIBTOOL) --mode=install /usr/bin/install –c daemon/mydaemon $(libexecdir)/mydaemon

($(mkinstalldirs) $(libexecdir)的作用是看看有沒有這個目錄,如果沒有的話新建。$(libexecdir)就是/usr/local/mysoft/libexec/。) 
到此爲止,任務完成了。運行./init.sh ,運行./configure,它會根據Makefile.am生成Makefile,然後就可以make 以及make install了。

總結一下:
1、兩個很有用的選項 prog_CFLAGS prog_LDCFLAGS 可以滿足我們增加編譯選項和連接選項的功。對應的全局變量是AM_CFLAGS AM_LDFLAGS
2、如果是兩個或兩個以上目錄的源文件需要合在一起編譯,可以採用每個目錄編譯編譯成一個.a,然後能過LDADD把它們放在一起連接。
3、我們可以直接在Makefile.am中寫Makefile的內容。

我在做的過程序中疑惑的問題
1、當bin_PROGRAMS=hello hello_SOURCE=test1.c test2.c時,AutoMake生成的中間文件會是hello-test1.o hello-test2.o,看起來有點彆扭。
2、 有時明明是我只修改了Makefile.am,按理說,我只要執行./configure,就可重新生成Makfile。但有時並不能如我所願,而我重新 執行./init.sh問題就解決了。我的經驗是當你修改了Makefile.am後發現沒什麼變化的時候,運行一下./init.sh或許就好了。
3、在使用過程中覺得make好像有什麼記憶之類的機制,有時,我改了Makfile.am,重新生成了Makefile後,運行make,它還是上次運行失敗的結果,再運行一次就好了。很奇怪。
4、 我在編輯Makefile.am時,往Makefile.am裏面增加command的,我在command 前面明明是用了/t,可是最終被 Automake拷到新的Makefile後,卻變成了4個空格。很鬱悶,最後用了一個笨方法,把Makefile.am改名成Makefile,用vi 打開看一下,確保是/t,然後再把名字改回去。這樣就可以了,可能是我vim的配置問題。

 

轉於

http://wanbin1980.blogcn.com/diary,201313447.shtml

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章