【问题标题】:linker error while linking boost log tutorial (undefined references)链接升压日志教程时出现链接器错误(未定义的引用)
【发布时间】:2014-06-01 23:45:57
【问题描述】:

我已经通过 yum 在 Fedora 20 上安装了 boost,并且正在尝试一些简单的示例。但是我无法从logging tutorial 编译第一个示例。

使用g++ -c boosttest.cc 编译可以正常工作,但是当我尝试将其链接时出现很多错误

g++ boosttest.o -o boosttest -lboost_log -lpthread

完整的错误日志:

boosttest.o: In function `main':
boosttest.cc:(.text+0x44): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
boosttest.cc:(.text+0x9a): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
boosttest.cc:(.text+0x167): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
boosttest.cc:(.text+0x1bd): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
boosttest.cc:(.text+0x28a): undefined reference to `boost::log::v2s_mt_posix::trivial::logger::get()'
boosttest.o:boosttest.cc:(.text+0x2e0): more undefined references to `boost::log::v2s_mt_posix::trivial::logger::get()' follow
boosttest.o: In function `boost::log::v2s_mt_posix::record::reset()':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix6record5resetEv[_ZN5boost3log12v2s_mt_posix6record5resetEv]+0x18): undefined reference to `boost::log::v2s_mt_posix::record_view::public_data::destroy(boost::log::v2s_mt_posix::record_view::public_data const*)'
boosttest.o: In function `boost::log::v2s_mt_posix::record boost::log::v2s_mt_posix::sources::basic_composite_logger<char, boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level>, boost::log::v2s_mt_posix::sources::multi_thread_model<boost::log::v2s_mt_posix::aux::light_rw_mutex>, boost::log::v2s_mt_posix::sources::features<boost::log::v2s_mt_posix::sources::severity<boost::log::v2s_mt_posix::trivial::severity_level>, void, void, void, void, void, void, void, void, void> >::open_record<boost::parameter::aux::tagged_argument<boost::log::v2s_mt_posix::keywords::tag::severity, boost::log::v2s_mt_posix::trivial::severity_level const> >(boost::parameter::aux::tagged_argument<boost::log::v2s_mt_posix::keywords::tag::severity, boost::log::v2s_mt_posix::trivial::severity_level const> const&)':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix7sources22basic_composite_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEENS2_8featuresINS2_8severityIS6_EEvvvvvvvvvEEE11open_recordINS_9parameter3aux15tagged_argumentINS1_8keywords3tag8severityEKS6_EEEENS1_6recordERKT_[_ZN5boost3log12v2s_mt_posix7sources22basic_composite_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEENS2_8featuresINS2_8severityIS6_EEvvvvvvvvvEEE11open_recordINS_9parameter3aux15tagged_argumentINS1_8keywords3tag8severityEKS6_EEEENS1_6recordERKT_]+0x1e): undefined reference to `boost::log::v2s_mt_posix::core::get_logging_enabled() const'
boosttest.o: In function `boost::log::v2s_mt_posix::aux::record_pump<boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level> >::~record_pump()':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEED2Ev[_ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEED5Ev]+0x2c): undefined reference to `boost::log::v2s_mt_posix::aux::unhandled_exception_count()'
boosttest.o: In function `boost::log::v2s_mt_posix::aux::record_pump<boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level> >::record_pump(boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level>&, boost::log::v2s_mt_posix::record&)':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEEC2ERS8_RNS1_6recordE[_ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEEC5ERS8_RNS1_6recordE]+0x1d): undefined reference to `boost::log::v2s_mt_posix::aux::stream_provider<char>::allocate_compound(boost::log::v2s_mt_posix::record&)'
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEEC2ERS8_RNS1_6recordE[_ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEEC5ERS8_RNS1_6recordE]+0x28): undefined reference to `boost::log::v2s_mt_posix::aux::unhandled_exception_count()'
boosttest.o: In function `boost::log::v2s_mt_posix::aux::record_pump<boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level> >::auto_release::~auto_release()':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEE12auto_releaseD2Ev[_ZN5boost3log12v2s_mt_posix3aux11record_pumpINS1_7sources18severity_logger_mtINS1_7trivial14severity_levelEEEE12auto_releaseD5Ev]+0xf): undefined reference to `boost::log::v2s_mt_posix::aux::stream_provider<char>::release_compound(boost::log::v2s_mt_posix::aux::stream_provider<char>::stream_compound*)'
boosttest.o: In function `boost::log::v2s_mt_posix::sources::aux::severity_level<boost::log::v2s_mt_posix::trivial::severity_level>::set_value(boost::log::v2s_mt_posix::trivial::severity_level)':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix7sources3aux14severity_levelINS1_7trivial14severity_levelEE9set_valueES6_[_ZN5boost3log12v2s_mt_posix7sources3aux14severity_levelINS1_7trivial14severity_levelEE9set_valueES6_]+0x7): undefined reference to `boost::log::v2s_mt_posix::sources::aux::get_severity_level()'
boosttest.o: In function `boost::log::v2s_mt_posix::record boost::log::v2s_mt_posix::sources::basic_logger<char, boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level>, boost::log::v2s_mt_posix::sources::multi_thread_model<boost::log::v2s_mt_posix::aux::light_rw_mutex> >::open_record_unlocked<boost::parameter::aux::tagged_argument<boost::log::v2s_mt_posix::keywords::tag::severity, boost::log::v2s_mt_posix::trivial::severity_level const> >(boost::parameter::aux::tagged_argument<boost::log::v2s_mt_posix::keywords::tag::severity, boost::log::v2s_mt_posix::trivial::severity_level const> const&)':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix7sources12basic_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEEE20open_record_unlockedINS_9parameter3aux15tagged_argumentINS1_8keywords3tag8severityEKS6_EEEENS1_6recordERKT_[_ZN5boost3log12v2s_mt_posix7sources12basic_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEEE20open_record_unlockedINS_9parameter3aux15tagged_argumentINS1_8keywords3tag8severityEKS6_EEEENS1_6recordERKT_]+0x2a): undefined reference to `boost::log::v2s_mt_posix::core::open_record(boost::log::v2s_mt_posix::attribute_set const&)'
boosttest.o: In function `boost::log::v2s_mt_posix::sources::basic_logger<char, boost::log::v2s_mt_posix::sources::severity_logger_mt<boost::log::v2s_mt_posix::trivial::severity_level>, boost::log::v2s_mt_posix::sources::multi_thread_model<boost::log::v2s_mt_posix::aux::light_rw_mutex> >::push_record_unlocked(boost::rv<boost::log::v2s_mt_posix::record>&)':
boosttest.cc:(.text._ZN5boost3log12v2s_mt_posix7sources12basic_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEEE20push_record_unlockedERNS_2rvINS1_6recordEEE[_ZN5boost3log12v2s_mt_posix7sources12basic_loggerIcNS2_18severity_logger_mtINS1_7trivial14severity_levelEEENS2_18multi_thread_modelINS1_3aux14light_rw_mutexEEEE20push_record_unlockedERNS_2rvINS1_6recordEEE]+0x36): undefined reference to `boost::log::v2s_mt_posix::core::push_record_move(boost::log::v2s_mt_posix::record&)'
collect2: error: ld returned 1 exit status

