Makefile.am文件配置

Makefile.am

Makefile.am是一種比Makefile更高層次的編譯規則,能夠和configure.in文件一塊兒經過調用automake命令,生成Makefile.in文件,再調用./configure的時候,就將Makefile.in文件自動生成Makefile文件了。因此Makefile.am文件是比Makefile文件更高的抽象。apache

下面我根據本身的工做中的一些應用,來討論Makefile.am的編寫。我以爲主要是要注意的問題是將編譯什麼文件?這個文件會不會安裝?這個文件被安裝到什麼目錄下?能夠將文件編譯成可執行文件來安裝,也能夠編譯成靜態庫文件安裝,常見的文件編譯類型有下面幾種:session

  • PROGRAMS。表示可執行文件
  • LIBRARIES。表示庫文件
  • LTLIBRARIES。這也是表示庫文件,前面的LT表示libtool。
  • HEADERS。頭文件。
  • SCRIPTS。腳本文件,這個能夠被用於執行。如:example_SCRIPTS,若是用這樣的話,須要咱們本身定義安裝目錄下的example目錄,很容易的,往下看。
  • DATA。數據文件,不能執行。

可執行文件

bin_PROGRAMS = client  
  
client_SOURCES = key.c connect.c client.c main.c session.c hash.c  
client_CPPFLAGS = -DCONFIG_DIR=\"$(sysconfdir)\" -DLIBRARY_DIR=\"$(pkglibdir)\"  
client_LDFLAGS = -export-dynamic -lmemcached  
noinst_HEADERS = client.h  
  
INCLUDES = -I/usr/local/libmemcached/include/  
  
client_LDADD = $(top_builddir)/sx/libsession.la \  
            $(top_builddir)/util/libutil.la

上面就是一個所有的Makefile.am文件,這個文件用於生成client可執行應用程序,引用了兩個靜態庫和MC等動態庫的鏈接。分析一下:memcached

  • bin_PROGRAMS:表示指定要生成的可執行應用程序文件,這表示可執行文件在安裝時須要被安裝到系統中,若是隻是想編譯。不想被安裝到系統中,能夠用noinst_PROGRAMS來代替。
    • bin_PROGRAMS=client 這一行表示什麼意思?解釋以下:
      • PROGRAMS知道這是一個可執行文件。
      • client表示編譯的目標文件。
      • bin表示目錄文件被安裝到系統的目錄。
  • client_SOURCES:表示生成可執行應用程序所用的源文件,這裏注意,client_是由前面的bin_PROGRAMS指定的,若是前面是生成example,那麼這裏就是example_SOURCES,其它的相似標識也是同樣。
  • client_CPPFLAGS:這和Makefile文件中同樣,表示C語言預處理器參數,這裏指定了DCONFIG_DIR,之後在程序中,就能夠直接使用CONFIG_DIR,不要把這個和另外一個CFLAGS混淆,後者表示編譯器參數。
  • client_LDFLAGS:這個表示在鏈接時所須要的庫文件選項標識。這個也就是對應一些如-l,-shared等選項。
  • noinst_HEADERS:這個表示該頭文件只是參加可執行文件的編譯,而不用安裝到安裝目錄下。若是須要安裝到系統中,能夠用include_HEADERS來代替。
  • INCLUDES:鏈接時所須要的頭文件。
  • client_LDADD:鏈接時所須要的庫文件,這裏表示須要兩個庫文件的支持,下面會看到這個庫文件又是怎麼用Makefile.am文件後成的。

再談談關於上文中的全局變量引用,可能有人注意到$(top_builddir)等全局變量(由於這個文件以前沒有定義),其實這個變量是Makefile.am系統定義的一個基本路徑變量,表示生成目標文件的最上層目錄,若是這個Makefile.am文件被其它的Makefile.am文件,這個會表示其它的目錄,而不是這個當前目錄。還可使用$(top_srcdir),這個表示工程的最頂層目錄,其實也是第一個Makefile.am的入口目錄,由於Makefile.am文件能夠被遞歸性的調用。ui

