automake學(xué)習(xí)筆記 - helloworld

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

雖然之前已經(jīng)用過一段時(shí)間的automake,但是總覺得對它的理解不過充分,只是知其然而不知其所以然。于是下定決心好好啃文檔,并將學(xué)的的東西記錄下來。

這篇文章用一個(gè)簡單的log工具的編譯先對automake做一個(gè)hello world級別的介紹羡蛾。

代碼

我們的demo有6個(gè)文件cout_log_interface.h, cout_log_interface.cpp, log_interface.h, easy_log.h, easy_log.cpp, main.cpp

簡單介紹下代碼吧,首先有個(gè)簡單的Log類:

class EasyLog {
public:
    EasyLog(std::shared_ptr<LogInterface> interface);

    void Info(const std::string& tag, const std::string& log);

    void Debug(const std::string& tag, const std::string& log);

    void Warn(const std::string& tag, const std::string& log);

    void Error(const std::string& tag, const std::string& log);

private:
    std::string GetLog(const std::string& tag, const std::string& log) const;

    std::shared_ptr<LogInterface> interface_;
};

它的實(shí)現(xiàn)十分簡單岂津,就是將所有的操作代理給LogInterface:

EasyLog::EasyLog(shared_ptr<LogInterface> interface)
    : interface_(interface)
{
}

void EasyLog::Info(const string& tag, const string& log)
{
    interface_->DoLog(kInfo, tag, GetLog(tag, log));
}

void EasyLog::Debug(const string& tag, const string& log)
{
    interface_->DoLog(kDebug, tag, GetLog(tag, log));
}

void EasyLog::Warn(const string& tag, const string& log)
{
    interface_->DoLog(kWarn, tag, GetLog(tag, log));
}

void EasyLog::Error(const string& tag, const string& log)
{
    interface_->DoLog(kError, tag, GetLog(tag, log));
}

std::string EasyLog::GetLog(const string& tag, const string& log) const
{
    return "[" + tag + "]" + " " + log;
}

LogInterface是一個(gè)純虛類硝皂,然后LogLevel是一個(gè)枚舉體:

enum LogLevel {
    kInfo,
    kDebug,
    kWarn,
    kError
};

class LogInterface {
public:
    virtual void DoLog(LogLevel level, const std::string& tag, const std::string& log) = 0;
};

我們再寫一個(gè)使用標(biāo)準(zhǔn)輸出打印log的LogInterface:

class COutLogInterface : public LogInterface {
public:
    virtual void DoLog(LogLevel level, const std::string& tag, const std::string& log);
};

它的實(shí)現(xiàn)就是使用cout打印log:

void COutLogInterface::DoLog(LogLevel level, const string& tag, const string& log) {
    cout<<log<<endl;
}

當(dāng)然需要有個(gè)main函數(shù):

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

Makefile.am

automake使用Makefile.am配置工程的源碼,它的內(nèi)容如下:

bin_PROGRAMS = easylog
easylog_SOURCES = cout_log_interface.cpp \
                  easy_log.cpp \
                  main.cpp

bin_PROGRAMS 指定了要編譯生成的目標(biāo)程序的名字,在這里我們最終編譯出來的目標(biāo)程序的文件名是easylog

之后的 easylog_SOURCES 指定了需要參與編譯的源代碼疫剃。

如果需要同時(shí)編譯多個(gè)目標(biāo)程序的話可以用下面的方式分別指定各個(gè)目標(biāo)程序的源代碼

bin_PROGRAMS = program_a program_b
program_a_SOURCES = code_a.cpp
program_b_SOURCES = code_b.cpp 

configure.ac

指定了源代碼還不夠桨菜,因?yàn)閍utomake不僅僅可以用來生成編譯c/c++的makefile仍侥,還可以用來編譯生成其他許許多多語言的makefile要出,所以還需要指定編譯器和依賴文件等。automake使用configure.ac配置這些東西,本例子的configure.ac是這么寫的:

AC_INIT([easylog], [0.0.1], [466474482@qq.com])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_HEADERS([config.h])

AC_PROG_CXX
AX_CXX_COMPILE_STDCXX_11

AC_CONFIG_FILES([Makefile])

AC_OUTPUT

簡單分析一下configure.ac的內(nèi)容:

  • AC_INIT

指定了工程的名字农渊、版本號患蹂、和bug的報(bào)告郵箱

  • AM_INIT_AUTOMAKE

指定了一些選項(xiàng),-Wall和-Werror指定編譯的時(shí)候?qū)⑺械膚arning當(dāng)做error來報(bào)錯(cuò), foreign告訴automake這里不用遵循GNU標(biāo)準(zhǔn)。GNU軟件包應(yīng)該包括一些附加文件去描述如修改項(xiàng)砸紊,作者等信息传于。在這里我們不需要automake去檢查這些附加文件的存在。

  • AC_CONFIG_HEADERS

我們在AC_INIT中配置了版本號等信息,c/c++中一般需要用宏來定義它們,這里就指定了生成的配置宏的頭文件名醉顽。配置了這里,automake就會自動(dòng)幫我們生成config.h頭文件,里面定義了一些VERSION之類的宏

  • AC_PROG_CXX

該宏用于檢查系統(tǒng)中是否有g(shù)++編譯器

  • AX_CXX_COMPILE_STDCXX_11

檢查系統(tǒng)的c++11編譯支持

  • AC_CONFIG_FILES

