1

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?

Kevin
  • 16,549
  • 8
  • 60
  • 74
Laine
  • 179
  • 1
  • 8

2 Answers2

3

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.

Darklighter
  • 2,082
  • 1
  • 16
  • 21
  • by the way, waht do you mean by `statically linking the runtime to both`? Does `target_link_libraries(lib_B lib_A)` linking statically? Then how to link dynamically ? – Laine Apr 04 '20 at 03:37
  • @Laine i may have misunderstood what the actual issue was. I assumed your getting multiple definitions was due to several conflicting standard libraries. Do you maybe instead have a variable with the same name in both libraries? – Darklighter Apr 06 '20 at 17:11
  • No, you didn't misunderstand me. I use `typedef` in `lib_A`, and refer the `typedef`ed class in `lib_B`, but msvc told me `LNK1169`, i.e., the `**` class already defined in `lib_A`. And what the most wierd is, two classes used the `typedef`ed class, but only one got the `LNK1169` error. – Laine Apr 08 '20 at 09:20
  • @Laine i tried to test if something like this not supposed to work, but your statements are still too little/inexact info to be able to tell if msvc actually erroneously instantiates something for a typedef here or if there are conflicting definitions from a c++ standard POV in your setup. You could elaborate on the types, variables and includes in question, in your question. – Darklighter Apr 20 '20 at 01:07
0

Adding the following line worked for me:

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE") 
Aleph0
  • 5,816
  • 4
  • 29
  • 80
  • 1
    although it works, using those global flags is somewhat antiquated – Darklighter Sep 19 '19 at 12:18
  • @Darklighter: We are using these flags to globally set the same flags for all projects. But, I'll also consider `target_link_options` as an alternate. Thanks for the comment. – Aleph0 Sep 19 '19 at 12:21
  • @Alepho the code doesn't work for me. I tried another way by explicit export with ```template class MyExports std::vector < size_t >```. Then the compile errors disappers currently. – Laine Sep 19 '19 at 14:05