Search code examples
c++boostboost-log

Boost log linking error on OSX


I've been trying to compile the following example program from the boost tutorial to create a logger all morning and can't work out what I'm doing wrong:

#include <boost/log/common.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/expressions.hpp>
#include <boost/core/null_deleter.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>

using namespace boost::log;

BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)

int main()
{
  typedef sinks::asynchronous_sink<sinks::text_ostream_backend> text_sink;
  boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();

  boost::shared_ptr<std::ostream> stream{&std::clog,
    boost::null_deleter{}};
  sink->locked_backend()->add_stream(stream);
  sink->set_filter(severity > 0);
  sink->set_formatter(expressions::stream << severity << ": " <<
    expressions::smessage);

  core::get()->add_sink(sink);

  sources::severity_logger<int> lg;

  BOOST_LOG_SEV(lg, 0) << "note";
  BOOST_LOG_SEV(lg, 1) << "warning";
  BOOST_LOG_SEV(lg, 2) << "error";
  sink->flush();
}

using the following commands:

clang -std=c++11 -c ./test.cpp -Wall -DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK -DBOOST_LOG_DYN_LINK
clang test.o -o test -DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK -DBOOST_LOG_DYN_LINK

And I'm met with a massive error message that ends like this:

     vtable for boost::log::v2s_mt_posix::attribute::impl in test-7198fd.o
      vtable for boost::detail::sp_counted_base in test-7198fd.o
      vtable for boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char> in test-7198fd.o
      vtable for boost::log::v2s_mt_posix::sinks::basic_sink_frontend in test-7198fd.o
      vtable for boost::log::v2s_mt_posix::sinks::sink in test-7198fd.o
      vtable for boost::detail::tss_cleanup_function in test-7198fd.o
      ...
  "___cxa_rethrow", referenced from:
      boost::detail::shared_count::shared_count<boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue>*, boost::detail::sp_ms_deleter<boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue> > >(boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue>*, boost::detail::sp_inplace_tag<boost::detail::sp_ms_deleter<boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue> > >) in test-7198fd.o
      boost::log::v2s_mt_posix::sinks::basic_sink_frontend::will_consume(boost::log::v2s_mt_posix::attribute_value_set const&) in test-7198fd.o
      boost::log::v2s_mt_posix::visitation_result boost::log::v2s_mt_posix::value_visitor_invoker<boost::mpl::vector2<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >, boost::log::v2s_mt_posix::fallback_to_none>::operator()<boost::log::v2s_mt_posix::binder1st<boost::log::v2s_mt_posix::output_fun, boost::log::v2s_mt_posix::expressions::aux::stream_ref<boost::log::v2s_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&> >(boost::log::v2s_mt_posix::attribute_name const&, boost::log::v2s_mt_posix::attribute_value_set const&, boost::log::v2s_mt_posix::binder1st<boost::log::v2s_mt_posix::output_fun, boost::log::v2s_mt_posix::expressions::aux::stream_ref<boost::log::v2s_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>) const in test-7198fd.o
      boost::detail::shared_count::shared_count<boost::thread_specific_ptr<boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::delete_data*, boost::detail::do_heap_delete<boost::thread_specific_ptr<boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::delete_data> >(boost::thread_specific_ptr<boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::delete_data*, boost::detail::do_heap_delete<boost::thread_specific_ptr<boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::delete_data>) in test-7198fd.o
      boost::log::v2s_mt_posix::aux::threadsafe_queue<boost::log::v2s_mt_posix::record_view, std::__1::allocator<void> >::threadsafe_queue(std::__1::allocator<boost::log::v2s_mt_posix::aux::threadsafe_queue_types<boost::log::v2s_mt_posix::record_view, std::__1::allocator<void> >::node> const&) in test-7198fd.o
      boost::detail::shared_count::shared_count<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>*, boost::detail::sp_ms_deleter<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char> > >(boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>*, boost::detail::sp_inplace_tag<boost::detail::sp_ms_deleter<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char> > >) in test-7198fd.o
      void boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::feed_record<boost::recursive_mutex, boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char> >(boost::log::v2s_mt_posix::record_view const&, boost::recursive_mutex&, boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>&) in test-7198fd.o
      ...
  "___cxa_throw", referenced from:
      boost::log::v2s_mt_posix::aux::threadsafe_queue<boost::log::v2s_mt_posix::record_view, std::__1::allocator<void> >::threadsafe_queue(std::__1::allocator<boost::log::v2s_mt_posix::aux::threadsafe_queue_types<boost::log::v2s_mt_posix::record_view, std::__1::allocator<void> >::node> const&) in test-7198fd.o
      void boost::throw_exception<boost::thread_resource_error>(boost::thread_resource_error const&) in test-7198fd.o
      boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::thread_resource_error> >::rethrow() const in test-7198fd.o
      void boost::throw_exception<boost::lock_error>(boost::lock_error const&) in test-7198fd.o
      boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >::rethrow() const in test-7198fd.o
      void boost::throw_exception<boost::condition_error>(boost::condition_error const&) in test-7198fd.o
      boost::detail::interruption_checker::check_for_interruption() in test-7198fd.o
      ...
  "___gxx_personality_v0", referenced from:
      _main in test-7198fd.o
      boost::system::system_error::what() const in test-7198fd.o
      boost::detail::sp_if_not_array<boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue> >::type boost::make_shared<boost::log::v2s_mt_posix::sinks::asynchronous_sink<boost::log::v2s_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2s_mt_posix::sinks::unbounded_fifo_queue> >() in test-7198fd.o
      void boost::log::v2s_mt_posix::sinks::basic_sink_frontend::set_filter<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::greater, boost::proto::argsns_::list2<boost::log::v2s_mt_posix::expressions::attribute_actor<int, boost::log::v2s_mt_posix::fallback_to_none, tag::severity, boost::phoenix::actor>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<int>, 0l> > >, 2l> > >(boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::greater, boost::proto::argsns_::list2<boost::log::v2s_mt_posix::expressions::attribute_actor<int, boost::log::v2s_mt_posix::fallback_to_none, tag::severity, boost::phoenix::actor>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<int>, 0l> > >, 2l> > const&) in test-7198fd.o
      void boost::log::v2s_mt_posix::sinks::basic_formatting_sink_frontend<char>::set_formatter<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0l> >, boost::log::v2s_mt_posix::expressions::attribute_actor<int, boost::log::v2s_mt_posix::fallback_to_none, tag::severity, boost::phoenix::actor> >, 2l> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<char [3]>, 0l> > >, 2l> >, boost::log::v2s_mt_posix::expressions::attribute_actor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, boost::log::v2s_mt_posix::fallback_to_none, boost::log::v2s_mt_posix::expressions::tag::smessage, boost::phoenix::actor> >, 2l> > >(boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::argument<2> >, 0l> >, boost::log::v2s_mt_posix::expressions::attribute_actor<int, boost::log::v2s_mt_posix::fallback_to_none, tag::severity, boost::phoenix::actor> >, 2l> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<char [3]>, 0l> > >, 2l> >, boost::log::v2s_mt_posix::expressions::attribute_actor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, boost::log::v2s_mt_posix::fallback_to_none, boost::log::v2s_mt_posix::expressions::tag::smessage, boost::phoenix::actor> >, 2l> > const&) in test-7198fd.o
      boost::log::v2s_mt_posix::aux::record_pump<boost::log::v2s_mt_posix::sources::severity_logger<int> >::stream() const in test-7198fd.o
      boost::detail::shared_count::~shared_count() in test-7198fd.o
      ...
