From c810f071cdd7d427b0145b804a0812b9ce4b4d0a Mon Sep 17 00:00:00 2001 From: kervala Date: Thu, 26 Sep 2013 22:49:30 +0200 Subject: [PATCH] Changed: Improved Windows SDK detection --- code/CMakeModules/FindWindowsSDK.cmake | 195 ++++++++++++++++++++----- 1 file changed, 157 insertions(+), 38 deletions(-) diff --git a/code/CMakeModules/FindWindowsSDK.cmake b/code/CMakeModules/FindWindowsSDK.cmake index 1b2affb99..4b8556398 100644 --- a/code/CMakeModules/FindWindowsSDK.cmake +++ b/code/CMakeModules/FindWindowsSDK.cmake @@ -11,6 +11,7 @@ IF(WINSDK_FOUND) RETURN() ENDIF(WINSDK_FOUND) +# Values can be CURRENT or any existing versions 7.1, 8.0A, etc... SET(WINSDK_VERSION "CURRENT" CACHE STRING "Windows SDK version to prefer") MACRO(DETECT_WINSDK_VERSION_HELPER _ROOT _VERSION) @@ -22,7 +23,7 @@ MACRO(DETECT_WINSDK_VERSION_HELPER _ROOT _VERSION) IF(NOT WindowsSDK_FIND_QUIETLY) MESSAGE(STATUS "Found Windows SDK ${_VERSION} in ${WINSDK${_VERSION}_DIR}") ENDIF(NOT WindowsSDK_FIND_QUIETLY) - ELSEIF(WINSDK${_VERSION}_DIR AND NOT WINSDK${_VERSION}_DIR STREQUAL "/registry") + ELSE(WINSDK${_VERSION}_DIR AND NOT WINSDK${_VERSION}_DIR STREQUAL "/registry") SET(WINSDK${_VERSION}_DIR "") ENDIF(WINSDK${_VERSION}_DIR AND NOT WINSDK${_VERSION}_DIR STREQUAL "/registry") ENDMACRO(DETECT_WINSDK_VERSION_HELPER) @@ -30,17 +31,22 @@ ENDMACRO(DETECT_WINSDK_VERSION_HELPER) MACRO(DETECT_WINSDK_VERSION _VERSION) SET(WINSDK${_VERSION}_FOUND OFF) DETECT_WINSDK_VERSION_HELPER("HKEY_CURRENT_USER" ${_VERSION}) - + IF(NOT WINSDK${_VERSION}_FOUND) DETECT_WINSDK_VERSION_HELPER("HKEY_LOCAL_MACHINE" ${_VERSION}) ENDIF(NOT WINSDK${_VERSION}_FOUND) ENDMACRO(DETECT_WINSDK_VERSION) -SET(WINSDK_VERSIONS "8.0" "8.0A" "7.1" "7.0A" "6.1" "6.0" "6.0A") +SET(WINSDK_VERSIONS "8.0" "8.0A" "7.1" "7.1A" "7.0" "7.0A" "6.1" "6.0" "6.0A") +SET(WINSDK_DETECTED_VERSIONS) # Search all supported Windows SDKs FOREACH(_VERSION ${WINSDK_VERSIONS}) DETECT_WINSDK_VERSION(${_VERSION}) + + IF(WINSDK${_VERSION}_FOUND) + LIST(APPEND WINSDK_DETECTED_VERSIONS ${_VERSION}) + ENDIF(WINSDK${_VERSION}_FOUND) ENDFOREACH(_VERSION) SET(WINSDK_SUFFIX) @@ -54,51 +60,164 @@ ELSEIF(TARGET_X86) SET(WINSDK8_SUFFIX "x86") ENDIF(TARGET_ARM) -GET_FILENAME_COMPONENT(WINSDKCURRENT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentVersion]" NAME) +GET_FILENAME_COMPONENT(WINSDKCURRENT_VERSION_REGISTRY "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentVersion]" NAME) -IF(WINSDKCURRENT_VERSION AND NOT WINSDKCURRENT_VERSION STREQUAL "/registry") +IF(WINSDKCURRENT_VERSION_REGISTRY AND NOT WINSDKCURRENT_VERSION_REGISTRY STREQUAL "/registry") IF(NOT WindowsSDK_FIND_QUIETLY) -# MESSAGE(STATUS "Current version is ${WINSDKCURRENT_VERSION}") +# MESSAGE(STATUS "Current version is ${WINSDKCURRENT_VERSION_REGISTRY}") ENDIF(NOT WindowsSDK_FIND_QUIETLY) -ENDIF(WINSDKCURRENT_VERSION AND NOT WINSDKCURRENT_VERSION STREQUAL "/registry") +ENDIF(WINSDKCURRENT_VERSION_REGISTRY AND NOT WINSDKCURRENT_VERSION_REGISTRY STREQUAL "/registry") + +SET(WINSDKCURRENT_VERSION_INCLUDE $ENV{INCLUDE}) + +IF(WINSDKCURRENT_VERSION_INCLUDE) + FILE(TO_CMAKE_PATH "${WINSDKCURRENT_VERSION_INCLUDE}" WINSDKCURRENT_VERSION_INCLUDE) +ENDIF(WINSDKCURRENT_VERSION_INCLUDE) SET(WINSDKENV_DIR $ENV{WINSDK_DIR}) +MACRO(FIND_WINSDK_VERSION_HEADERS) + IF(WINSDK_DIR AND NOT WINSDK_VERSION) + # Search version in headers + IF(EXISTS ${WINSDK_DIR}/include/Msi.h) + SET(_MSI_FILE ${WINSDK_DIR}/include/Msi.h) + ENDIF(EXISTS ${WINSDK_DIR}/include/Msi.h) + + IF(_MSI_FILE) + # Look for Windows SDK 8.0 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WIN8") + + IF(_CONTENT) + SET(WINSDK_VERSION "8.0") + ENDIF(_CONTENT) + + IF(NOT WINSDK_VERSION) + # Look for Windows SDK 7.0 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WIN7") + + IF(_CONTENT) + IF(EXISTS ${WINSDK_DIR}/include/winsdkver.h) + SET(_WINSDKVER_FILE ${WINSDK_DIR}/include/winsdkver.h) + ELSEIF(EXISTS ${WINSDK_DIR}/include/WinSDKVer.h) + SET(_WINSDKVER_FILE ${WINSDK_DIR}/include/WinSDKVer.h) + ENDIF(EXISTS ${WINSDK_DIR}/include/winsdkver.h) + + IF(_WINSDKVER_FILE) + # Load WinSDKVer.h content + FILE(STRINGS ${_WINSDKVER_FILE} _CONTENT REGEX "^#define NTDDI_MAXVER") + + # Get NTDDI_MAXVER value + STRING(REGEX REPLACE "^.*0x([0-9A-Fa-f]+).*$" "\\1" _WINSDKVER "${_CONTENT}") + + # In Windows SDK 7.1, NTDDI_MAXVER is wrong + IF(_WINSDKVER STREQUAL "06010000") + SET(WINSDK_VERSION "7.1") + ELSEIF(_WINSDKVER STREQUAL "0601") + SET(WINSDK_VERSION "7.0A") + ELSE(_WINSDKVER STREQUAL "06010000") + MESSAGE(FATAL_ERROR "Can't determine Windows SDK version with NTDDI_MAXVER 0x${_WINSDKVER}") + ENDIF(_WINSDKVER STREQUAL "06010000") + ELSE(_WINSDKVER_FILE) + SET(WINSDK_VERSION "7.0") + ENDIF(_WINSDKVER_FILE) + ENDIF(_CONTENT) + ENDIF(NOT WINSDK_VERSION) + + IF(NOT WINSDK_VERSION) + # Look for Windows SDK 6.0 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_VISTA") + + IF(_CONTENT) + SET(WINSDK_VERSION "6.0") + ENDIF(_CONTENT) + ENDIF(NOT WINSDK_VERSION) + + IF(NOT WINSDK_VERSION) + # Look for Windows SDK 5.2 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WS03SP1") + + IF(_CONTENT) + SET(WINSDK_VERSION "5.2") + ENDIF(_CONTENT) + ENDIF(NOT WINSDK_VERSION) + + IF(NOT WINSDK_VERSION) + # Look for Windows SDK 5.1 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WINXP") + + IF(_CONTENT) + SET(WINSDK_VERSION "5.1") + ENDIF(_CONTENT) + ENDIF(NOT WINSDK_VERSION) + + IF(NOT WINSDK_VERSION) + # Look for Windows SDK 5.0 + FILE(STRINGS ${_MSI_FILE} _CONTENT REGEX "^#ifndef NTDDI_WIN2K") + + IF(_CONTENT) + SET(WINSDK_VERSION "5.0") + ENDIF(_CONTENT) + ENDIF(NOT WINSDK_VERSION) + ELSE(_MSI_FILE) + MESSAGE(FATAL_ERROR "Unable to find Msi.h in ${WINSDK_DIR}") + ENDIF(_MSI_FILE) + ENDIF(WINSDK_DIR AND NOT WINSDK_VERSION) +ENDMACRO(FIND_WINSDK_VERSION_HEADERS) + MACRO(USE_CURRENT_WINSDK) - IF(WINSDKENV_DIR) - SET(WINSDK_VERSION "") - SET(WINSDK_VERSION_FULL "") + SET(WINSDK_DIR "") + SET(WINSDK_VERSION "") + SET(WINSDK_VERSION_FULL "") + + # Use WINSDK environment variable + IF(WINSDKENV_DIR AND EXISTS ${WINSDKENV_DIR}/include/Windows.h) SET(WINSDK_DIR ${WINSDKENV_DIR}) - FOREACH(_VERSION ${WINSDK_VERSIONS}) - IF(WINSDK_DIR STREQUAL WINSDK${_VERSION}_DIR) - SET(WINSDK_VERSION ${_VERSION}) - SET(WINSDK_VERSION_FULL "${WINSDK${_VERSION}_VERSION_FULL}") + ENDIF(WINSDKENV_DIR AND EXISTS ${WINSDKENV_DIR}/include/Windows.h) + + # Use INCLUDE environment variable + IF(NOT WINSDK_DIR AND WINSDKCURRENT_VERSION_INCLUDE) + FOREACH(_INCLUDE ${WINSDKCURRENT_VERSION_INCLUDE}) + FILE(TO_CMAKE_PATH ${_INCLUDE} _INCLUDE) + + # Look for Windows.h because there are several paths + IF(EXISTS ${_INCLUDE}/Windows.h) + STRING(REGEX REPLACE "/(include|INCLUDE|Include)" "" WINSDK_DIR ${_INCLUDE}) + MESSAGE(STATUS "Found Windows SDK environment variable in ${WINSDK_DIR}") BREAK() - ENDIF(WINSDK_DIR STREQUAL WINSDK${_VERSION}_DIR) + ENDIF(EXISTS ${_INCLUDE}/Windows.h) + ENDFOREACH(_INCLUDE) + ENDIF(NOT WINSDK_DIR AND WINSDKCURRENT_VERSION_INCLUDE) + + IF(WINSDK_DIR) + # Compare WINSDK_DIR with registered Windows SDKs + FOREACH(_VERSION ${WINSDK_DETECTED_VERSIONS}) + IF(WINSDK_DIR STREQUAL "${WINSDK${_VERSION}_DIR}") + SET(WINSDK_VERSION ${_VERSION}) + SET(WINSDK_VERSION_FULL "${WINSDK${WINSDK_VERSION}_VERSION_FULL}") + BREAK() + ENDIF(WINSDK_DIR STREQUAL "${WINSDK${_VERSION}_DIR}") ENDFOREACH(_VERSION) - ELSE(WINSDKENV_DIR) - # Windows SDK 7.0A doesn't provide 64bits compilers, use SDK 7.1 for 64 bits - IF(WINSDKCURRENT_VERSION STREQUAL WINSDK7.0A_VERSION_FULL) - IF(TARGET_X64) - SET(WINSDK_VERSION "7.1") - SET(WINSDK_VERSION_FULL ${WINSDK7.1_VERSION_FULL}) - SET(WINSDK_DIR ${WINSDK7.1_DIR}) - ELSE(TARGET_X64) - SET(WINSDK_VERSION "7.0A") - SET(WINSDK_VERSION_FULL ${WINSDK7.0A_VERSION_FULL}) - SET(WINSDK_DIR ${WINSDK7.0A_DIR}) - ENDIF(TARGET_X64) - ELSE(WINSDKCURRENT_VERSION STREQUAL WINSDK7.0A_VERSION_FULL) - FOREACH(_VERSION ${WINSDK_VERSIONS}) - IF(WINSDKCURRENT_VERSION STREQUAL WINSDK${_VERSION}_VERSION) - SET(WINSDK_VERSION ${_VERSION}) - SET(WINSDK_VERSION_FULL "${WINSDK${_VERSION}_VERSION_FULL}") - SET(WINSDK_DIR "${WINSDK${_VERSION}_DIR}") - BREAK() - ENDIF(WINSDKCURRENT_VERSION STREQUAL WINSDK${_VERSION}_VERSION) - ENDFOREACH(_VERSION) - ENDIF(WINSDKCURRENT_VERSION STREQUAL WINSDK7.0A_VERSION_FULL) - ENDIF(WINSDKENV_DIR) + + FIND_WINSDK_VERSION_HEADERS() + ENDIF(WINSDK_DIR) + + # Use Windows SDK currently used by Visual C++ + IF(NOT WINSDK_DIR AND WINSDKCURRENT_VERSION_REGISTRY) + IF(WINSDKCURRENT_VERSION_REGISTRY STREQUAL WINSDK7.0A_VERSION_FULL AND TARGET_X64) + # Windows SDK 7.0A doesn't provide 64bits compilers, use SDK 7.1 for 64 bits + SET(WINSDKCURRENT_VERSION_REGISTRY "${WINSDK7.1_VERSION_FULL}") + ENDIF(WINSDKCURRENT_VERSION_REGISTRY STREQUAL WINSDK7.0A_VERSION_FULL AND TARGET_X64) + + # Look for correct registered Windows SDK version + FOREACH(_VERSION ${WINSDK_DETECTED_VERSIONS}) + IF(WINSDKCURRENT_VERSION_REGISTRY STREQUAL WINSDK${_VERSION}_VERSION_FULL) + SET(WINSDK_VERSION ${_VERSION}) + SET(WINSDK_VERSION_FULL "${WINSDK${WINSDK_VERSION}_VERSION_FULL}") + SET(WINSDK_DIR "${WINSDK${WINSDK_VERSION}_DIR}") + BREAK() + ENDIF(WINSDKCURRENT_VERSION_REGISTRY STREQUAL WINSDK${_VERSION}_VERSION_FULL) + ENDFOREACH(_VERSION) + ENDIF(NOT WINSDK_DIR AND WINSDKCURRENT_VERSION_REGISTRY) ENDMACRO(USE_CURRENT_WINSDK) IF(WINSDK_VERSION STREQUAL "CURRENT")