CMake 链接以提升。错误LNK2005

发布于 2024-11-18 23:46:05 字数 2603 浏览 2 评论 0原文

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

我有一个包含 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 项目(Fixer),例如删除 program_options 的链接输入,这解决了问题(直到我再次运行 cmake)。但我认为这不是解决方案,因为从它的外观来看,由于某种原因它同时链接到 dll 库和静态库...... 我尝试从 TARGET_LINK_LIBRARIES 中的 BBlockFixer 中删除 ${Boost_PROGRAM_OPTIONS_LIBRARY} 并从 FIND_PACKAGE 中删除program_options,但没有帮助。

根据我在 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 是为了包含实用程序中的 .h 文件。但我确信必须有一种更清洁的方法来做到这一点,或者?

Been looking around all day for a solution but no joy.

I have a CMake solution with 2 projects. The one is a static library which links to boost, and the other is an executable which links to boost and my own static library.
Problem is: In Linux it compiles fine with gcc. But in VS2008 I get the following type of linker errors for program_options only.

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)

Looks like it's linking to both the static lib and the dll lib...but why?

So I have a solution directory with a CMakeFile like this:

    CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
    PROJECT( BBlockTools )

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

And then the two project directories. Utilities is a static library and is created by following 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}
)

And the second project created by this 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}
)

I'm new to CMake so I might be doing something very bad but I really can't find out what's going on. I started playing around with the VS Project(Fixer) like removing the link input to program_options which fixes the problem(until I run cmake again). But I think that isn't the solution since from how it looks it's linking both to the dll lib and to the static lib for some reason...
I tried removing ${Boost_PROGRAM_OPTIONS_LIBRARY} from BBlockFixer from TARGET_LINK_LIBRARIES and program_options from FIND_PACKAGE but doesnt help.

From what I understand in CMake my BBlockFixer inherits the links to program_options from my static lib which should be all fine. But where did this boost_program_options-vc90-mt-gd-1_46_1.lib(boost_program_options-vc90-mt-gd-1_46_1.dll) get linked into my project?

Any help would be appreciated because I'm becoming desperate. It can't really be that hard...

PS. this TopDir I set is so that I can include the .h file from the Utilities. But I'm sure there must be a cleaner way to do it or?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

手心的海 2024-11-25 23:46:05

我的猜测是您仍在自动链接:在 MSVC 上,boost 使用一些编译指示自动指示编译器链接到必要的库,然后无需向链接器手动指定所有链接目标。当然,这会影响 CMake 的依赖解析,并且您手动指定 target_link_libraries。

看看我的对一个问题的回答类似的问题,我建议使用以下额外定义来禁用自动链接:

add_definition( -DBOOST_ALL_NO_LIB )

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

add_definitions( -DBOOST_ALL_DYN_LINK )

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

target_link_libraries( ${Boost_LIBRARIES} )

My guess is that you are still auto-linking: On MSVC, boost uses some pragma's to automically instruct the compiler to link to the necessary libraries and there is then no need to specify all the link-targets manually to the linker. Of course, this bites with the dependency-resolution of CMake and you specifying target_link_libraries manually.

Take a look at my answer to a similar question where I suggested the following extra definition to disable auto-linking:

add_definition( -DBOOST_ALL_NO_LIB )

You may need to add the following when linking dynamically and depending on the Boost version and the components:

add_definitions( -DBOOST_ALL_DYN_LINK )

Note also that you specify the Boost components you want in the find_package() call and then specify them again manually in your target_link_libraries() call. Depending a bit on your need, you could also replace this with

target_link_libraries( ${Boost_LIBRARIES} )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文