Подтвердить что ты не робот

Установка времени выполнения MSVC в CMake

Я следую инструкциям в разделе часто задаваемых вопросов CMake "Как я могу создать свое приложение MSVC со статической средой выполнения?" централизовать выбор среды выполнения MSVC для нескольких вложенных проектов CMake (они извлекаются как подмодули Git и добавляются в главный проект с помощью директивы CMake find_package()).

Итак, я написал этот макрос CMake:

macro(configure_msvc_runtime)
  if(MSVC)

    # Default to statically-linked runtime.
    if("${MSVC_RUNTIME}" STREQUAL "")
      set(MSVC_RUNTIME "static")
    endif()

    # Set compiler options.
    set(variables
      CMAKE_C_FLAGS_DEBUG
      CMAKE_C_FLAGS_MINSIZEREL
      CMAKE_C_FLAGS_RELEASE
      CMAKE_C_FLAGS_RELWITHDEBINFO
      CMAKE_CXX_FLAGS_DEBUG
      CMAKE_CXX_FLAGS_MINSIZEREL
      CMAKE_CXX_FLAGS_RELEASE
      CMAKE_CXX_FLAGS_RELWITHDEBINFO
    )
    if(${MSVC_RUNTIME} STREQUAL "static")
      message(STATUS
        "MSVC -> forcing use of statically-linked runtime."
      )
      foreach(variable ${variables})
        if(${variable} MATCHES "/MD")
          string(REGEX REPLACE "/MD" "/MT" ${variable} "${${variable}}")
        endif()
      endforeach()
    else()
      message(STATUS
        "MSVC -> forcing use of dynamically-linked runtime."
      )
      foreach(variable ${variables})
        if(${variable} MATCHES "/MT")
          string(REGEX REPLACE "/MT" "/MD" ${variable} "${${variable}}")
        endif()
      endforeach()
    endif()
  endif()
endmacro()

Я вызываю этот макрос в начале моего корневого CMakeLists.txt (до выполнения любого add_library() или add_executable()) и добавляю немного отладочных отпечатков:

configure_msvc_runtime()
set(variables
  CMAKE_C_FLAGS_DEBUG
  CMAKE_C_FLAGS_MINSIZEREL
  CMAKE_C_FLAGS_RELEASE
  CMAKE_C_FLAGS_RELWITHDEBINFO
  CMAKE_CXX_FLAGS_DEBUG
  CMAKE_CXX_FLAGS_MINSIZEREL
  CMAKE_CXX_FLAGS_RELEASE
  CMAKE_CXX_FLAGS_RELWITHDEBINFO
)
message(STATUS "Initial build flags:")
foreach(variable ${variables})
  message(STATUS "  '${variable}': ${${variable}}")
endforeach()
message(STATUS "")

Затем я запускаю CMake для генерации решения Visual Studio следующим образом:

cmake -G "Visual Studio 9 2008" ..\.. -DMSVC_RUNTIME=dynamic

и я получаю следующие выводы:

-- MSVC -> forcing use of dynamically-linked runtime.
-- Initial build flags:
--   'CMAKE_C_FLAGS_DEBUG': /D_DEBUG /MDd /Zi  /Ob0 /Od /RTC1
--   'CMAKE_C_FLAGS_MINSIZEREL': /MD /O1 /Ob1 /D NDEBUG
--   'CMAKE_C_FLAGS_RELEASE': /MD /O2 /Ob2 /D NDEBUG
--   'CMAKE_C_FLAGS_RELWITHDEBINFO': /MD /Zi /O2 /Ob1 /D NDEBUG
--   'CMAKE_CXX_FLAGS_DEBUG': /D_DEBUG /MDd /Zi /Ob0 /Od /RTC1
--   'CMAKE_CXX_FLAGS_MINSIZEREL': /MD /O1 /Ob1 /D NDEBUG
--   'CMAKE_CXX_FLAGS_RELEASE': /MD /O2 /Ob2 /D NDEBUG
--   'CMAKE_CXX_FLAGS_RELWITHDEBINFO': /MD /Zi /O2 /Ob1 /D NDEBUG

