1

I am able to successfully compile the below program.

#include <iostream>

#include "boost/log/trivial.hpp"

int main(int, char**)
{
    BOOST_LOG_TRIVIAL(trace) << "A trace severity message";
    return EXIT_SUCCESS;
}

With the following CMakeFile.

cmake_minimum_required(VERSION 2.8)

project(boost_log CXX)

# we will use static libs
set(Boost_USE_STATIC_LIBS ON)

# Boost::log required Boost version >= 1.54.0 
find_package(Boost 1.54.0 REQUIRED COMPONENTS log)

find_package(Threads)

include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

set(SRC_FILES
    src/main.cpp)

add_executable(boost_log ${SRC_FILES})
target_link_libraries(boost_log ${Boost_LIBRARIES} Threads::Threads)

However, if I edit main.cpp and add the following snippet:

#include "boost/log/utility/setup.hpp"
#include "boost/log/utility/setup/from_settings.hpp"

void blah(void)
{

    boost::log::settings setts;
    boost::log::init_from_settings(setts);
}

Then I get linking errors:

/usr/bin/c++    -rdynamic CMakeFiles/boost_log.dir/src/main.cpp.o  -o boost_log -Wl,-Bstatic -lboost_log -lboost_date_time -lboost_log_setup -lboost_system -lboost_filesystem -lboost_thread -lboost_regex -lboost_chrono -lboost_atomic -Wl,-Bdynamic -lpthread -lpthread 
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libboost_log_setup.a(init_from_settings.o): In function `boost::log::v2s_mt_posix::(anonymous namespace)::default_syslog_sink_factory<char>::create_sink(boost::log::v2s_mt_posix::basic_settings_section<char> const&)':
(.text+0x27fa): undefined reference to `boost::log::v2s_mt_posix::sinks::syslog_backend::set_severity_mapper(boost::log::v2s_mt_posix::aux::light_function<boost::log::v2s_mt_posix::sinks::syslog::level (boost::log::v2s_mt_posix::record_view const&)> const&)'
(snipped, but the errors continue)

Why does including from_settings.hpp cause linking to fail? Is this not avaliable to link statically?

I have tried both on Fedora and Ubuntu with the same result.

john
  • 11
  • 1

2 Answers2

0

You are missing the log_setup library!

Do:

find_package(Boost 1.54.0 REQUIRED COMPONENTS log_setup log)
Skriptkiddie
  • 411
  • 2
  • 7
  • Simply list it in `find_package` doesn't help. You will need to list it in `target_link_libraries` in the correct order. See my answer below. – yaobin Oct 20 '21 at 13:54
0

I encountered the same link error these days and it turned out to be a static linking order issue which is a topic I'm not familiar enough to explain here but I found an article that may help: Library order in static linking.

I used the same C++ source code as you posted in the question but my CMakeLists.txt looks like the following:

cmake_minimum_required(VERSION 3.10)

include(CMakePrintHelpers)

project(boost_log CXX)

# Compile as C++17.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# we will use static libs
set(Boost_USE_STATIC_LIBS ON)

find_package(Boost REQUIRED COMPONENTS
    filesystem
    log
    log_setup
    regex
    system
)

find_package(Threads)

include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

set(SRC_FILES main.cpp)

message(STATUS "==========")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "==========")

add_executable(boost_log_exec ${SRC_FILES}
)
target_link_libraries(boost_log_exec
    # Unfortunately, in ${Boost_LIBRARIES}, `boost_log_setup` follows
    # `boost_log` rather than precedes it, hence the link errors.
    # ${Boost_LIBRARIES}
    Boost::log_setup
    Boost::log
    Threads::Threads
)

The key point is the explicit use of Boost::log_setup and Boost::log in this particular order (i.e., Boost::log_setup must precede Boost::log) which are CMake targets that are explained here. With these two targets explicitly specified in target_link_libraries, you don't need the variable Boost_LIBRARIES at all.

The order of these two is important due to the static linking order issue I mentioned at the very beginning: one must put before the other in order to link correctly.

The reason that ${Boost_LIBRARIES} alone doesn't work is that the static libraries that Boost_LIBRARIES represents are listed in the following order (which is printed out by the message call in my CMakeLists.txt):

Boost_LIBRARIES: /usr/lib/x86_64-linux-gnu/libboost_filesystem.a;/usr/lib/x86_64-linux-gnu/libboost_log.a;/usr/lib/x86_64-linux-gnu/libboost_log_setup.a;/usr/lib/x86_64-linux-gnu/libboost_regex.a;/usr/lib/x86_64-linux-gnu/libboost_system.a;/usr/lib/x86_64-linux-gnu/libboost_date_time.a;/usr/lib/x86_64-linux-gnu/libboost_thread.a;-lpthread;/usr/lib/x86_64-linux-gnu/libboost_chrono.a;/usr/lib/x86_64-linux-gnu/libboost_atomic.a

(I'm not sure why -lpthread is also in the listing, by the way.)

The GCC command line that CMake generates uses the same order of the static libraries when ${Boost_LIBRARIES} was used. Therefore, the actual command was (see note [1] at the end):

/usr/bin/c++ CMakeFiles/boost_log_exec.dir/main.cpp.o -o boost_log_exec /usr/lib/x86_64-linux-gnu/libboost_filesystem.a /usr/lib/x86_64-linux-gnu/libboost_log.a /usr/lib/x86_64-linux-gnu/libboost_log_setup.a /usr/lib/x86_64-linux-gnu/libboost_regex.a /usr/lib/x86_64-linux-gnu/libboost_system.a /usr/lib/x86_64-linux-gnu/libboost_date_time.a /usr/lib/x86_64-linux-gnu/libboost_thread.a -lpthread /usr/lib/x86_64-linux-gnu/libboost_chrono.a /usr/lib/x86_64-linux-gnu/libboost_atomic.a -lpthread

The libboost_log.a and libboost_log_setup.a are listed in the inverse order that they should be, hence the link errors.

In addition, using the CMake target Boost::log itself doesn't solve the problem. In other words, the following code snippet doesn't work:

target_link_libraries(boost_log_exec
    Boost::log
    Threads::Threads
)

It doesn't work because the target Boost::log also lists libboost_log.a first and then libboost_log_setup.a, which is not the desired order. I found this by showing the underlying GCC command line as I mentioned in note [1].

Note [1]: FYI: After I ran cmake . to configure the build, I ran make VERBOSE=1 to build but also show the underlying GCC command line. New versions of CMake seem to support --verbose command line option directly. See this answer.

yaobin
  • 2,436
  • 5
  • 33
  • 54