轉載時請註明出處和作者連絡方式
文章出處:http://www.limodev.cn/blog
作者連絡方式:李先靜 <xianjimli@gmail.com>
系統程式員成長計劃-工程管理(三)
函數庫
現在我們用automake來管理我們前面所建立的函數庫,這是一個基礎的函數庫,我們就把它命名為base吧。
o 目錄結構
base 根目錄
base/src 原始碼目錄
o 建立Makefile模板
base/Makefile.am內容為:
SUBDIRS=src
base/src/Makefile.am內容為:
lib_LTLIBRARIES=libbase.lalibbase_la_SOURCES= darray.c / darray.h / dlist.c / dlist.h / darray_iterator.h / dlist_iterator.h / hash_table.c / hash_table.h / invert.c / iterator.h / linear_container_darray.c / linear_container_darray.h / linear_container_dlist.c / linear_container_dlist.h / linear_container.h / queue.c / queue.h / sort.c / sort.h / stack.c / stack.h / typedef.hlibbase_la_LDFLAGS=-lpthreadnoinst_PROGRAMS=darray_test dlist_testdarray_test_SOURCES=darray.cdarray_test_CFLAGS=-DDARRAY_TESTdlist_test_SOURCES=dlist.cdlist_test_CFLAGS=-DDLIST_TESTbasedir=$(includedir)/basebase_HEADERS=darray.h dlist.h iterator.h linear_container_dlist.h typedef.h / darray_iterator.h dlist_iterator.h linear_container_darray.h / linear_container.hEXTRA_DIST=/ linear_container_test.c / invert_ng.c / darray_iterator.c / dlist_iterator.c / test_helper.c
LTLIBRARIES是關鍵字。LT代表libtool,libtool是用來封裝共用庫在不同平台上差異的指令碼,其具體實現我們不用關心。
libbase.la 是函數庫的名稱,副檔名用.la而不是.so或.a,同時會產生共用庫和靜態庫。libbase_la_SOURCES是產生libbase.la所需要 的源檔案。
LDFLAGS是關鍵字,用來指定連結時需要的參數,-lpthread表示要連結libpthread.so。
noinst_PROGRAMS是關鍵字,表示不需要安裝的可執行檔,通常是測試程式。為了簡單明了,這裡沒有寫出全部的測試程式。
CFLAGS是關鍵字,用來指定編譯和預先處理時的參數。
HEADERS是關鍵字,列出所要安裝的標頭檔。xxx_HEADERS和xxxdir要配套使用,後者表示要安裝的位置。這裡在 base_HEADERS中列出的標頭檔會安裝到basedir目錄裡。
o 建立autoconf的模板。
運行:
autoscan
mv configure.scan configure.in
然後按前面介紹的方法修改configure.in,得到下面的內容:
AC_PREREQ(2.61)AC_INIT(base, 0.1, xianjimli@hotmail.com)AC_CONFIG_SRCDIR([src/invert.c])AC_CONFIG_HEADER([config.h])AM_INIT_AUTOMAKE(base, 0.1)# Checks for programs.AC_PROG_CCAC_PROG_LIBTOOL # Checks for libraries.# FIXME: Replace `main' with a function in `-lpthread':AC_CHECK_LIB([pthread], [main]) # Checks for header files.AC_HEADER_STDCAC_CHECK_HEADERS([stdlib.h string.h unistd.h]) # Checks for typedefs, structures, and compiler characteristics.AC_C_INLINEAC_TYPE_SIZE_T # Checks for library functions.AC_FUNC_MALLOCAC_FUNC_REALLOC AC_CONFIG_FILES([Makefile src/Makefile])AC_OUTPUT
與前面不同的是:
AC_PROG_LIBTOOL 用來檢查libtool指令碼。
AC_CHECK_LIB用來檢查共用庫是否存在。
AC_CHECK_HEADERS 用來檢查標頭檔是否存在。
AC_FUNC_MALLOC 用來檢查標準的malloc函數是否存在。
o 收集用到的m4宏。
運行:aclocal
o 產生配置標頭檔的模板。
運行:autoheader
o 建立README、NEWS、ChangeLog和AUTHORS幾個檔案。
o 產生libtool需要的檔案。
運行:libtoolize –force –copy
這個命令的主要功能是產生ltmain.sh,而ltmain.sh用來產生libtool指令碼。
o 產生Makefile.in和需要的指令碼。
運行:automake -a
o 產生configure指令碼。
運行:autoconf
o 產生最終的Makefile。
運行:./configure –prefix=$HOME/usr
o 編譯運行:make
o 安裝
運行:make install
o 發布軟體包
運行:make dist
我們編譯好的檔案安裝到/home/lixianjing/usr/lib/目錄下了:
libbase.a libbase.la libbase.so libbase.so.0 libbase.so.0.0.0
靜態庫:libbase.a
動態庫:libbase.so
libtool的封裝:libbase.la
標頭檔和庫都安裝好了,調用者還需要知道下列資訊才能使用:
標頭檔和庫安裝在哪裡?
還依賴哪些其它模組?
為瞭解決這個問題,我們需要藉助另外一個名為pkg-config的工具。pkg是package的簡寫,pkg-config負責查詢指定軟體包 的配置資訊,如軟體包的名稱、說明、版本號碼、標頭檔、庫和依賴關係等等。為了讓pkg-config能正常工作,軟體包的實現者需要提供一個副檔名為pc 的設定檔。
系統中的pkg-config設定檔通常放在/usr/lib/pkgconfig/和/usr/local/lib/pkgconfig/下, 下面是gtk+-2.0.pc:
prefix=/usrexec_prefix=/usrlibdir=/usr/libincludedir=/usr/includetarget=x11 gtk_binary_version=2.10.0gtk_host=i386-redhat-linux-gnu Name: GTK+Description: GIMP Tool Kit (${target} target)Version: 2.12.10Requires: gdk-${target}-2.0 atk cairoLibs: -L${libdir} -lgtk-${target}-2.0Cflags: -I${includedir}/gtk-2.0
前面部分是定義的一些變數,後面是一些關鍵字:
Name: 名稱
Description: 功能描述
Version: 版本號碼
Requires: 所依賴的軟體包
Libs: 調用者的連結參數。
Cflags: 調用者的編譯參數。
由於 prefix之類的變數是在軟體包configure時才決定的,不能直接寫死在pc檔案中。我們可以讓configure根據模板檔案來產生。
模板檔案名稱為base.pc.in,內容為:
prefix=@prefix@exec_prefix=${prefix}libdir=${prefix}/libincludedir=${prefix}/include Name: @PACKAGE_NAME@Description: a basic library.Version: @VERSION@Requires:Libs: -L${libdir} -lbaseCflags: -I${includedir}/base
這個模板檔案和Makefile.in的替換規則一樣,用兩個@@括起來的變數會替換成configure檢測出來的值,@prefix@等變數是 標準的變數。
修改一下base/Makefile.am,增加下列兩行代碼:
pkgconfigdir=${libdir}/pkgconfig
pkgconfig_DATA=base.pc
這是安裝資料檔案的方法,pkgconfig不是關鍵字,取個描述性的名稱就好了。dir和_DATA是關鍵字,它們有相同的首碼,前者表示安裝的 目錄,後者表示要安裝的檔案。按照慣例,pc檔案安裝到${libdir}/pkgconfig下。
修改configure.in,增加輸入出檔案base.pc
AC_OUTPUT([base.pc])
放到AC_CONFIG_FILES也可以,它告訴configure指令碼要產生的檔案。
重新運行configure後會產生base.pc,內容為:
prefix=/home/lixianjing/usr/localexec_prefix=${prefix}libdir=${prefix}/libincludedir=${prefix}/includeName: baseDescription: a basic library.Version: 0.1Requires:Libs: -L${libdir} -lbaseCflags: -I${includedir}/base
(prefix與configure時指定的prefix參數一致。)
在下一節中,我們再學習調用者如何使用pc檔案。