CMakeDetermineCompilerId.cmake 32.4 KB
Newer Older
1 2
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
3

4

5
# Function to compile a source file to identify the compiler.  This is
6
# used internally by CMake and should not be included by user code.
7 8
# If successful, sets CMAKE_<lang>_COMPILER_ID and CMAKE_<lang>_PLATFORM_ID

9
function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
10
  # Make sure the compiler arguments are clean.
11 12
  string(STRIP "${CMAKE_${lang}_COMPILER_ARG1}" CMAKE_${lang}_COMPILER_ID_ARG1)
  string(REGEX REPLACE " +" ";" CMAKE_${lang}_COMPILER_ID_ARG1 "${CMAKE_${lang}_COMPILER_ID_ARG1}")
13

14
  # Make sure user-specified compiler flags are used.
15 16
  if(CMAKE_${lang}_FLAGS)
    set(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS})
17
  else()
18
    set(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}})
19
  endif()
20
  string(REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}")
21

22
  # Compute the directory in which to run the test.
23
  set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
24 25 26

  # Try building with no extra flags and then try each set
  # of helper flags.  Stop when the compiler is identified.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
  foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
    foreach(testflags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
                      ""
                      ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
      CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${testflags}" "${userflags}" "${src}")
      CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
      if(CMAKE_${lang}_COMPILER_ID)
        break()
      endif()
      foreach(file ${COMPILER_${lang}_PRODUCED_FILES})
        CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
      endforeach()
      if(CMAKE_${lang}_COMPILER_ID)
        break()
      endif()
42 43 44
    endforeach()
    if(CMAKE_${lang}_COMPILER_ID)
      break()
45 46
    endif()
  endforeach()
47

48
  # If the compiler is still unknown, try to query its vendor.
49
  if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID)
50 51 52
    foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
      CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang} "${userflags}")
    endforeach()
53
  endif()
54

55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
  # CUDA < 7.5 is missing version macros
  if(lang STREQUAL "CUDA"
     AND CMAKE_${lang}_COMPILER_ID STREQUAL "NVIDIA"
     AND NOT CMAKE_${lang}_COMPILER_VERSION)
    execute_process(
      COMMAND "${CMAKE_${lang}_COMPILER}"
      --version
      OUTPUT_VARIABLE output ERROR_VARIABLE output
      RESULT_VARIABLE result
      TIMEOUT 10
    )
    if(output MATCHES [=[ V([0-9]+)\.([0-9]+)\.([0-9]+)]=])
      set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
    endif()
  endif()

71
  if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
72 73 74 75 76 77 78 79 80 81 82 83 84 85
    execute_process(
      COMMAND "${CMAKE_${lang}_COMPILER}"
      -V
      OUTPUT_VARIABLE output ERROR_VARIABLE output
      RESULT_VARIABLE result
      TIMEOUT 10
      )
    if (output MATCHES "targets available")
      set(CMAKE_${lang}_COMPILER_ID QCC)
      # http://community.qnx.com/sf/discussion/do/listPosts/projects.community/discussion.qnx_momentics_community_support.topc3555?_pagenum=2
      # The qcc driver does not itself have a version.
    endif()
  endif()

86
  # if the format is unknown after all files have been checked, put "Unknown" in the cache
87 88
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
89
  endif()
90

91
  if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
92 93 94
    foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
      CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}")
    endforeach()
95 96 97 98
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "")
  endif()

99
  # Display the final identification result.
100 101 102 103 104 105 106
  if(CMAKE_${lang}_COMPILER_ID)
    if(CMAKE_${lang}_COMPILER_VERSION)
      set(_version " ${CMAKE_${lang}_COMPILER_VERSION}")
    else()
      set(_version "")
    endif()
    message(STATUS "The ${lang} compiler identification is "
107
      "${CMAKE_${lang}_COMPILER_ID}${_version}")
108
  else()
109
    message(STATUS "The ${lang} compiler identification is unknown")
110
  endif()
111

112
  # Check if compiler id detection gave us the compiler tool.
113 114 115 116
  if(CMAKE_${lang}_COMPILER_ID_TOOL)
    set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_ID_TOOL}" PARENT_SCOPE)
  elseif(NOT CMAKE_${lang}_COMPILER)
    set(CMAKE_${lang}_COMPILER "CMAKE_${lang}_COMPILER-NOTFOUND" PARENT_SCOPE)
