【问题标题】:CMake linking to boost. error LNK2005CMake 链接到 boost。错误 LNK2005
【发布时间】:2011-10-01 05:07:56
【问题描述】:

整天都在寻找解决方案,但没有任何乐趣。

我有一个包含 2 个项目的 CMake 解决方案。一个是链接到 boost 的静态库,另一个是链接到 boost 和我自己的静态库的可执行文件。 问题是:在 Linux 中,它使用 gcc 编译得很好。但在 VS2008 中,我只收到以下类型的 program_options 链接器错误。

libboost_program_options-vc90-mt-gd-1_46_1.lib(options_description.obj) : error LNK2005: "public: class boost::program_options::options_description_easy_init & __thiscall boost::program_options::options_description_easy_init::operator()(char const *,char const *)" (??Roptions_description_easy_init@program_options@boost@@QAEAAV012@PBD0@Z) already defined in boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll)

看起来它同时链接到静态库和 dll 库...但是为什么呢?

所以我有一个像这样的 CMakeFile 的解决方案目录:

    CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
    PROJECT( BBlockTools )

    SET( TopDir ${CMAKE_CURRENT_SOURCE_DIR} )
    ADD_SUBDIRECTORY( Utilities )
    ADD_SUBDIRECTORY( BBlockFixer )

然后是两个项目目录。 Utilities 是一个静态库,通过以下 CMakeFile 创建:

PROJECT( Utilities )

SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system program_options REQUIRED)
LINK_DIRECTORIES ( ${Boost_LIBRARY_DIRS} )
INCLUDE_DIRECTORIES ( ${Boost_INCLUDE_DIRS} )

SET( src_h Utilities.h )
SET( src_cpp Utilities.cpp )

ADD_LIBRARY( Utilities STATIC ${src_h} ${src_cpp} )

TARGET_LINK_LIBRARIES( Utilities 
  ${Boost_SYSTEM_LIBRARY}
  ${Boost_PROGRAM_OPTIONS_LIBRARY}
  ${Boost_LIBRARIES}
)

以及由此 CMakeFile 创建的第二个项目:

PROJECT( BBlockFixer )

SET(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost COMPONENTS system filesystem program_options REQUIRED)
LINK_DIRECTORIES ( ${BBlockTools_BINARY_DIR}/Utilities/Debug ${Boost_LIBRARY_DIRS} )
INCLUDE_DIRECTORIES ( ${TopDir} ${Boost_INCLUDE_DIRS} )

SET( src_cpp fixerMain.cpp )

ADD_EXECUTABLE( BBlockFixer ${src_cpp} )

TARGET_LINK_LIBRARIES( BBlockFixer 
  Utilities
  ${Boost_FILESYSTEM_LIBRARY}
  ${Boost_PROGRAM_OPTIONS_LIBRARY}
  ${Boost_SYSTEM_LIBRARY}
  ${Boost_LIBRARIES}
)

我是 CMake 的新手,所以我可能会做一些非常糟糕的事情,但我真的不知道发生了什么。我开始使用 VS Project(Fixer),比如删除链接输入到 program_options 来解决问题(直到我再次运行 cmake)。但我认为这不是解决方案,因为从它的外观来看,它出于某种原因同时链接到 dll 库和静态库...... 我尝试从 TARGET_LINK_LIBRARIES 的 BBlockFixer 和 FIND_PACKAGE 的 program_options 中删除 ${Boost_PROGRAM_OPTIONS_LIBRARY} 但没有帮助。

根据我在 CMake 中的理解,我的 BBlockFixer 从我的静态库中继承了指向 program_options 的链接,这应该没问题。但是这个 boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll) 在哪里链接到我的项目中?

任何帮助将不胜感激,因为我变得绝望。真的没那么难……

PS。我设置的这个 TopDir 是为了让我可以包含 Utilities 中的 .h 文件。但我确定一定有更清洁的方法吗?

【问题讨论】:

    标签: c++ visual-studio-2008 boost cmake libraries


    【解决方案1】:

    我的猜测是您仍在自动链接:在 MSVC 上,boost 使用一些 pragma 来自动指示编译器链接到必要的库,然后不需要手动指定所有链接目标到链接器。当然,这与 CMake 的依赖解析以及您手动指定 target_link_libraries 相关。

    看看我的answer to a similar question,我建议使用以下额外定义来禁用自动链接:

    add_definition( -DBOOST_ALL_NO_LIB )
    

    动态链接时可能需要添加以下内容,具体取决于 Boost 版本和组件:

    add_definitions( -DBOOST_ALL_DYN_LINK )
    

    还要注意,您在 find_package() 调用中指定了所需的 Boost 组件,然后在 target_link_libraries() 调用中再次手动指定它们。根据您的需要,您也可以将其替换为

    target_link_libraries( ${Boost_LIBRARIES} )
    

    【讨论】:

    • 感谢您的回答!一秒钟前,我通过将动态库移出 boost libs 文件夹解决了这个问题。我意识到 cmake(FindBoost.cmake?) 只在该文件夹中找到动态库,即使我告诉它链接到静态库。如果它首先找到它们,似乎它优先选择动态的。在 linux 中,显然我只有 boost 的静态库,这就是为什么没有发生冲突的原因。这是你刚刚告诉我的关于自动链接的效果,我说得对吗?我现在会尝试禁用自动链接 :) 谢谢,Stefan
    • 嗯,我尝试将 add_definitions( -DBOOST_ALL_NO_LIB ) 放入所有 3 个 CMakeList 文件中,但并没有改变 CMake 更喜欢动态库的事实。我想我会坚持将动态库移出 boost lib 文件夹
    • 噢!!!实际上,我向您隐瞒了一个事实,即我的解决方案中也有其他项目。在其中一些中,我忘记了设置 SET(Boost_USE_STATIC_LIBS ON)。出于某种原因,说服 cmake 在我的所有项目的配置步骤中选择动态库而不是静态库。伟大的。现在我把它放在任何地方都很好。
    • 你知道,你可以在你的 Boost 部分周围放置 if ( NOT Boost_FOUND ) 测试。这样可以避免这个问题,但代价是需要一次性找到所有的 boost-components。
    • 我的印象是发现了 boost 但它的错误版本(动态而不是静态)。所以我想如果或的话,放这个也没用?
    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-26
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多