automake學習筆記 - helloworld

系列文章:
automake學習筆記 - helloworld
automake學習筆記 - 模塊化編譯
automake學習筆記 - 安裝與發布
automake學習筆記 - 交叉編譯

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

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

代碼

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

簡單介紹下代碼吧,首先有個簡單的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_;
};

它的實現十分簡單,就是將所有的操作代理給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是一個純虛類,然后LogLevel是一個枚舉體:

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

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

我們再寫一個使用標準輸出打印log的LogInterface:

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

它的實現就是使用cout打印log:

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

當然需要有個main函數:

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

Makefile.am

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

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

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

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

如果需要同時編譯多個目標程序的話可以用下面的方式分別指定各個目標程序的源代碼

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

configure.ac

指定了源代碼還不夠,因為automake不僅僅可以用來生成編譯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的內容:

  • AC_INIT

指定了工程的名字、版本號、和bug的報告郵箱

  • AM_INIT_AUTOMAKE

指定了一些選項,-Wall和-Werror指定編譯的時候將所有的warning當做error來報錯, foreign告訴automake這里不用遵循GNU標準。GNU軟件包應該包括一些附加文件去描述如修改項,作者等信息。在這里我們不需要automake去檢查這些附加文件的存在。

  • AC_CONFIG_HEADERS

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

  • AC_PROG_CXX

該宏用于檢查系統中是否有g++編譯器

  • AX_CXX_COMPILE_STDCXX_11

檢查系統的c++11編譯支持

  • AC_CONFIG_FILES

指定了需要configure生成的Makefile,autoreconf的時候會通過Makefile.am生成Makefile.in。而configure的時候會通過Makefile.in生成Makefile。因為Makefile.am和configure.ac在同級目錄,所以直接寫Makefile就好了。在后面我會介紹當Makefile.am和configure.ac不在同級目錄的時候需要怎么配置

  • AC_OUTPUT

這是一個結束標志,實際上它是一個腳本命令用來創建AC_CONFIG_HEADERS和AC_CONFIG_FILES所配置的文件

生成Makefile

首先要安裝autoconf

sudo apt-get install autoconf

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

autoreconf --install

除了configure之外,它還會生成一些其他的文件,當然現在我們不需要去管這些文件

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

./configure

編譯工程

Makefile都已經生成了,現在就可以使用make命令編譯工程啦

編譯成功之后就能在當前目錄看到easylog程序。我們可以運行它:

./easylog

得到下面輸出:

[test] testlog

在build目錄中編譯項目

現在我們編譯生成的.o文件和目標程序都混在源代碼中間,看起來很不舒服。我們可以創建一個build目錄。然后進入build目錄執行下面命令

../configure

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

使用autoscan生成configure.ac

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

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

  1. autoscan.log

  2. configure.scan

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

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

#                                               -*- 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                                                                        

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

這里有兩個宏我們是沒有見過的

  • AC_PREREQ

用于檢查autoconf的最低版本

  • AC_CONFIG_SRCDIR

用一個項目中一定存在的文件去確定源碼目錄的有效性,這是一個安全檢查宏。configure有一個--srcdir的參數可以指定源碼目錄,這個宏就可以檢查出源碼目錄是否不小心配置錯了

Demo項目

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容