HomeBlogMagic

CMake Visual Studio Redistributables

Wer mit Visual Studio und C++ Software schreibt wird wohl oder übel einmal den Pfad zu den passenden Redistributables brauchen.

Mit Cmake kann man sich die ganz einfach auslesen lassen:

set(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE)
set(CMAKE_INSTALL_UCRT_LIBRARIES  TRUE)
include(InstallRequiredSystemLibraries)

if(MSVC_CRT_DIR)
  message("Visual Studio runtimes found at ${MSVC_CRT_DIR}")
endif()

Im Anschluss kann man die notwendigen redists z.B. in die notwendigen Verzeichnisse kopieren.

if(MSVC_CRT_DIR)
  message("Visual Studio runtimes found at ${MSVC_CRT_DIR}")
  file(COPY "${MSVC_CRT_DIR}/vcruntime140d.dll"                         ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/vccorlib140d.dll"                          ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/msvcp140d.dll"                             ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/concrt140d.dll"                            ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/../Microsoft.VC141.DebugMFC/mfc140ud.dll"  ${TARGET_DIR})
  if(WINDOWS_KITS_DIR)
    file(COPY "${WINDOWS_KITS_DIR}/bin/x64/ucrt/ucrtbased.dll"          ${TARGET_DIR})
  endif()
endif()

Wenn man den Pfad hat könnte man diese auch dem install Prozess hinzufügen.

ucrtbased mit Versionsnummern

Nach ein paar Updates von Visual Studio hat der Pfad zur ucrtbased eine Versionsnummer bekommen. Deshalb lasse ich mir mit Cmake alle Pfade suchen und nehme mir den mit der neuesten Versionsnummer:

if(WINDOWS_KITS_DIR)
  # Default location for ucrtbased
  set(UCRTBASED_DLL_PATH "${WINDOWS_KITS_DIR}/bin/x64/ucrt")
  if(NOT EXISTS "${UCRTBASED_DLL_PATH}/ucrtbased.dll")
    # ucrt not found search in kits
    file(GLOB UCRTBASED_DLL_PATHS
        "${WINDOWS_KITS_DIR}/*/x64/ucrt/ucrtbased.dll"
    )
    if(UCRTBASED_DLL_PATHS)
      # ucrt paths found, select newest
      list(GET UCRTBASED_DLL_PATHS -1 UCRTBASED_DLL_FULLPATH)
      # extract path of file
      get_filename_component(UCRTBASED_DLL_PATH ${UCRTBASED_DLL_FULLPATH} DIRECTORY)
    endif()
  endif()
  message("ucrtbased available in ${UCRTBASED_DLL_PATH}/ucrtbased.dll")
endif()

Im Anschluss kann mit der Variable UCRTBASED_DLL_PATH der Pfad zur ucrtbased genutzt werden.
Hier das ehemalige Beispiel erweitert:

if(MSVC_CRT_DIR)
  message("Visual Studio runtimes found at ${MSVC_CRT_DIR}")
  file(COPY "${MSVC_CRT_DIR}/vcruntime140d.dll"                         ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/vccorlib140d.dll"                          ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/msvcp140d.dll"                             ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/concrt140d.dll"                            ${TARGET_DIR})
  file(COPY "${MSVC_CRT_DIR}/../Microsoft.VC141.DebugMFC/mfc140ud.dll"  ${TARGET_DIR})
  if(UCRTBASED_DLL_PATH)
    file(COPY "${UCRTBASED_DLL_PATH}/ucrtbased.dll"          ${TARGET_DIR})
  endif()
endif()