Boost Log does not work correctly when linked to a shared library

2.9k Views Asked by At

I tried to do this: create 1 shared library on Windows (*.dll) which uses Boost::Log (I want to link the Boost::Log to this library statically since I want everything was packaged in only 1 DLL file) but not successful.

My project has 4 files as the following:

My CMakeLists.txt: ( There is another CMakeLists.txt that finds Boost library with find_package(Boost 1.54.0 REQUIRED thread log log_setup filesystem date_time system) )

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)

My 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();
}

And 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

My 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;
}

When I compiled the library mylog as a static one (without SHARED keyword) and ran program testlog, log messages were saved in the file testlog.log and no thing printed to the screen as the code said:

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         

But if I compile it to a DLL shared library (with SHARED keyword), the compilation was successful but the result was not as expected. No log file created and messages were displayed to the screen with different format. It looks like the function initLog was not run:

[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          

Please help me on this. Thanks.

P/S: I have also tried creating custom sinks for logging, not using Boost::Log::Trivial but the result is the same. Both Boost 1.54.0 and 1.55.0 are tested.

2

There are 2 best solutions below

3
On

It appears you need to configure and build boost::log appropriately to support dynamic linking. Otherwise, it assumes a static link model.

Documentation here: http://boost-log.sourceforge.net/libs/log/doc/html/log/installation/config.html

Relevant quote:

The library has a separately compiled part which should be built as described in the Getting Started guide. One thing should be noted, though. If your application consists of more than one module (e.g. an exe and one or several dll's) that use Boost.Log, the library must be built as a shared object. If you have a single executable or a single module that works with Boost.Log, you may build the library as a static library.

1
On

You need a dllimport attribute on your initLog() prototype on the calling end. An idiomatic approach is to use a preprocessor define to tell mylog.h whether it is included from the DLL build, in which case it needs dllexport, or from an executable linked against the DLL, in which case it needs dllimport:

mylog.h:

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

DLLATTRIBUTE void initLog();

CMakeLists.txt:

SET_TARGET_PROPERTIES(mylog PROPERTIES COMPILE_DEFINITIONS "BUILD_MYLOG_DLL")

Now the dllexport is only used when building the mylog library, and anything else that includes the file will get dllimport instead.

If you want to support static mode as well, add another condition around the entire BUILD_MYLOG_DLL clause which defines DLLATTRIBUTE to empty.