下面再說一下上文中出現的$(sysconfdir),在系統安裝時,咱們都記得先配置安裝路徑,如./configure --prefix=/install/apache 其實在調用這個以後,就定義了一個變量$(prefix),表示安裝的路徑,若是沒有指定安裝的路徑,會被安裝到默認的路徑,通常都是/usr/local。在定義$(prefix),還有一些預約義好的目錄,其實這一些定義均可以在頂層的Makefile文件中能夠看到,以下面一些值:url

  • bindir = $(prefix)/bin。
  • libdir = $(prefix)/lib。
  • datadir=$(prefix)/share。
  • sysconfdir=$(prefix)/etc。
  • includedir=$(prefix)/include。

這些量還能夠用於定義其它目錄,例如我想將client.h安裝到include/client目錄下,這樣寫Makefile.am文件:spa

clientincludedir=$(includedir)/client  
clientinclude_HEADERS=$(top_srcdir)/client/client.h

這就達到了個人目的,至關於定義了一個安裝類型,這種安裝類型是將文件安裝到include/client目錄下。
咱們本身也能夠定義新的安裝目錄下的路徑,如我在應用中簡單定義的:code

devicedir = ${prefix}/device  
device_DATA = package

這樣的話,package文件會做爲數據文件安裝到device目錄之下,這樣一個可執行文件就定義好了。注意,這也至關於定義了一種安裝類型:devicedir,因此你想怎麼安裝就怎麼安裝,後面的XXXXXdir,dir是固定不變的。server

靜態庫文件

編譯靜態庫和編譯動態庫是不同的,咱們先看靜態庫的例子,這個比較簡單。直接指定 XXXX_LTLIBRARIES或者XXXX_LIBRARIES就能夠了。若是不須要安裝到系統,將XXXX換成noinst就能夠。仍是再羅嗦一下:遞歸

通常推薦使用libtool庫編譯目標,由於automake包含libtool,這對於跨平臺可移植的庫來講,確定是一個福音。
看例子以下:編譯器

noinst_LTLIBRARIES = libutil.la  
  
noinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h   
  
libutil_la_SOURCES = access.c config.c datetime.c hex.c inaddr.c log.c device.c pool.c rate.c sha1.c stanza.c str.c xhash.c  
  
libutil_la_LIBADD = @LDFLAGS@

第一行的noinst_LTLIBRARIES,這裏要注意的是LTLIBRARIES,另外還有LIBRARIES,兩個都表示庫文件。前者表示libtool庫,用法上基本是同樣的。若是須要安裝到系統中的話,用lib_LTLIBRARIES
注意:靜態庫編譯鏈接時須要其它的庫的話,採用XXXX_LIBADD選項,而不是前面的XXXX_LDADD。編譯靜態庫是比較簡單的,由於直接能夠指定其類型。

動態庫文件

想要編譯XXX.so文件,須要用_PROGRAMS類型,這裏一個關於安裝路徑要注意的問題是,咱們通常但願將動態庫安裝到lib目錄下,按照前面所討論的,只須要寫成lib_PROGRAMS就能夠了,由於前面的lib表示安裝路徑,可是automake不容許這麼直接定義,能夠採用下面的辦法,也是將動態庫安裝到lib目錄下

projectlibdir=$(libdir) //新建一個目錄,就是該目錄就是lib目錄  
projectlib_PROGRAMS=project.so  
project_so_SOURCES=xxx.C  
project_so_LDFLAGS=-shared -fpic //GCC編譯動態庫的選項

SUBDIRS的用法

這是一個很重要的關鍵詞,咱們前面生成了一個一個的目標文件,可是一個大型的工程項目是由許多個可執行文件和庫文件組成,也就是包含多個目錄,每一個目錄下都有用於生成該目錄下的目標文件的Makefile.am文件,但頂層目錄是如何調用,才能使下面各個目錄分別生成本身的目標文件呢?就是SUBDIRS關鍵詞的用法了。

看一下個人工程項目,這是頂層的Makefile.am文件

EXTRA_DIST = Doxyfile.in README.win32 README.protocol contrib UPGRADE  
  
devicedir = ${prefix}/device  
device_DATA = package  
  
SUBDIRS = etc man  
if USE_LIBSUBST  
SUBDIRS += subst  
endif  
SUBDIRS += tools io sessions util client dispatch server hash storage sms

UBDIRS表示在處理目錄以前,要遞歸處理哪些子目錄,這裏還要注意處理的順序。好比個人client對sessions和utils這兩上目標文件有依賴,就在client以前須要處理這兩個目標文件。 EXTRA_DIST:將哪些文件一塊兒打包。

相關文章
相關標籤/搜索