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阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容