automake學(xué)習(xí)筆記 - 模塊化編譯

系列文章:
automake學(xué)習(xí)筆記 - helloworld
automake學(xué)習(xí)筆記 - 模塊化編譯
automake學(xué)習(xí)筆記 - 安裝與發(fā)布
automake學(xué)習(xí)筆記 - 交叉編譯

一般來說一個工程會由許多不同的模塊組成鳖眼。源碼放在一個地方尝哆,示例代碼放到另一個地方速勇,第三方庫又放到其他地方。這種時候又應(yīng)該怎么去使用automake呢妖啥?

這篇文章就討論了一下如何使用automake去進行模塊化編譯

我們還是用easylog來做例子,下面是我們修改后的easylog工程的根目錄下的文件:

configure.ac examples Makefile.am src

src目錄

src目錄放的就是庫的源代碼,我們使用src中的源代碼編譯出一個庫來給其他的程序使用easylog的功能

src目錄中有下面幾個文件log_interface.h掉房,easy_log.h,easy_log.cpp综苔,cout_log_interface.h酣倾,cout_log_interface.cpp煎饼,Makefile.am讹挎。實際上就是除了main.cpp,其他文件都放到了這里來吆玖。因為我們提供給別的是一個庫而不是一個可執(zhí)行程序筒溃,所以main.cpp可以不需要編譯到目標文件中

.h和.cpp的內(nèi)容和上一篇文章的內(nèi)容是一樣的。這里的重點其實是Makefile.am沾乘。讓我們先來看看它的內(nèi)容:

lib_LTLIBRARIES = libeasylog.la                                                             
libeasylog_la_SOURCES = cout_log_interface.cpp \                                            
                     easy_log.cpp

其實它的內(nèi)容很簡單怜奖,就是指定了要編譯的庫的名字和庫的源碼。但是有一個問題翅阵,我們這里需要編譯的是但為什么這里的目標文件是libeasylog.la呢?

Libtool是一種屬于GNU構(gòu)建系統(tǒng)的GNU程序設(shè)計工具,它將靜態(tài)庫和動態(tài)庫抽象成了一種統(tǒng)一的叫做libtool庫的概念歪玲。libtool庫使用la作為后綴。它可以用來構(gòu)建靜態(tài)庫也能用來構(gòu)建動態(tài)庫掷匠,而最終編譯出來的到底是哪一種滥崩,在最后執(zhí)行configure命令的時候才能確定。同時它編譯的時候產(chǎn)生的文件就不再是.o文件而是.lo文件讹语。

這里lib_LTLIBRARIES的lib前綴表示的就是目標文件是一個動態(tài)庫而不是可執(zhí)行文件(bin前綴表示目標文件是可執(zhí)行文件,noinst_LTLIBRARIES表示目標文件是靜態(tài)庫)钙皮。而LTLIBRARIES的LT指的就是Libtool。還有一點是一般編譯庫文件的話我們會在文件名錢加上lib前綴,所以我們的目標文件是libeasylog.la株灸。

而下面的libeasylog_la_SOURCES就是指定編譯libeasylog.la使用的源代碼

這里順便說一點,如果這里需要鏈接其他的庫的話需要用 _LIBADD 去指定崇摄。如需要鏈接libpthread這個庫的話就需要這樣寫:

libeasylog_la_LIBADD = -lpthread

examples目錄

examples目錄里面放了這個庫的example代碼擎值。因為我們的庫是要提供給其他人使用的慌烧,所以一般除了文檔之外,還會有一些例子去幫助使用者了解應(yīng)該如何去使用我們的庫鸠儿。這個目錄中的example.cpp其實就是上一篇文章中的main.cpp:

#include "easy_log.h"
#include "cout_log_interface.h"


int main()
{
    EasyLog log(std::make_shared<COutLogInterface>());
    log.Debug("test", "testlog");

    return 0;
}

這個目錄下也有一個Makefile.am屹蚊,它是用來配置example程序的編譯選項的:

AM_CPPFLAGS = -I$(top_srcdir)/src

bin_PROGRAMS = example
example_SOURCES = example.cpp

example_LDADD = -L$(top_builddir)/src \
                -leasylog

AM_CPPFLAGS的值在c/c++預(yù)處理的時候會當(dāng)做參數(shù)傳給預(yù)處理器例如我們將源碼目錄傳給預(yù)處理器,這樣預(yù)處理器才能找到easy_log.h和cout_log_interface.h

這里的top_srcdir變量會在configure是被定義进每,它的值是工程目錄的位置(也就是configure所在目錄的位置)汹粤,后面的top_builddir也是類似的,不過它的值是編譯目錄的位置(也就是執(zhí)行make命令是所在的目錄)

這里編譯出來的example就是我們的demo程序

根目錄

根目錄下也有個Makefile.am,這個文件的內(nèi)容很簡單:

SUBDIRS = src examples

就是將src和examples指定為子目錄于是在make編譯的時候,編譯器就會進入到這兩個目錄中繼續(xù)編譯田晚。它們在這里的先后順序決定了編譯的先后順序嘱兼。因為examples中的example程序是依賴于easylog庫的,所以要然src先編譯