117 118
  endif()

119 120
  set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
121
  set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE)
122
  set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
123
    PARENT_SCOPE)
124
  set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_${lang}_XCODE_CURRENT_ARCH}" PARENT_SCOPE)
125
  set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE)
126
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
127
  set(CMAKE_${lang}_COMPILER_VERSION_INTERNAL "${CMAKE_${lang}_COMPILER_VERSION_INTERNAL}" PARENT_SCOPE)
128
  set(CMAKE_${lang}_COMPILER_WRAPPER "${CMAKE_${lang}_COMPILER_WRAPPER}" PARENT_SCOPE)
129 130
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
131
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
132 133
  set(CMAKE_${lang}_COMPILER_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE)
  set(CMAKE_${lang}_COMPILER_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
134
endfunction()
135

136
include(CMakeCompilerIdDetection)
137

138 139
#-----------------------------------------------------------------------------
# Function to write the compiler id source file.
140
function(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
141
  find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
142
  file(READ ${src_in} ID_CONTENT_IN)
143

144 145 146
  compiler_id_detection(CMAKE_${lang}_COMPILER_ID_CONTENT ${lang}
    ID_STRING
    VERSION_STRINGS
147
    PLATFORM_DEFAULT_COMPILER
148
  )
149

150
  unset(src_in CACHE)
151 152
  string(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
  file(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
153
endfunction()
154

155 156 157
#-----------------------------------------------------------------------------
# Function to build the compiler id source file and look for output
# files.
158
function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags userflags src)
159
  # Create a clean working directory.
160 161
  file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
  file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
162
  file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}/tmp)
163
  CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}")
164

165
  # Construct a description of this test case.
166
  set(COMPILER_DESCRIPTION
167
    "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
168
Build flags: ${userflags}
169
Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
170
")
171

172
  # Compile the compiler identification source.
173
  if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)")
174
    set(vs_version ${CMAKE_MATCH_1})
175
    set(id_platform ${CMAKE_VS_PLATFORM_NAME})
176
    set(id_lang "${lang}")
177 178 179 180 181
    if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
      set(id_cl clang.exe)
    else()
      set(id_cl cl.exe)
    endif()
182 183 184 185 186 187 188 189 190 191 192
    if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
      set(v NsightTegra)
      set(ext vcxproj)
      if(lang STREQUAL CXX)
        set(id_gcc g++)
        set(id_clang clang++)
      else()
        set(id_gcc gcc)
        set(id_clang clang)
      endif()
    elseif(lang STREQUAL Fortran)
193 194 195
      set(v Intel)
      set(ext vfproj)
      set(id_cl ifort.exe)
196 197 198 199
    elseif(lang STREQUAL CSharp)
      set(v 10)
      set(ext csproj)
      set(id_cl csc.exe)
200
    elseif(NOT "${vs_version}" VERSION_LESS 10)
201 202
      set(v 10)
      set(ext vcxproj)
203
    else()
204 205 206 207 208
      set(id_version ${vs_version}.00)
      set(v 7)
      set(ext vcproj)
    endif()
    if(CMAKE_VS_PLATFORM_TOOLSET)
209 210 211 212 213 214 215
      if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
        set(id_toolset "<NdkToolchainVersion>${CMAKE_VS_PLATFORM_TOOLSET}</NdkToolchainVersion>")
      else()
        set(id_toolset "<PlatformToolset>${CMAKE_VS_PLATFORM_TOOLSET}</PlatformToolset>")
        if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "Intel")
          set(id_cl icl.exe)
        endif()
216
      endif()
217 218 219
    else()
      set(id_toolset "")
    endif()
220 221 222 223 224
    if(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE)
      set(id_PreferredToolArchitecture "<PreferredToolArchitecture>${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}</PreferredToolArchitecture>")
    else()
      set(id_PreferredToolArchitecture "")
    endif()
225 226 227 228 229 230 231 232 233 234 235 236
    if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
      set(id_system "<ApplicationType>Windows Phone</ApplicationType>")
    elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
      set(id_system "<ApplicationType>Windows Store</ApplicationType>")
    else()
      set(id_system "")
    endif()
    if(id_system AND CMAKE_SYSTEM_VERSION)
      set(id_system_version "<ApplicationTypeRevision>${CMAKE_SYSTEM_VERSION}</ApplicationTypeRevision>")
    else()
      set(id_system_version "")
    endif()
