Как добавить флаги компиляции в cmake на Windows?

Я написал проект с использованием CMake (с компилятором ninja и Visual Studio 2017 C++) с двумя модулями lib_A и lib_B

  • lib_B зависит от одного lib_A.
  • И lib_B, и lib_A определяют std::vector < size_t >.

Наконец, компилятор сказал мне: LNK2005 lib_A: std::vector < size_t > already defined in lib_B

Я искал ответы, и они дали решение добавить флаг ссылки /FORCE:MULTIPLE, page1 и page2 .

Я пробовал все это, но ни один из них не работает.


  1. Используйте target_link_libraries

    • with 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. Use CMAKE_EXE_LINKER_FLAGS
    • withset(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, компилятор сообщит мне аналогичный результат.

Кто-нибудь может мне помочь? Добавляет ли ссылку флаг с какой-либо ошибкой?


person Laine    schedule 19.09.2019    source источник


Ответы (2)


Вы можете использовать target_link_options в CMake ≥ 3.13 или set_target_properties со свойством LINK_FLAGS ранее.

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

Это также использует выражения генератора только для применения флаг для MSVC.

Но похоже, что обе ваши библиотеки являются общими (DLL), но вы статически связываете среду выполнения с обеими. Я не думаю, что это хорошая идея.

Попробуйте либо связать динамическую среду выполнения для обеих библиотек, если вы хотите динамически связать их, либо использовать статическую среду выполнения, но также создать обе библиотеки как статическую библиотеку.

person Darklighter    schedule 19.09.2019
comment
кстати, что ты имеешь в виду под statically linking the runtime to both? Связывается ли target_link_libraries(lib_B lib_A) статически? Тогда как связать динамически? - person Laine; 04.04.2020
comment
@Laine, возможно, я неправильно понял, в чем была проблема. Я предположил, что вы получили несколько определений из-за нескольких конфликтующих стандартных библиотек. Возможно, вместо этого у вас есть переменная с одинаковым именем в обеих библиотеках? - person Darklighter; 06.04.2020
comment
Нет, вы не поняли меня неправильно. Я использую typedef в lib_A и ссылаюсь на класс typedefed в lib_B, но msvc сказал мне LNK1169, то есть класс ** уже определен в lib_A. И что самое странное, два класса использовали класс typedefed, но только один получил ошибку LNK1169. - person Laine; 08.04.2020
comment
@Laine Я пытался проверить, не должно ли что-то подобное работать, но ваши утверждения все еще слишком малы / неточны, чтобы можно было определить, действительно ли msvc ошибочно создает что-то для typedef здесь или есть конфликтующие определения из стандарта С++ POV в вашей настройке. В своем вопросе вы можете уточнить типы, переменные и включения, о которых идет речь. - person Darklighter; 20.04.2020

Добавление следующей строки помогло мне:

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /FORCE:MULTIPLE") 
person Aleph0    schedule 19.09.2019
comment
хотя это работает, использование этих глобальных флагов несколько устарело - person Darklighter; 19.09.2019
comment
@Darklighter: мы используем эти флаги, чтобы глобально устанавливать одинаковые флаги для всех проектов. Но я также рассмотрю target_link_options как альтернативу. Спасибо за комментарий. - person Aleph0; 19.09.2019
comment
@Alepho код у меня не работает. Я попробовал другой способ явным экспортом с помощью template class MyExports std::vector < size_t >. Затем ошибки компиляции в настоящее время исчезают. - person Laine; 19.09.2019