指定了需要configure生成的Makefile,autoreconf的時(shí)候會通過Makefile.am生成Makefile.in沼溜。而configure的時(shí)候會通過Makefile.in生成Makefile。因?yàn)镸akefile.am和configure.ac在同級目錄,所以直接寫Makefile就好了游添。在后面我會介紹當(dāng)Makefile.am和configure.ac不在同級目錄的時(shí)候需要怎么配置

  • AC_OUTPUT

這是一個(gè)結(jié)束標(biāo)志,實(shí)際上它是一個(gè)腳本命令用來創(chuàng)建AC_CONFIG_HEADERS和AC_CONFIG_FILES所配置的文件

生成Makefile

首先要安裝autoconf

sudo apt-get install autoconf

然后使用下面的命令生成configure

autoreconf --install

除了configure之外系草,它還會生成一些其他的文件,當(dāng)然現(xiàn)在我們不需要去管這些文件

之后就能使用configure腳本去生成Makefile和config.h等

./configure

編譯工程

Makefile都已經(jīng)生成了唆涝,現(xiàn)在就可以使用make命令編譯工程啦

編譯成功之后就能在當(dāng)前目錄看到easylog程序找都。我們可以運(yùn)行它:

./easylog

得到下面輸出:

[test] testlog

在build目錄中編譯項(xiàng)目

現(xiàn)在我們編譯生成的.o文件和目標(biāo)程序都混在源代碼中間,看起來很不舒服。我們可以創(chuàng)建一個(gè)build目錄廊酣。然后進(jìn)入build目錄執(zhí)行下面命令

../configure

這樣就在build目錄下生成Makefile了,于是現(xiàn)在我們在build中使用make命令編輯工程就會發(fā)現(xiàn)編譯產(chǎn)生的.o文件和目標(biāo)文件都在build中而不會污染源代碼了能耻。

使用autoscan生成configure.ac

如果直接手寫configure.ac的話是比較困難的,很容易漏掉一些依賴項(xiàng)沒有檢查。所以就出現(xiàn)了autoscan這個(gè)工具,它可以幫我們檢查工程中的依賴項(xiàng)生成configure.ac的模板,然后我們只需要在它生成的模板上略加改動(dòng)就可以了亡驰。

我們在工程目錄下使用autoscan命令,會得到下面的兩個(gè)文件:

  1. autoscan.log

  2. configure.scan

autoscan.log是一個(gè)日志文件,通過它我們可以知道一些配置為什么會被需要

而configure.scan就是生成出來的configure.ac的模板了,在easylog工程目錄使用autoscan,生成的configure.scan內(nèi)容如下

#                                               -*- Autoconf -*-                 
# Process this file with autoconf to produce a configure script.                 
                                                                                 
AC_PREREQ([2.69])                                                                
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])                    
AC_CONFIG_SRCDIR([log_interface.h])                                              
AC_CONFIG_HEADERS([config.h])                                                    
                                                                                 
# Checks for programs.                                                           
AC_PROG_CXX                                                                      
AC_PROG_CC                                                                       
                                                                                 
# Checks for libraries.                                                          
                                                                                 
# Checks for header files.                                                       
                                                                                 
# Checks for typedefs, structures, and compiler characteristics.                 
                                                                                 
# Checks for library functions.                                                  
                                                                                 
AC_CONFIG_FILES([Makefile])                                                      
AC_OUTPUT                                                                        

看是不是和我們之前手寫的很像?我們只有在上面進(jìn)行一些小的修改就能得到最終我們需要的configure.ac了

這里有兩個(gè)宏我們是沒有見過的

  • AC_PREREQ

用于檢查autoconf的最低版本

  • AC_CONFIG_SRCDIR

用一個(gè)項(xiàng)目中一定存在的文件去確定源碼目錄的有效性,這是一個(gè)安全檢查宏晓猛。configure有一個(gè)--srcdir的參數(shù)可以指定源碼目錄,這個(gè)宏就可以檢查出源碼目錄是否不小心配置錯(cuò)了

Demo項(xiàng)目

可以在這里查看完整的項(xiàng)目代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市凡辱,隨后出現(xiàn)的幾起案子鞍帝,更是在濱河造成了極大的恐慌,老刑警劉巖煞茫,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡续徽,警方通過查閱死者的電腦和手機(jī)蚓曼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钦扭,“玉大人纫版,你說我怎么就攤上這事】颓椋” “怎么了其弊?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長膀斋。 經(jīng)常有香客問我梭伐,道長,這世上最難降的妖魔是什么仰担? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任糊识,我火速辦了婚禮,結(jié)果婚禮上摔蓝,老公的妹妹穿的比我還像新娘赂苗。我一直安慰自己,他們只是感情好贮尉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布拌滋。 她就那樣靜靜地躺著,像睡著了一般猜谚。 火紅的嫁衣襯著肌膚如雪败砂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天龄毡,我揣著相機(jī)與錄音吠卷,去河邊找鬼。 笑死沦零,一個(gè)胖子當(dāng)著我的面吹牛祭隔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播路操,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疾渴,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屯仗?” 一聲冷哼從身側(cè)響起搞坝,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎魁袜,沒想到半個(gè)月后桩撮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敦第,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年店量,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芜果。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡融师,死狀恐怖右钾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旱爆,我是刑警寧澤舀射,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站怀伦,受9級特大地震影響脆烟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜空镜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一浩淘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吴攒,春花似錦张抄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至镣隶,卻和暖如春极谊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背安岂。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工轻猖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人域那。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓咙边,卻偏偏與公主長得像,于是被迫代替她去往敵國和親次员。 傳聞我的和親對象是個(gè)殘疾皇子败许,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

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