237 238 239
    if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
      set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
    endif()
240 241 242
    if(id_platform STREQUAL ARM64)
      set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARM64Support>true</WindowsSDKDesktopARM64Support>")
    elseif(id_platform STREQUAL ARM)
243 244 245 246
      set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>")
    else()
      set(id_WindowsSDKDesktopARMSupport "")
    endif()
247
    if(CMAKE_VS_WINCE_VERSION)
248
      set(id_entrypoint "mainACRTStartup")
249 250 251 252 253
      if("${vs_version}" VERSION_LESS 9)
        set(id_subsystem 9)
      else()
        set(id_subsystem 8)
      endif()
254 255
    else()
      set(id_subsystem 1)
256
    endif()
257
    set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
258
    set(id_src "${src}")
259 260
    set(id_compile "ClCompile")
    set(id_PostBuildEvent_Command "for %%i in (${id_cl}) do %40echo CMAKE_${lang}_COMPILER=%%~$PATH:i")
261 262 263 264
    set(id_Import_props "")
    set(id_Import_targets "")
    set(id_ItemDefinitionGroup_entry "")
    set(id_Link_AdditionalDependencies "")
265 266 267 268 269 270 271 272 273 274 275 276 277 278
    if(lang STREQUAL CUDA)
      if(NOT CMAKE_VS_PLATFORM_TOOLSET_CUDA)
        message(FATAL_ERROR "No CUDA toolset found.")
      endif()
      set(cuda_tools "CUDA ${CMAKE_VS_PLATFORM_TOOLSET_CUDA}")
      set(id_compile "CudaCompile")
      set(id_PostBuildEvent_Command [[echo CMAKE_CUDA_COMPILER=$(CudaToolkitBinDir)\nvcc.exe]])
      string(CONCAT id_Import_props [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.props" />]])
      string(CONCAT id_Import_targets [[<Import Project="$(VCTargetsPath)\BuildCustomizations\]] "${cuda_tools}" [[.targets" />]])
      if(CMAKE_VS_PLATFORM_NAME STREQUAL x64)
        set(id_ItemDefinitionGroup_entry "<CudaCompile><TargetMachinePlatform>64</TargetMachinePlatform></CudaCompile>")
      endif()
      set(id_Link_AdditionalDependencies "<AdditionalDependencies>cudart.lib</AdditionalDependencies>")
    endif()
279
    configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in
280
      ${id_dir}/CompilerId${lang}.${ext} @ONLY)
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    if(CMAKE_VS_MSBUILD_COMMAND AND NOT lang STREQUAL "Fortran")
      set(command "${CMAKE_VS_MSBUILD_COMMAND}" "CompilerId${lang}.${ext}"
        "/p:Configuration=Debug" "/p:Platform=${id_platform}" "/p:VisualStudioVersion=${vs_version}.0"
        )
    elseif(CMAKE_VS_DEVENV_COMMAND)
      set(command "${CMAKE_VS_DEVENV_COMMAND}" "CompilerId${lang}.${ext}" "/build" "Debug")
    else()
      set(command "")
    endif()
    if(command)
      execute_process(
        COMMAND ${command}
        WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
        OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
        ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
        RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
        )
    else()
      set(CMAKE_${lang}_COMPILER_ID_RESULT 1)
      set(CMAKE_${lang}_COMPILER_ID_OUTPUT "VS environment not known to support ${lang}")
    endif()
302 303
    # Match the compiler location line printed out.
    if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CMAKE_${lang}_COMPILER=([^%\r\n]+)[\r\n]")
304 305
      # Strip VS diagnostic output from the end of the line.
      string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _comp "${CMAKE_MATCH_1}")
306 307 308 309 310 311
      if(EXISTS "${_comp}")
        file(TO_CMAKE_PATH "${_comp}" _comp)
        set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE)
      endif()
    endif()
  elseif("${CMAKE_GENERATOR}" MATCHES "Xcode")
312 313 314
    set(id_lang "${lang}")
    set(id_type ${CMAKE_${lang}_COMPILER_XCODE_TYPE})
    set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
315
    set(id_src "${src}")
