【问题标题】:How to add compile flags in cmake on windows?如何在 Windows 上的 cmake 中添加编译标志?
【发布时间】:2019-09-19 09:50:40
【问题描述】:

我使用 CMake(使用 ninja 和 Visual Studio 2017 C++ 编译器)编写了一个项目,其中包含两个模块 lib_Alib_B

  • lib_B 依赖于一个 lib_A
  • lib_Blib_A 都定义了 std::vector < size_t >

最后,编译器告诉我:LNK2005 lib_A: std::vector < size_t > already defined in lib_B

我搜索了答案,他们给出了添加链接标志/FORCE:MULTIPLEpage1page2的解决方案。

我尝试了所有这些,但它们都不起作用。


  1. 使用target_link_libraries

    • target_link_libraries(lib_B lib_A INTERFACE "/FORCE:MULTIPLE")
    • 编译器告诉我The INTERFACE, PUBLIC or PRIVATE option must appear as the second argument, just after the target name.

    • target_link_libraries(lib_B INTERFACE "/FORCE:MULTIPLE" lib_A )

    • 编译器告诉我ninja: error: '/FORCE:MULTIPLE', needed by 'lib_B', missing and no known rule to make it

  1. 使用CMAKE_EXE_LINKER_FLAGS
    • set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "/FORCE:MULTIPLE")
    • 编译告诉我LINK : warning LNK4012: value “x64;/FORCE:MULTIPLE” is invalid, must be one of "ARM, EBC, HYBRID_X86_ARM64X64, or X86" omit this option"

  1. 使用set_target_properties 使用 CMake 代码
get_target_property(TEMP lib_B COMPILE_FLAGS)
if(TEMP STREQUAL "TEMP-NOTFOUND")
  SET(TEMP "") # Set to empty string
else()
  SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
endif()
# Append our values
SET(TEMP "${TEMP} /FORCE:MULTIPLE" )
set_target_properties(lib_B PROPERTIES COMPILE_FLAGS ${TEMP} )

编译器告诉我cl: command line error D8021 : invalid parameter "/FORCE:MULTIPLE"


如果我将/FORCE:MULTIPLE 更改为-Wl,--allow-multiple-definition,编译器会告诉我类似的结果。

谁能帮帮我? 添加链接标志是否有任何错误?

【问题讨论】:

    标签: windows visual-studio cmake compiler-flags ninja


    【解决方案1】:

    您可以在 CMake ≥ 3.13 或 set_target_properties 之前使用 target_link_optionsLINK_FLAGS 属性。

    target_link_options(${PROJECT_NAME} PUBLIC $<$<CXX_COMPILER_ID:MSVC>:/FORCE:MULTIPLE>)

    这也使用generator expressions 只为 MSVC 应用标志。

    但您的两个库似乎都是共享的 (DLL),但您将运行时静态链接到两者。 我不认为这是个好主意。

    如果您想动态链接到两个库,请尝试为两个库动态链接到运行时,或者使用静态运行时但也将两个库构建为静态库。

    【讨论】:

    • 顺便问一下,statically linking the runtime to both 是什么意思? target_link_libraries(lib_B lib_A) 是否静态链接?那么如何动态链接呢?
    • @Laine 我可能误解了实际问题是什么。我认为您获得多个定义是由于几个相互冲突的标准库。您是否可能在两个库中都有一个同名的变量?
    • 不,你没有误解我的意思。我在lib_A 中使用typedef,并在lib_B 中引用typedefed 类,但msvc 告诉我LNK1169,即** 类已经在lib_A 中定义。最奇怪的是,有两个类使用了typedefed 类,但只有一个得到了LNK1169 错误。
    • @Laine 我试图测试这样的事情是否不应该工作,但你的陈述仍然太少/不准确的信息,无法判断 msvc 是否真的在这里错误地为 typedef 实例化了一些东西,或者如果您的设置中存在来自 c++ 标准 POV 的冲突定义。您可以在问题中详细说明类型、变量和包含问题。
    【解决方案2】:

    添加以下行对我有用:

    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE") 
    

    【讨论】:

    • 虽然可行,但使用这些全局标志有点过时了
    • @Darklighter:我们正在使用这些标志为所有项目全局设置相同的标志。但是,我也会考虑将target_link_options 作为替代方案。感谢您的评论。
    • @Alepho 该代码对我不起作用。我尝试了另一种方法,使用template class MyExports std::vector < size_t > 显式导出。然后编译错误当前消失。
    猜你喜欢
    • 2019-03-11
    • 2019-02-02
    • 1970-01-01
    • 2010-12-13
    • 2020-03-12
    相关资源
    最近更新 更多