我错过了什么?我做错了什么?

编辑 1:-lboost_log -lpthread 的顺序对输出没有影响。还有a very similar question,但该解决方案对我不起作用。以下也失败并出现相同的错误:

g++ -DBOOST_LOG_DYN_LINK boosttest.o -o boosttest -lboost_log -lpthread

【问题讨论】:

    标签: c++ boost fedora ld


    【解决方案1】:

    如果您只需要静态编译,则可以避免使用标志。在这种情况下,只需在 CMake 中包含 loglog_setup 组件。

    set(Boost_USE_STATIC_LIBS ON)
    
    find_package(Boost 1.67.0 COMPONENTS log log_setup REQUIRED)
    if(Boost_FOUND)
        target_link_libraries(YourExecutable ${Boost_LIBRARIES})
    endif()
    

    【讨论】:

      【解决方案2】:

      我也有这个错误,如果你使用 CMake,你可以通过以下方式解决这个问题,

      1. 查找相关包:log log_setup

        find_package(Boost COMPONENTS program_options log log_setup REQUIRED)

      2.Append log 和 log_setup 到其他库中:

        set(PROJECT_LIB ${PROJECT_LIB} ${Boost_LOG_LIBRARY} ${Boost_LOG_SETUP_LIBRARY})
      
      1. 将这些库链接到您的程序中,

        target_link_libraries(${PROJECT_NAME} -Wl,--start-group ${PROJECT_LIB} -Wl,--end-group)

      2. DBOOST_LOG_DYN_LINK 添加到 CMAKE_CXX_FLAGS 标志中

        set(CMAKE_CXX_FLAGS "-Wall -Wextra -fPIC -fopenmp -DBOOST_LOG_DYN_LINK")

      【讨论】:

      • 谢谢,这个解决方案对我有用 :)
      【解决方案3】:

      我正在使用cmake 并在make 上遇到相同的错误,我将set (CMAKE_CXX_FLAGS "-g -Wall -DBOOST_LOG_DYN_LINK") 插入到我的CMakeLists.txt 中使其看起来像:

      cmake_minimum_required(VERSION 2.6)
      project(LOGGER)
      
      set(BOOST_INCLUDEDIR "/path/to/env/include")
      set(BOOST_ROOT "/path/to/env/include")
      
      find_package(Boost REQUIRED)
      
      message(STATUS Boost_LIBRARIES:)
      message (STATUS ${Boost_LIBRARIES})
      message(STATUS BOOST_INCLUDEDIR:)
      message(STATUS ${BOOST_INCLUDEDIR})
      
      ADD_EXECUTABLE(logger logger.cpp)
      target_include_directories(logger PUBLIC ${BOOST_INCLUDEDIR})
      
      set (CMAKE_CXX_FLAGS "-g -Wall -DBOOST_LOG_DYN_LINK")
      

      创建此输出:

      -- The C compiler identification is GNU 5.4.0
      -- The CXX compiler identification is GNU 5.4.0
      -- Check for working C compiler: /usr/bin/cc
      -- Check for working C compiler: /usr/bin/cc -- works
      -- Detecting C compiler ABI info
      -- Detecting C compiler ABI info - done
      -- Detecting C compile features
      -- Detecting C compile features - done
      -- Check for working CXX compiler: /usr/bin/c++
      -- Check for working CXX compiler: /usr/bin/c++ -- works
      -- Detecting CXX compiler ABI info
      -- Detecting CXX compiler ABI info - done
      -- Detecting CXX compile features
      -- Detecting CXX compile features - done
      -- Boost version: 1.67.0
      -- Boost_LIBRARIES:
      -- 
      -- BOOST_INCLUDEDIR:
      -- /path/to/env/include
      -- Configuring done
      -- Generating done
      

      请注意,Boost_LIBRARIES 出于某种原因一直为空...:o

      【讨论】:

      • 我发现 Boost_LIBRARIES 变量保持为空,除非您在 find_package 命令中指定 Boost 组件。
      【解决方案4】:

      如果您想静态链接 boost 日志记录,您需要在 boost 编译和项目设置期间准确使用 _WIN32_WINNT 和 BOOST_LOG_NO_THREADS 设置,您将使用日志记录。

      boost\1.67.0\include\boost\log\detail\config.hpp 中的以下 sn-p 说明了如何选择用于记录的命名空间。

      如果您不确定 boost 是如何编译的,请尝试在十六进制编辑器中打开库并找到流提供程序。

      std@@@attributes@v2s_mt_nt6@log@1@_N@Z.??0stream_compound@?$stream_provider

      下面的片段描述了链接器要求的内容。

      // Setup namespace name
      #if !defined(BOOST_LOG_DOXYGEN_PASS)
      #   if defined(BOOST_LOG_DLL)
      #       if defined(BOOST_LOG_NO_THREADS)
      #           define BOOST_LOG_VERSION_NAMESPACE v2_st
      #       else
      #           if defined(BOOST_THREAD_PLATFORM_PTHREAD)
      #               define BOOST_LOG_VERSION_NAMESPACE v2_mt_posix
      #           elif defined(BOOST_THREAD_PLATFORM_WIN32)
      #               if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
      #                   define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt6
      #               else
      #                   define BOOST_LOG_VERSION_NAMESPACE v2_mt_nt5
      #               endif
      #           else
      #               define BOOST_LOG_VERSION_NAMESPACE v2_mt
      #           endif
      #       endif // defined(BOOST_LOG_NO_THREADS)
      #   else
      #       if defined(BOOST_LOG_NO_THREADS)
      #           define BOOST_LOG_VERSION_NAMESPACE v2s_st
      #       else
      #           if defined(BOOST_THREAD_PLATFORM_PTHREAD)
      #               define BOOST_LOG_VERSION_NAMESPACE v2s_mt_posix
      #           elif defined(BOOST_THREAD_PLATFORM_WIN32)
      #               if BOOST_USE_WINAPI_VERSION >= BOOST_WINAPI_VERSION_WIN6
      #                   define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt6
      #               else
      #                   define BOOST_LOG_VERSION_NAMESPACE v2s_mt_nt5
      #               endif
      #           else
      #               define BOOST_LOG_VERSION_NAMESPACE v2s_mt
      #           endif
      #       endif // defined(BOOST_LOG_NO_THREADS)
      #   endif // defined(BOOST_LOG_DLL)
      

      【讨论】:

        【解决方案5】:

        如果您希望 静态地 链接 boost.log,那么您可能需要这样做(按此顺序的库)

        g++ main.cpp -static -lboost_log -lboost_system -lboost_thread -lpthread -o main
        

        【讨论】:

          【解决方案6】:

          -lboost_log_setup 为我解决了这个问题。

          我从spdlog bench Makefile借来的

          g++ -std=c++11 -Wall -pedantic -g -O0 -DBOOST_LOG_DYN_LINK  -c boost-bench-mt.cpp
          g++ boost-bench-mt.o  -lpthread -lboost_log -lboost_log_setup  -lboost_system -lboost_thread -o boost-bench-mt
          

          【讨论】:

            【解决方案7】:

            实际上,只有g++ -DBOOST_ALL_DYN_LINK -lpthread -lboost_log-mt logging_test.cpp 适合我。 DBOOST_LOG_DYN_LINK-lboost_log 得到了同样的错误。

            【讨论】:

              【解决方案8】:

              有人建议添加 cflag BOOST_LOG_DYN_LINK。我认为这不是全部。

              要使用 libboost_log,您应该在构建库时知道库的 cxxflag。可能没有将标志 BOOST_LOG_DYN_LINK 添加到构建中。

              您应该保管好文件 boost/log/detail/config.hpp 关于 BOOST_LOG_VERSION_NAMESPACE。

              无论如何,您应该与链接的 libboost_log 保持相同的 boost_log_version_namespace。

              要检查 boost_log_version_namespace 可以使用以下命令: nm -C libboost_log | grep push_record_move

              push_record_move 是 boost_log 的一个功能,它会输出,像这样, boost::log::v2s_mt_posix::core::push_record_move(boost::log::v2s_mt_posix::record&)

              v2s_mt_posix 是 boost_log_version_namespace。

              【讨论】:

              • 问题出在我的代码中,而不是在 boost 库中。我看不出您的答案与我的代码中错误放置/丢失标志/定义的原始问题有何关系。
              • 首先,您应该检查 boost/log/detail/config.hpp 以查找 libboost_log 已定义的 BOOST_LOG_VERSION_NAMESPACE。然后你应该在你的程序中使用相同的 boost_log_version_namespace。可能链接的 libboost_log 不是 v2s_mt_posix 等命名空间,添加 BOOST_LOG_DYN_LINK 标志可能不会再次起作用。
              • 我只是说一下boost日志版本命名空间的原理。是的,这次你解决了问题。当您发生对boost::log::v2_mt_posix::trivial:: 的未定义引用,然后......
              【解决方案9】:

              我也遇到了同样烦人的问题。 宏应该在编译时定义,而不是链接:

              g++ -std=c++11 -DBOOST_LOG_DYN_LINK -c boosttest.cc
              

              在链接器命令中,确保顺序如下:

              g++ boosttest.o -lboost_log -lpthread -o boosttest
              

              【讨论】:

                【解决方案10】:

                您只需要添加BOOST_LOG_DYN_LINK 定义。因此,在这样的单行命令中:

                g++ -DBOOST_LOG_DYN_LINK logging_test.cpp -lboost_log -lpthread
                

                使用该命令,它现在应该正在运行。

                【讨论】:

                  【解决方案11】:

                  看看马克·拉卡塔在Boost logger linking issue的回答

                  我的问题,也可能是 Michael 的问题,确实是 /usr/local/lib 中同时存在 .dylib 和 .a。因为我不打算动态链接 boost,所以运行 sudo rm -f /usr/local/lib/libboost_*.dylib 解决了这个问题,让我静态链接。我正在开发的程序用于重新分发,我想分发一个没有依赖关系的可执行文件,因此此页面上的其他解决方案不可行。 如果这不可接受,您还可以指定 lib 的完整路径,例如 -l/usr/include/lib/libboost_log.a,但这会导致系统依赖的 makefile。

                  【讨论】:

                    【解决方案12】:

                    只需添加一行

                    #define BOOST_LOG_DYN_LINK 1
                    

                    作为boosttest.cc的第一行。

                    或者,您可以将-DBOOST_LOG_DYN_LINK 添加到您的编译步骤(不是链接步骤,正如您在问题中发布的那样):

                    g++ -std=c++11 -Wall -pedantic -g -O0 -DBOOST_LOG_DYN_LINK  -c boosttest.cc
                    g++  boosttest.o -lpthread -lboost_log -o boosttest
                    

                    【讨论】:

                    • Boost.Log 是否需要 C++11 或更高版本?或者我应该能够使用 C++03 吗?
                    • 忽略——它确实需要 C++11。我在 C++03 中的问题是我在 #included &lt;boost/log/trivial.hpp&gt; 之后是 #defineing BOOST_LOG_DYN_LINK,而不是之前
                    • 也可以链接静态版的boost_log /usr/lib/libboost_log.a。现在,为什么 Boost-maintainers 会这样做并不明显......
                    • 如何为 cmake 指定这个?
                    • @ThunderPhoenix,只需将其添加到您的 CMAKE_CXX_FLAGS 定义中即可。比如这里:set(CMAKE_CXX_FLAGS "... -DBOOST_LOG_DYN_LINK")
                    【解决方案13】:

                    这只是意味着 boost-log 库没有正确链接。此外,GCC 中的顺序也很重要。参考这个question

                    1. 首先确保库已正确构建并且包含所有符号。
                    2. 尝试更改顺序。它可能会对您有所帮助。

                    【讨论】:

                    • 不幸的是,重新排列库对我没有任何影响,请参阅我的编辑。
                    猜你喜欢
                    • 2019-11-25
                    • 2018-03-05
                    • 2014-09-14
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-07-07
                    • 2013-04-04
                    相关资源
                    最近更新 更多