316 317 318 319 320
    if(CMAKE_XCODE_PLATFORM_TOOLSET)
      set(id_toolset "GCC_VERSION = ${CMAKE_XCODE_PLATFORM_TOOLSET};")
    else()
      set(id_toolset "")
    endif()
321
    if("${lang}" STREQUAL "Swift")
322 323 324 325 326 327 328
      if(CMAKE_Swift_LANGUAGE_VERSION)
        set(id_lang_version "SWIFT_VERSION = ${CMAKE_Swift_LANGUAGE_VERSION};")
      elseif(XCODE_VERSION VERSION_GREATER_EQUAL 8.3)
        set(id_lang_version "SWIFT_VERSION = 3.0;")
      else()
        set(id_lang_version "SWIFT_VERSION = 2.3;")
      endif()
329 330 331
    else()
      set(id_lang_version "")
    endif()
332 333 334 335 336 337
    if(CMAKE_OSX_DEPLOYMENT_TARGET)
      set(id_deployment_target
        "MACOSX_DEPLOYMENT_TARGET = \"${CMAKE_OSX_DEPLOYMENT_TARGET}\";")
    else()
      set(id_deployment_target "")
    endif()
338
    set(id_product_type "com.apple.product-type.tool")
339 340
    if(CMAKE_OSX_SYSROOT)
      set(id_sdkroot "SDKROOT = \"${CMAKE_OSX_SYSROOT}\";")
341 342
      if(CMAKE_OSX_SYSROOT MATCHES "(^|/)[Ii][Pp][Hh][Oo][Nn][Ee]" OR
        CMAKE_OSX_SYSROOT MATCHES "(^|/)[Aa][Pp][Pp][Ll][Ee][Tt][Vv]")
343 344
        set(id_product_type "com.apple.product-type.bundle.unit-test")
      endif()
345 346 347
    else()
      set(id_sdkroot "")
    endif()
348 349 350 351 352 353
    if(CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
      set(id_development_team
        "DEVELOPMENT_TEAM = \"${CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM}\";")
    else()
      set(id_development_team "")
    endif()
354 355
    configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-3.pbxproj.in
      ${id_dir}/CompilerId${lang}.xcodeproj/project.pbxproj @ONLY)
356 357 358 359 360
    unset(_ENV_MACOSX_DEPLOYMENT_TARGET)
    if(DEFINED ENV{MACOSX_DEPLOYMENT_TARGET})
      set(_ENV_MACOSX_DEPLOYMENT_TARGET "$ENV{MACOSX_DEPLOYMENT_TARGET}")
      set(ENV{MACOSX_DEPLOYMENT_TARGET} "")
    endif()
361 362 363 364 365 366
    execute_process(COMMAND xcodebuild
      WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
      OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
      ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
      RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
      )
367 368 369
    if(DEFINED _ENV_MACOSX_DEPLOYMENT_TARGET)
      set(ENV{MACOSX_DEPLOYMENT_TARGET} "${_ENV_MACOSX_DEPLOYMENT_TARGET}")
    endif()
370

371 372 373 374 375 376
    if(DEFINED CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_REGEX)
      if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "${CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_REGEX}")
        set(_comp "${CMAKE_MATCH_${CMAKE_${lang}_COMPILER_ID_TOOL_MATCH_INDEX}}")
        if(EXISTS "${_comp}")
          set(CMAKE_${lang}_COMPILER_ID_TOOL "${_comp}" PARENT_SCOPE)
        endif()
377 378
      endif()
    endif()
379 380 381
    if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CURRENT_ARCH=([^%\r\n]+)[\r\n]")
      set(CMAKE_${lang}_XCODE_CURRENT_ARCH "${CMAKE_MATCH_1}" PARENT_SCOPE)
    endif()
382
  else()
383 384 385
    execute_process(
      COMMAND "${CMAKE_${lang}_COMPILER}"
              ${CMAKE_${lang}_COMPILER_ID_ARG1}
386
              ${userflags}
387
              ${testflags}
388
              ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS}
389 390 391 392 393 394
              "${src}"
      WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
      OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
      ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
      RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
      )
395
  endif()
396 397

  # Check the result of compilation.
398 399 400 401
  if(CMAKE_${lang}_COMPILER_ID_RESULT
     # Intel Fortran warns and ignores preprocessor lines without /fpp
     OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "Bad # preprocessor line"
     )