ld: symbol(s) not found for architecture x86_64

Boost was installed using:

brew install boost --c++11

Any ideas what's going on?

UPDATE

Having accidentally tried to compile the code in C as pointed out by gavinb, I've tried to recompile using the correct c++ compiler:

c++ -std=c++11 -c ./test.cpp -Wall -DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK -DBOOST_LOG_DYN_LINK
c++ test.o -o test -DBOOST_ALL_NO_LIB -DBOOST_ALL_DYN_LINK -DBOOST_LOG_DYN_LINK

and now receive the following error:

st::thread_specific_ptr<boost::log::v2_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::get() const in test.o
  "boost::detail::set_tss_data(void const*, boost::shared_ptr<boost::detail::tss_cleanup_function>, void*, bool)", referenced from:
      boost::thread_specific_ptr<boost::log::v2_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::reset(boost::log::v2_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context*) in test.o
      boost::thread_specific_ptr<boost::log::v2_mt_posix::sinks::basic_formatting_sink_frontend<char>::formatting_context>::~thread_specific_ptr() in test.o
  "boost::detail::thread_data_base::~thread_data_base()", referenced from:
      boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue> >, boost::_bi::list1<boost::_bi::value<boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>*> > > >::~thread_data() in test.o
  "boost::detail::get_current_thread_data()", referenced from:
      boost::detail::interruption_checker::interruption_checker(_opaque_pthread_mutex_t*, _opaque_pthread_cond_t*) in test.o
  "boost::system::system_category()", referenced from:
      ___cxx_global_var_init2 in test.o
      boost::thread_exception::thread_exception(int, char const*) in test.o
      boost::condition_error::condition_error(int, char const*) in test.o
  "boost::system::generic_category()", referenced from:
      ___cxx_global_var_init in test.o
      ___cxx_global_var_init1 in test.o
  "boost::thread::join_noexcept()", referenced from:
      boost::thread::join() in test.o
  "boost::thread::native_handle()", referenced from:
      boost::thread::get_id() const in test.o
  "boost::thread::start_thread_noexcept()", referenced from:
      boost::thread::start_thread() in test.o
  "boost::thread::detach()", referenced from:
      boost::thread::~thread() in test.o
  "boost::thread::thread()", referenced from:
      boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>::asynchronous_sink(bool) in test.o
  "boost::log::v2_mt_posix::attribute_value_set::end() const", referenced from:
      boost::log::v2_mt_posix::visitation_result boost::log::v2_mt_posix::value_visitor_invoker<boost::mpl::vector2<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >, boost::log::v2_mt_posix::fallback_to_none>::operator()<boost::log::v2_mt_posix::binder1st<boost::log::v2_mt_posix::output_fun, boost::log::v2_mt_posix::expressions::aux::stream_ref<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&> >(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&, boost::log::v2_mt_posix::binder1st<boost::log::v2_mt_posix::output_fun, boost::log::v2_mt_posix::expressions::aux::stream_ref<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>) const in test.o
      boost::log::v2_mt_posix::value_extractor<int, boost::log::v2_mt_posix::fallback_to_none, tag::severity>::operator()(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&) const in test.o
      boost::log::v2_mt_posix::value_extractor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, boost::log::v2_mt_posix::fallback_to_none, boost::log::v2_mt_posix::expressions::tag::smessage>::operator()(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&) const in test.o
  "boost::log::v2_mt_posix::attribute_value_set::find(boost::log::v2_mt_posix::attribute_name) const", referenced from:
      boost::log::v2_mt_posix::visitation_result boost::log::v2_mt_posix::value_visitor_invoker<boost::mpl::vector2<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > >, boost::log::v2_mt_posix::fallback_to_none>::operator()<boost::log::v2_mt_posix::binder1st<boost::log::v2_mt_posix::output_fun, boost::log::v2_mt_posix::expressions::aux::stream_ref<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&> >(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&, boost::log::v2_mt_posix::binder1st<boost::log::v2_mt_posix::output_fun, boost::log::v2_mt_posix::expressions::aux::stream_ref<boost::log::v2_mt_posix::basic_formatting_ostream<char, std::__1::char_traits<char>, std::__1::allocator<char> > >&>) const in test.o
      boost::log::v2_mt_posix::value_extractor<int, boost::log::v2_mt_posix::fallback_to_none, tag::severity>::operator()(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&) const in test.o
      boost::log::v2_mt_posix::value_extractor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, boost::log::v2_mt_posix::fallback_to_none, boost::log::v2_mt_posix::expressions::tag::smessage>::operator()(boost::log::v2_mt_posix::attribute_name const&, boost::log::v2_mt_posix::attribute_value_set const&) const in test.o
  "boost::log::v2_mt_posix::aux::once_block_sentry::enter_once_block() const", referenced from:
      boost::log::v2_mt_posix::aux::once_block_sentry::executed() const in test.o
  "boost::log::v2_mt_posix::core::get_logging_enabled() const", referenced from:
      boost::log::v2_mt_posix::record boost::log::v2_mt_posix::sources::basic_composite_logger<char, boost::log::v2_mt_posix::sources::severity_logger<int>, boost::log::v2_mt_posix::sources::single_thread_model, boost::log::v2_mt_posix::sources::features<boost::log::v2_mt_posix::sources::severity<int> > >::open_record<boost::parameter::aux::tagged_argument<boost::log::v2_mt_posix::keywords::tag::severity, int const> >(boost::parameter::aux::tagged_argument<boost::log::v2_mt_posix::keywords::tag::severity, int const> const&) in test.o
  "boost::thread::joinable() const", referenced from:
      boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>::flush() in test.o
      boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>::stop() in test.o
  "typeinfo for boost::detail::thread_data_base", referenced from:
      typeinfo for boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue> >, boost::_bi::list1<boost::_bi::value<boost::log::v2_mt_posix::sinks::asynchronous_sink<boost::log::v2_mt_posix::sinks::basic_text_ostream_backend<char>, boost::log::v2_mt_posix::sinks::unbounded_fifo_queue>*> > > > in test.o
  "vtable for boost::detail::thread_data_base", referenced from:
      boost::detail::thread_data_base::thread_data_base() in test.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Solution

  • These symbols belong to the C++ runtime:

    ___cxa_throw
    ___gxx_personality_v0
    

    When the linker complains these are missing, it is because you are linking the app as a C app rather than a C++ app.

    Rather than invoking clang, just use c++ for both compiling and linking and it should work.

    Some Boost libraries are header-only (being heavily templated), which means the implementation is completely provided by headers and thus does not require linking a separate library. But some Boost libraries (check the documentation as this is specifically noted) require linking a .so or .dylib for the implementation. This requires specifying the library name with the -l flag, such as -lboost_thread-mt and possibly the -L flag if the libraries aren't on your library path.

    In your case, both the threading and logging libraries need their own libraries added to the link stage, and these also depend on the system library (a common/shared library). As you discovered, this means adding the following to the link phase:

    -lpthread -lboost_log-mt -lboost_thread-mt -lboost_system-mt