Search code examples
windowsvisual-studiocmakecompiler-flagsninja

How to add compile flags in cmake on windows?


I wrote a project using CMake (with ninja and Visual Studio 2017 C++ compiler), with two modules lib_A and lib_B

  • lib_B depends one lib_A.
  • Both lib_B and lib_A define std::vector < size_t >.

Finally, the compiler told me: LNK2005 lib_A: std::vector < size_t > already defined in lib_B

I searched answers, and they gave the solution to add link flag /FORCE:MULTIPLE, page1 and page2.

I tried all these, but none of them work.


  1. Use target_link_libraries

    • with target_link_libraries(lib_B lib_A INTERFACE "/FORCE:MULTIPLE")
    • compiler tells me The INTERFACE, PUBLIC or PRIVATE option must appear as the second argument, just after the target name.

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

    • compiler tells me ninja: error: '/FORCE:MULTIPLE', needed by 'lib_B', missing and no known rule to make it

  1. Use CMAKE_EXE_LINKER_FLAGS
    • withset(CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS} "/FORCE:MULTIPLE")
    • compile tells me LINK : warning LNK4012: value “x64;/FORCE:MULTIPLE” is invalid, must be one of "ARM, EBC, HYBRID_X86_ARM64X64, or X86" omit this option"

  1. Use set_target_properties with CMake code
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} )

The compiler tells me cl: command line error D8021 : invalid parameter "/FORCE:MULTIPLE"


If I change /FORCE:MULTIPLE to -Wl,--allow-multiple-definition, compiler tells me similar result.

Could anyone help me? Does add link flag with any error?


Solution

  • You can use target_link_options in CMake ≥ 3.13 or set_target_properties with the LINK_FLAGS property before.

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

    This also uses generator expressions to only apply the flag for MSVC.

    But it seems like both your libraries are shared (DLL), but you are statically linking the runtime to both. I don’t think that that’s a good idea.

    Try either linking to the runtime dynamically for both libs if you want to dynamically link to them, or use the static runtime but build both libraries as static library too.