链接到共享库时,Boost Log无法正常工作

时间:2013-12-20 07:17:59

标签: c++ cmake shared-libraries static-libraries boost-log

我尝试这样做:在Windows上创建1个共享库(* .dll),它使用Boost :: Log (我想静态地将Boost :: Log链接到这个库,因为我希望所有内容只打包在1个DLL文件中),但不成功

我的项目有4个文件如下:

我的 CMakeLists.txt :(还有另一个CMakeLists.txt找到带有find_package(Boost 1.54.0 REQUIRED thread log log_setup filesystem date_time system)的Boost库)

cmake_minimum_required(VERSION 2.6)

add_library(mylog SHARED
  mylog.cpp
  )
target_link_libraries(mylog ${Boost_LIBRARIES})

if(UNIX)
  target_link_libraries(mylog rt)
endif(UNIX)

add_executable(testlog
  main.cpp
  )
target_link_libraries(testlog mylog)

我的 mylog.cpp

#include "mylog.h"

namespace logging = boost::log;
namespace expr = boost::log::expressions;
namespace keywords = boost::log::keywords;

__declspec( dllexport ) void initLog()
{
    logging::add_file_log(
    keywords::file_name = "testlog.log",    
    keywords::format = expr::format("%1% [%2%] %3% ")
        % expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d, %H:%M:%S.%f")
        % expr::attr< logging::trivial::severity_level >("Severity")
        % expr::smessage
    );

    logging::add_common_attributes();
}

mylog.h

#ifndef _MYLOG_H
#define _MYLOG_H

#include <boost/log/common.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/console.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/log/utility/empty_deleter.hpp>

__declspec( dllexport ) void initLog();

#endif //_MYLOG_H

我的 main.cpp

#include "mylog.h"

int main(int, char*[])
{
    using namespace boost::log::trivial;
    initLog();
    BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
    BOOST_LOG_TRIVIAL(debug) << "A debug severity message";
    BOOST_LOG_TRIVIAL(info) << "An informational severity message";
    BOOST_LOG_TRIVIAL(warning) << "A warning severity message";
    BOOST_LOG_TRIVIAL(error) << "An error severity message";
    BOOST_LOG_TRIVIAL(fatal) << "A fatal severity message";    
    return 0;
}

当我将库 mylog 编译为静态(没有SHARED关键字)并运行程序 testlog 时,日志消息保存在文件 testlog.log 没有任何东西打印到屏幕,代码说:

2013-12-20, 15:05:36.741156 [trace] A trace severity message         
2013-12-20, 15:05:36.742156 [debug] A debug severity message         
2013-12-20, 15:05:36.743156 [info] An informational severity message 
2013-12-20, 15:05:36.743156 [warning] A warning severity message     
2013-12-20, 15:05:36.743156 [error] An error severity message        
2013-12-20, 15:05:36.743156 [fatal] A fatal severity message         

但是,如果我将其编译为DLL 共享库(带有SHARED关键字),则编译成功但结果不符合预期。 未创建日志文件,消息以不同格式显示在屏幕上。看起来函数 initLog 没有运行:

[2013-12-20 15:06:17.195469] [0x00000e6c] [trace]   A trace severity message          
[2013-12-20 15:06:17.198470] [0x00000e6c] [debug]   A debug severity message          
[2013-12-20 15:06:17.198470] [0x00000e6c] [info]    An informational severity message 
[2013-12-20 15:06:17.199470] [0x00000e6c] [warning] A warning severity message        
[2013-12-20 15:06:17.199470] [0x00000e6c] [error]   An error severity message         
[2013-12-20 15:06:17.200470] [0x00000e6c] [fatal]   A fatal severity message          

请帮我解决这个问题。感谢。

P / S:我也尝试过创建自定义接收器来进行日志记录,而不是使用Boost :: Log :: Trivial,但结果是一样的。 Boost 1.54.0和1.55.0都经过测试。

2 个答案:

答案 0 :(得分:1)

您似乎需要适当地配置和构建boost::log以支持动态链接。否则,它采用静态链接模型。

此处的文档:http://boost-log.sourceforge.net/libs/log/doc/html/log/installation/config.html

相关引用:

  

该库有一个单独编译的部分,应该构建为   在Getting Started guide中描述。有一点需要注意,   虽然。如果您的应用程序包含多个模块(例如   使用Boost.Log的exe和一个或几个dll,库必须是   作为共享对象构建。如果您有一个可执行文件或单个可执行文件   与Boost.Log一起使用的模块,您可以将库构建为   静态库。

答案 1 :(得分:0)

您的dllimport原型在主叫端需要initLog()属性。一种惯用的方法是使用预处理器定义来告诉mylog.h它是否包含在DLL构建中,在这种情况下它需要dllexport,或者来自链接到DLL的可执行文件,在这种情况下它需要{{ 1}}:

mylog.h:

dllimport

的CMakeLists.txt:

#ifdef BUILD_MYLOG_DLL
#define DLLATTRIBUTE __declspec( dllexport )
#else
#define DLLATTRIBUTE __declspec( dllimport )
#endif

DLLATTRIBUTE void initLog();

现在dllexport仅在构建mylog库时使用,而包含该文件的任何其他内容都将获得dllimport。

如果您还想支持静态模式,请在整个BUILD_MYLOG_DLL子句中添加另一个条件,该子句将DLLATTRIBUTE定义为空。