如果不在這里指定子目錄的話,在編譯目錄執(zhí)行make命令就不會自動編譯子目錄中為源碼,需要自己進到子目錄中手動執(zhí)行make命令。如果工程中的某些部分是可選編譯的時候可以這么做贤徒。

最后就是configure.ac文件了:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([easylog], [0.0.2], [466474482@qq.com])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR([src/log_interface.h])
AC_CONFIG_HEADERS([config.h])

AM_PROG_AR
LT_INIT

# Checks for programs.
AC_PROG_CXX
AC_PROG_CC
AX_CXX_COMPILE_STDCXX_11

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 examples/Makefile
                 src/Makefile])

AC_OUTPUT

它和上一篇文章只有一點點小的不同:

一是由于將log_interface.h放到src中了芹壕,所以AC_CONFIG_SRCDIR需要改一下

AC_CONFIG_SRCDIR([src/log_interface.h])

二是examples和src中的Makefile.am也需要在configure.ac中指定:

AC_CONFIG_FILES([Makefile
                 examples/Makefile
                 src/Makefile])

AC_CONFIG_FILES指定了一些需要從Makefile.in中生成的Makefile。這里如果不指定的話configure就不會為其生成Makefile

三是多了AM_PROG_AR和LT_INIT接奈。如果不定義這兩個宏的話,執(zhí)行autoreconf --install命令得到了下面的錯誤日志:

src/Makefile.am:1: error: Libtool library used but 'LIBTOOL' is undefined
src/Makefile.am:1:   The usual way to define 'LIBTOOL' is to add 'LT_INIT'
src/Makefile.am:1:   to 'configure.ac' and run 'aclocal' and 'autoconf' again.
src/Makefile.am:1:   If 'LT_INIT' is in 'configure.ac', make sure
src/Makefile.am:1:   its definition is in aclocal's search path.
automake: warnings are treated as errors
/usr/share/automake-1.15/am/ltlibrary.am: warning: 'libeasylog.la': linking libtool libraries using a non-POSIX
/usr/share/automake-1.15/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac'
src/Makefile.am:1:   while processing Libtool library 'libeasylog.la'
autoreconf: automake failed with exit status: 1

注意AM_PROG_AR 要放在 LT_INIT 之前,要不然 autoreconf --install 的時候會報warn

如果已經(jīng)加上了 LT_INIT 但還是會報錯的話就是系統(tǒng)中沒有安裝libtool了,必須先安裝一下:

sudo apt-get install libtool

編譯工程

  1. 在工程根目錄創(chuàng)建子build目錄用于編譯

  2. 進入build目錄

  3. 執(zhí)行../configure

  4. 執(zhí)行make

之后進入build/examples運行example就可以看到下面輸出:

[test] testlog

靜態(tài)庫和動態(tài)庫的區(qū)別

我們之前在src/Makefile.am中生成的是動態(tài)庫lib_LTLIBRARIES,所以如果將build/src目錄刪掉,build/examples/example就會因為找不到庫而報錯:

/home/linjw/workspace/automake-demo/build/examples/.libs/lt-example: error while loading shared libraries: libeasylog.so.0: cannot open shared object file: No such file or directory

但如果將Makefile.am改成生成靜態(tài)庫則不會報錯踢涌,因為靜態(tài)庫將庫的代碼也編譯到可執(zhí)行程序之中了。

noinst_LTLIBRARIES = libeasylog.la                                               
libeasylog_la_SOURCES = cout_log_interface.cpp \                                    
                     easy_log.cpp

這里的noinst代表的其實是no install的意思

Demo項目

可以在這里查看完整的項目代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末序宦,一起剝皮案震驚了整個濱河市睁壁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌互捌,老刑警劉巖潘明,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異秕噪,居然都是意外死亡钳降,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門巢价,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牲阁,“玉大人,你說我怎么就攤上這事壤躲〕蔷眨” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵碉克,是天一觀的道長凌唬。 經(jīng)常有香客問我,道長漏麦,這世上最難降的妖魔是什么客税? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任况褪,我火速辦了婚禮,結(jié)果婚禮上更耻,老公的妹妹穿的比我還像新娘测垛。我一直安慰自己,他們只是感情好秧均,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布食侮。 她就那樣靜靜地躺著,像睡著了一般目胡。 火紅的嫁衣襯著肌膚如雪锯七。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天誉己,我揣著相機與錄音眉尸,去河邊找鬼。 笑死巨双,一個胖子當(dāng)著我的面吹牛噪猾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播炉峰,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畏妖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了疼阔?” 一聲冷哼從身側(cè)響起戒劫,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婆廊,沒想到半個月后迅细,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡淘邻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年茵典,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宾舅。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡统阿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出筹我,到底是詐尸還是另有隱情扶平,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布蔬蕊,位于F島的核電站结澄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜麻献,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一们妥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧勉吻,春花似錦监婶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲜漩。三九已至源譬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間孕似,已是汗流浹背踩娘。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喉祭,地道東北人养渴。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像泛烙,于是被迫代替她去往敵國和親理卑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內(nèi)容