Дело в том, что когда я запускаю Visual Studio и проверяю свойства проекта в разделе "C/C++, Генерация кода", я вижу, что параметр "Библиотека времени выполнения" не согласуется с параметрами, напечатанными в оболочке. В конфигурациях "Release", "MinSizeRel" и "RelWithDebInfo" я получаю ожидаемые результаты ("Многопоточная DLL/MD", но в конфигурации "Debug" по-прежнему отображается "Многопоточная /MT").

Кроме того, когда я принудительно использую статически связанную среду выполнения, я получаю аналогичные результаты. Если я бегу

cmake -G "Visual Studio 9 2008" ..\.. -DMSVC_RUNTIME=static

Я получаю следующие выводы:

-- MSVC -> forcing use of statically-linked runtime.
-- Initial build flags:
--   'CMAKE_C_FLAGS_DEBUG': /D_DEBUG /MTd /Zi  /Ob0 /Od /RTC1
--   'CMAKE_C_FLAGS_MINSIZEREL': /MT /O1 /Ob1 /D NDEBUG
--   'CMAKE_C_FLAGS_RELEASE': /MT /O2 /Ob2 /D NDEBUG
--   'CMAKE_C_FLAGS_RELWITHDEBINFO': /MT /Zi /O2 /Ob1 /D NDEBUG
--   'CMAKE_CXX_FLAGS_DEBUG': /D_DEBUG /MTd /Zi /Ob0 /Od /RTC1
--   'CMAKE_CXX_FLAGS_MINSIZEREL': /MT /O1 /Ob1 /D NDEBUG
--   'CMAKE_CXX_FLAGS_RELEASE': /MT /O2 /Ob2 /D NDEBUG
--   'CMAKE_CXX_FLAGS_RELWITHDEBINFO': /MT /Zi /O2 /Ob1 /D NDEBUG

И все же все конфигурации выдают значение "Многопоточный /MT" для параметра "Библиотека времени выполнения".

Что я делаю не так, или это ошибка в CMake (2.8.7) или что-то в этом роде?


Для чего стоит, если я сгенерирую файлы проекта Visual Studio 2010, я получу другое значение для конфигурации "Отладка", но все равно не то, которое я выбрал.

Во всех случаях параметр отображается обычным шрифтом для конфигурации "Отладка", тогда как для других конфигураций он выделяется жирным шрифтом, указывая на то, что это переопределения. Более того, если я открою файлы проекта XML, то обнаружу, что в конфигурации "Отладка" нет настройки для атрибута "RuntimeLibrary" элемента "Инструмент" с атрибутом "Name = VCCLCompilerTool". Все остальные конфигурации имеют явную настройку.

4b9b3361

Ответ 1

Кажется, все время, пока я работал над этим, я забыл удалить неправильную конфигурацию CMake, которую я пытаюсь заменить.

Далее, вниз по сценарию сборки, я оставил небольшую ошибку:

set(CMAKE_CXX_FLAGS_DEBUG
  "/DWIN32 /D_WINDOWS /EHsc /WX /wd4355 /wd4251 /wd4250 /wd4996"
  CACHE STRING "Debug compiler flags" FORCE
)

По сути, я переопределял результаты макроса configure_msvc_runtime() с флагами сборки, которые не устанавливали время выполнения MSVC.

Ответ 2

Я взял ваш код и обобщил его для работы для каждой существующей конфигурации, а не только для Debug/Release/RelWithDebInfo/MinSizeRel.

Также я сделал это для работы с gcc - проверьте здесь

Ответ 3

Эта функциональность будет улучшена с выпуском cmake-3.15.

Необходимо установить CMAKE_MSVC_RUNTIME_LIBRARY, например (из docs), для установки "многопоточной статически связанной библиотеки времени выполнения с отладочной информацией или без нее в зависимости от конфигурации":

set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")