402
    # Compilation failed.
403
    set(MSG
404 405 406 407 408 409 410
      "Compiling the ${lang} compiler identification source file \"${src}\" failed.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
411 412 413
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
    #if(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
    #  message(FATAL_ERROR "${MSG}")
414
    #endif()
415 416

    # No output files should be inspected.
417
    set(COMPILER_${lang}_PRODUCED_FILES)
418
    set(COMPILER_${lang}_PRODUCED_OUTPUT)
419
  else()
420
    # Compilation succeeded.
421
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
422 423 424 425 426 427 428
      "Compiling the ${lang} compiler identification source file \"${src}\" succeeded.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
429

430 431
    # Find the executable produced by the compiler, try all files in the
    # binary dir.
432
    string(REGEX REPLACE "([][])" "[\\1]" _glob_id_dir "${CMAKE_${lang}_COMPILER_ID_DIR}")
433
    file(GLOB files
434
      RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR}
435 436

      # normal case
437
      ${_glob_id_dir}/*
438 439

      # com.apple.package-type.bundle.unit-test
440
      ${_glob_id_dir}/*.xctest/*
441
      )
442 443 444 445 446 447 448 449 450
    list(REMOVE_ITEM files "${src}")
    set(COMPILER_${lang}_PRODUCED_FILES "")
    foreach(file ${files})
      if(NOT IS_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}/${file})
        list(APPEND COMPILER_${lang}_PRODUCED_FILES ${file})
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
          "Compilation of the ${lang} compiler identification source \""
          "${src}\" produced \"${file}\"\n\n")
      endif()
451
    endforeach()
452

453
    if(NOT COMPILER_${lang}_PRODUCED_FILES)
454
      # No executable was found.
455
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
456
        "Compilation of the ${lang} compiler identification source \""
457
        "${src}\" did not produce an executable in \""
458
        "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n")
459
    endif()
460 461

    set(COMPILER_${lang}_PRODUCED_OUTPUT "${CMAKE_${lang}_COMPILER_ID_OUTPUT}")
462
  endif()
463

464
  # Return the files produced by the compilation.
465
  set(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
466
  set(COMPILER_${lang}_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE)
467

468 469 470 471 472 473 474 475 476 477 478
endfunction()

#-----------------------------------------------------------------------------
# Function to extract the compiler id from compiler output.
function(CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR lang output)
  foreach(vendor ${CMAKE_${lang}_COMPILER_ID_MATCH_VENDORS})
    if(output MATCHES "${CMAKE_${lang}_COMPILER_ID_MATCH_VENDOR_REGEX_${vendor}}")
      set(CMAKE_${lang}_COMPILER_ID "${vendor}")
    endif()
  endforeach()
  set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
479
endfunction()
480 481 482

#-----------------------------------------------------------------------------
# Function to extract the compiler id from an executable.
483
function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
484
  # Look for a compiler id if not yet known.
485
  if(NOT CMAKE_${lang}_COMPILER_ID)
486
    # Read the compiler identification string from the executable file.
487 488
    set(COMPILER_ID)
    set(COMPILER_VERSION)
489 490 491 492
    set(COMPILER_VERSION_MAJOR 0)
    set(COMPILER_VERSION_MINOR 0)
    set(COMPILER_VERSION_PATCH 0)
    set(COMPILER_VERSION_TWEAK 0)
493
    set(COMPILER_VERSION_INTERNAL "")
494 495 496 497
    set(HAVE_COMPILER_VERSION_MAJOR 0)
    set(HAVE_COMPILER_VERSION_MINOR 0)
    set(HAVE_COMPILER_VERSION_PATCH 0)
    set(HAVE_COMPILER_VERSION_TWEAK 0)
498
    set(COMPILER_WRAPPER)
499 500 501 502 503 504 505 506
    set(DIGIT_VALUE_1 1)
    set(DIGIT_VALUE_2 10)
    set(DIGIT_VALUE_3 100)
    set(DIGIT_VALUE_4 1000)
    set(DIGIT_VALUE_5 10000)
    set(DIGIT_VALUE_6 100000)
    set(DIGIT_VALUE_7 1000000)
    set(DIGIT_VALUE_8 10000000)
507
    set(PLATFORM_ID)
508
    set(ARCHITECTURE_ID)
509 510
    set(SIMULATE_ID)
    set(SIMULATE_VERSION)
511
    file(STRINGS ${file}
512 513 514
      CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38
      ${CMAKE_${lang}_COMPILER_ID_STRINGS_PARAMETERS}
      REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
515
    set(COMPILER_ID_TWICE)
516 517
    # In C# binaries, some strings are found more than once.
    list(REMOVE_DUPLICATES CMAKE_${lang}_COMPILER_ID_STRINGS)
518
    foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
519
      if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]")
520 521
        if(COMPILER_ID)
          set(COMPILER_ID_TWICE 1)
522
        endif()
523
        set(COMPILER_ID "${CMAKE_MATCH_1}")
524
      endif()
525
      if("${info}" MATCHES "INFO:platform\\[([^]\"]*)\\]")
526
        set(PLATFORM_ID "${CMAKE_MATCH_1}")
527
      endif()
528
      if("${info}" MATCHES "INFO:arch\\[([^]\"]*)\\]")
529
        set(ARCHITECTURE_ID "${CMAKE_MATCH_1}")
530
      endif()
531
      if("${info}" MATCHES "INFO:compiler_version\\[([^]\"]*)\\]")
532
        string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}")
533
        string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}")
534
      endif()
535 536 537 538
      if("${info}" MATCHES "INFO:compiler_version_internal\\[([^]\"]*)\\]")
        string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION_INTERNAL "${CMAKE_MATCH_1}")
        string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}")
      endif()
539 540 541 542 543 544 545 546 547
      foreach(comp MAJOR MINOR PATCH TWEAK)
        foreach(digit 1 2 3 4 5 6 7 8 9)
          if("${info}" MATCHES "INFO:compiler_version_${comp}_digit_${digit}\\[([0-9])\\]")
            set(value ${CMAKE_MATCH_1})
            math(EXPR COMPILER_VERSION_${comp} "${COMPILER_VERSION_${comp}} + ${value} * ${DIGIT_VALUE_${digit}}")
            set(HAVE_COMPILER_VERSION_${comp} 1)
          endif()
        endforeach()
      endforeach()
548 549 550
      if("${info}" MATCHES "INFO:compiler_wrapper\\[([^]\"]*)\\]")
        set(COMPILER_WRAPPER "${CMAKE_MATCH_1}")
      endif()
551
      if("${info}" MATCHES "INFO:simulate\\[([^]\"]*)\\]")
552 553
        set(SIMULATE_ID "${CMAKE_MATCH_1}")
      endif()
554
      if("${info}" MATCHES "INFO:simulate_version\\[([^]\"]*)\\]")
555
        string(REGEX REPLACE "^0+([0-9])" "\\1" SIMULATE_VERSION "${CMAKE_MATCH_1}")
556 557
        string(REGEX REPLACE "\\.0+([0-9])" ".\\1" SIMULATE_VERSION "${SIMULATE_VERSION}")
      endif()
558
      if("${info}" MATCHES "INFO:qnxnto\\[\\]")
559 560
        set(COMPILER_QNXNTO 1)
      endif()
561 562 563
      if("${info}" MATCHES "INFO:dialect_default\\[([^]\"]*)\\]")
        set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_MATCH_1}")
      endif()
564
    endforeach()
565

566 567 568 569
    # Construct compiler version from components if needed.
    if(NOT DEFINED COMPILER_VERSION AND HAVE_COMPILER_VERSION_MAJOR)
      set(COMPILER_VERSION "${COMPILER_VERSION_MAJOR}")
      if(HAVE_COMPILER_VERSION_MINOR)
570
        string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_MINOR}")
571
        if(HAVE_COMPILER_VERSION_PATCH)
572
          string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_PATCH}")
573
          if(HAVE_COMPILER_VERSION_TWEAK)
574
            string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_TWEAK}")
575 576 577 578 579
          endif()
        endif()
      endif()
    endif()

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
    # Detect the exact architecture from the PE header.
    if(WIN32)
      # The offset to the PE signature is stored at 0x3c.
      file(READ ${file} peoffsethex LIMIT 1 OFFSET 60 HEX)
      string(SUBSTRING "${peoffsethex}" 0 1 peoffsethex1)
      string(SUBSTRING "${peoffsethex}" 1 1 peoffsethex2)
      set(peoffsetexpression "${peoffsethex1} * 16 + ${peoffsethex2}")
      string(REPLACE "a" "10" peoffsetexpression "${peoffsetexpression}")
      string(REPLACE "b" "11" peoffsetexpression "${peoffsetexpression}")
      string(REPLACE "c" "12" peoffsetexpression "${peoffsetexpression}")
      string(REPLACE "d" "13" peoffsetexpression "${peoffsetexpression}")
      string(REPLACE "e" "14" peoffsetexpression "${peoffsetexpression}")
      string(REPLACE "f" "15" peoffsetexpression "${peoffsetexpression}")
      math(EXPR peoffset "${peoffsetexpression}")

      file(READ ${file} peheader LIMIT 6 OFFSET ${peoffset} HEX)
      if(peheader STREQUAL "50450000a201")
        set(ARCHITECTURE_ID "SH3")
      elseif(peheader STREQUAL "50450000a301")
        set(ARCHITECTURE_ID "SH3DSP")
      elseif(peheader STREQUAL "50450000a601")
        set(ARCHITECTURE_ID "SH4")
      elseif(peheader STREQUAL "50450000a801")
        set(ARCHITECTURE_ID "SH5")
      endif()
    endif()

607
    # Check if a valid compiler and platform were found.
608 609 610
    if(COMPILER_ID AND NOT COMPILER_ID_TWICE)
      set(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}")
      set(CMAKE_${lang}_PLATFORM_ID "${PLATFORM_ID}")
611
      set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${ARCHITECTURE_ID}")
612 613
      set(MSVC_${lang}_ARCHITECTURE_ID "${ARCHITECTURE_ID}")
      set(CMAKE_${lang}_COMPILER_VERSION "${COMPILER_VERSION}")
614
      set(CMAKE_${lang}_COMPILER_VERSION_INTERNAL "${COMPILER_VERSION_INTERNAL}")
615 616
      set(CMAKE_${lang}_SIMULATE_ID "${SIMULATE_ID}")
      set(CMAKE_${lang}_SIMULATE_VERSION "${SIMULATE_VERSION}")
617
    endif()
618 619

    # Check the compiler identification string.
620
    if(CMAKE_${lang}_COMPILER_ID)
621
      # The compiler identification was found.
622
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
623 624
        "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \""
        "${file}\"\n\n")
625
    else()
626
      # The compiler identification could not be found.
627
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
628 629
        "The ${lang} compiler identification could not be found in \""
        "${file}\"\n\n")
630 631
    endif()
  endif()
632 633

  # try to figure out the executable format: ELF, COFF, Mach-O
634 635
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    file(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX)
636 637

    # ELF files start with 0x7f"ELF"
638 639
    if("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
      set(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format")
640
    endif()
641 642

#    # COFF (.exe) files start with "MZ"
643 644
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
#      set(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
645
#    endif()
646 647
#
#    # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html
648 649
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
650
#    endif()
651 652
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
653
#    endif()
654

655
  endif()
656 657 658
  if(NOT DEFINED CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT)
  endif()
659
  # Return the information extracted.
660 661
  set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
662
  set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE)
663
  set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
664
    PARENT_SCOPE)
665
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
666
  set(CMAKE_${lang}_COMPILER_VERSION_INTERNAL "${CMAKE_${lang}_COMPILER_VERSION_INTERNAL}" PARENT_SCOPE)
667
  set(CMAKE_${lang}_COMPILER_WRAPPER "${COMPILER_WRAPPER}" PARENT_SCOPE)
668 669
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
670
  set(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE)
671
  set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE)
672
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
673
endfunction()
674 675 676 677 678 679 680 681 682

#-----------------------------------------------------------------------------
# Function to query the compiler vendor.
# This uses a table with entries of the form
#   list(APPEND CMAKE_${lang}_COMPILER_ID_VENDORS ${vendor})
#   set(CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor} -some-vendor-flag)
#   set(CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor} "Some Vendor Output")
# We try running the compiler with the flag for each vendor and
# matching its regular expression in the output.
683
function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang userflags)
684

685
  if(NOT CMAKE_${lang}_COMPILER_ID_DIR)
686 687 688
    # We get here when this function is called not from within CMAKE_DETERMINE_COMPILER_ID()
    # This is done e.g. for detecting the compiler ID for assemblers.
    # Compute the directory in which to run the test and Create a clean working directory.
689
    set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
690 691
    file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
    file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
692
  endif()
693 694


695 696 697 698
  foreach(vendor ${CMAKE_${lang}_COMPILER_ID_VENDORS})
    set(flags ${CMAKE_${lang}_COMPILER_ID_VENDOR_FLAGS_${vendor}})
    set(regex ${CMAKE_${lang}_COMPILER_ID_VENDOR_REGEX_${vendor}})
    execute_process(
699
      COMMAND "${CMAKE_${lang}_COMPILER}"
700
      ${CMAKE_${lang}_COMPILER_ID_ARG1}
701
      ${userflags}
702 703 704 705
      ${flags}
      WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
      OUTPUT_VARIABLE output ERROR_VARIABLE output
      RESULT_VARIABLE result
706
      TIMEOUT 10
707
      )
708

709 710
    if("${output}" MATCHES "${regex}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
711 712
        "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
        "matched \"${regex}\":\n${output}")
713
      set(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE)
714
      set(CMAKE_${lang}_COMPILER_ID_OUTPUT "${output}" PARENT_SCOPE)
715 716 717 718
      break()
    else()
      if("${result}" MATCHES  "timeout")
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
719 720
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "terminated after 10 s due to timeout.")
721 722
      else()
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
723 724
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "did not match \"${regex}\":\n${output}")
725 726 727
       endif()
    endif()
  endforeach()
728
endfunction()
729

730
function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang userflags)
731 732 733 734 735 736 737 738 739
  # Run this MSVC-compatible compiler to detect what the /showIncludes
  # option displays.  We can use a C source even with the C++ compiler
  # because MSVC-compatible compilers handle both and show the same output.
  set(showdir ${CMAKE_BINARY_DIR}/CMakeFiles/ShowIncludes)
  file(WRITE ${showdir}/foo.h "\n")
  file(WRITE ${showdir}/main.c "#include \"foo.h\" \nint main(){}\n")
  execute_process(
    COMMAND "${CMAKE_${lang}_COMPILER}"
            ${CMAKE_${lang}_COMPILER_ID_ARG1}
740
            ${userflags}
741 742 743 744 745
            /nologo /showIncludes /c main.c
    WORKING_DIRECTORY ${showdir}
    OUTPUT_VARIABLE out
    ERROR_VARIABLE err
    RESULT_VARIABLE res
746
    ENCODING AUTO # cl prints in current code page
747
    )
748 749
  if(res EQUAL 0 AND "${out}" MATCHES "(^|\n)([^:\n]*:[^:\n]*:[ \t]*)")
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_MATCH_2}" PARENT_SCOPE)
750 751 752 753
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "" PARENT_SCOPE)
  endif()
endfunction()
754 755 756 757 758 759 760

function(CMAKE_DIAGNOSE_UNSUPPORTED_CLANG lang envvar)
  if(NOT CMAKE_HOST_WIN32 OR CMAKE_GENERATOR MATCHES "Visual Studio" OR
      NOT "${CMAKE_${lang}_COMPILER_ID};${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "Clang;MSVC")
    return()
  endif()

761 762
  # Test whether an MSVC-like command-line option works.
  execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" /?
763 764 765
    RESULT_VARIABLE _clang_result
    OUTPUT_VARIABLE _clang_stdout
    ERROR_VARIABLE _clang_stderr)
766
  if(_clang_result EQUAL 0)
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
    return()
  endif()

  # Help the user configure the environment to use the MSVC-like Clang.
  string(CONCAT _msg
    "The Clang compiler tool\n"
    "  \"${CMAKE_${lang}_COMPILER}\"\n"
    "targets the MSVC ABI but has a GNU-like command-line interface.  "
    "This is not supported.  "
    "Use 'clang-cl' instead, e.g. by setting '${envvar}=clang-cl' in the environment."
    )
  execute_process(COMMAND rc -help
    RESULT_VARIABLE _rc_result
    OUTPUT_VARIABLE _rc_stdout
    ERROR_VARIABLE _rc_stderr)
  if(NOT _rc_result EQUAL 0)
    string(APPEND _msg "  "
      "Furthermore, use the MSVC command-line environment."
      )
  endif()
  message(FATAL_ERROR "${_msg}")
endfunction()