OSX 上的 Boost 日志链接错误

Boost log linking error on OSX

我整个上午都在尝试从 boost 教程中编译以下示例程序来创建一个记录器,但无法弄清楚我做错了什么:

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

使用以下命令:

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

而且我遇到了这样结束的大量错误消息:

     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 安装使用:

brew install boost --c++11

知道发生了什么事吗?

更新

正如 gavinb 所指出的,我不小心尝试用 C 编译代码,我尝试使用正确的 c++ 编译器重新编译:

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

现在收到以下错误:

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)

这些符号属于 C++ 运行时:

___cxa_throw
___gxx_personality_v0

当 link 用户抱怨缺少这些时,那是因为您link将该应用程序作为 C 应用程序而不是 C++ 应用程序。

而不是调用 clang,只需使用 c++ 进行编译和 linking,它应该可以工作。

一些 Boost 库是 header-only(大量模板化),这意味着实现完全由 headers 提供,因此不需要 linking 一个单独的库。但是一些 Boost 库(检查文档,因为这是特别指出的)需要 linking 一个 .so.dylib 来实现。这需要使用 -l 标志指定库名称,例如 -lboost_thread-mt,如果库不在您的库路径中,则可能需要 -L 标志。

在你的例子中,线程库和日志库都需要将它们自己的库添加到 link 阶段,并且这些库也依赖于系统库(common/shared 库)。正如您所发现的,这意味着将以下内容添加到 link 阶段:

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

终于找到解决问题的命令:

clang++ -std=c++11 -DBOOST_LOG_DYN_LINK ./test.cpp -o test -lboost_log-mt -lpthread -lboost_thread-mt -lboost_system-mt