CMakeDetermineCompilerId.cmake 26.9 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
  foreach(flags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
                ""
                ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
30
    CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}")
31 32 33 34
    CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
    if(CMAKE_${lang}_COMPILER_ID)
      break()
    endif()
35 36 37 38 39
    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()
40 41
    endif()
  endforeach()
42

43
  # If the compiler is still unknown, try to query its vendor.
44
  if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID)
45
    CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang})
46
  endif()
47

48
  if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
49 50 51 52 53 54 55 56 57 58 59 60 61 62
    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()

63
  # if the format is unknown after all files have been checked, put "Unknown" in the cache
64 65
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
66
  endif()
67

68 69 70 71 72 73
  if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
    CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang})
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "")
  endif()

74
  # Display the final identification result.
75 76 77 78 79 80 81
  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 "
82
      "${CMAKE_${lang}_COMPILER_ID}${_version}")
83
  else()
84
    message(STATUS "The ${lang} compiler identification is unknown")
85
  endif()
86

87
  # Check if compiler id detection gave us the compiler tool.
88 89 90 91
  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)
92 93
  endif()

94 95 96
  set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
  set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
97
    PARENT_SCOPE)
98
  set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE)
99
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
100
  set(CMAKE_${lang}_COMPILER_WRAPPER "${CMAKE_${lang}_COMPILER_WRAPPER}" PARENT_SCOPE)
101 102
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
103
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
104
endfunction()
105

106
include(CMakeCompilerIdDetection)
107

108 109
#-----------------------------------------------------------------------------
# Function to write the compiler id source file.
110
function(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
111
  find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
112
  file(READ ${src_in} ID_CONTENT_IN)
113

114 115 116
  compiler_id_detection(CMAKE_${lang}_COMPILER_ID_CONTENT ${lang}
    ID_STRING
    VERSION_STRINGS
117
    PLATFORM_DEFAULT_COMPILER
118
  )
119

120
  unset(src_in CACHE)
121 122
  string(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
  file(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
123
endfunction()
124

125 126 127
#-----------------------------------------------------------------------------
# Function to build the compiler id source file and look for output
# files.
128
function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
129
  # Create a clean working directory.
130 131
  file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
  file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
132
  CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}")
133

134
  # Construct a description of this test case.
135
  set(COMPILER_DESCRIPTION
136 137 138 139
    "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
Id flags: ${testflags}
")
140

141
  # Compile the compiler identification source.
142
  if("${CMAKE_GENERATOR}" MATCHES "Visual Studio ([0-9]+)")
143
    set(vs_version ${CMAKE_MATCH_1})
144
    set(id_platform ${CMAKE_VS_PLATFORM_NAME})
145
    set(id_lang "${lang}")
146 147 148 149 150
    if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*")
      set(id_cl clang.exe)
    else()
      set(id_cl cl.exe)
    endif()
151 152 153 154 155 156 157 158 159 160 161
    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)
162 163 164 165
      set(v Intel)
      set(ext vfproj)
      set(id_cl ifort.exe)
    elseif(NOT "${vs_version}" VERSION_LESS 10)
166 167
      set(v 10)
      set(ext vcxproj)
168
    else()
169 170 171 172 173
      set(id_version ${vs_version}.00)
      set(v 7)
      set(ext vcproj)
    endif()
    if(CMAKE_VS_PLATFORM_TOOLSET)
174 175 176 177 178 179 180
      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()
181
      endif()
182 183 184
    else()
      set(id_toolset "")
    endif()
185 186 187 188 189
    if(CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE)
      set(id_PreferredToolArchitecture "<PreferredToolArchitecture>${CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE}</PreferredToolArchitecture>")
    else()
      set(id_PreferredToolArchitecture "")
    endif()
190 191 192 193 194 195 196 197 198 199 200 201
    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()
202 203 204
    if(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION)
      set(id_WindowsTargetPlatformVersion "<WindowsTargetPlatformVersion>${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}</WindowsTargetPlatformVersion>")
    endif()
205 206 207 208 209
    if(id_platform STREQUAL ARM)
      set(id_WindowsSDKDesktopARMSupport "<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>")
    else()
      set(id_WindowsSDKDesktopARMSupport "")
    endif()
210
    if(CMAKE_VS_WINCE_VERSION)
211
      set(id_entrypoint "mainACRTStartup")
212 213 214 215 216
      if("${vs_version}" VERSION_LESS 9)
        set(id_subsystem 9)
      else()
        set(id_subsystem 8)
      endif()
217 218
    else()
      set(id_subsystem 1)
219
    endif()
220
    set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
221
    set(id_src "${src}")
222
    configure_file(${CMAKE_ROOT}/Modules/CompilerId/VS-${v}.${ext}.in
223
      ${id_dir}/CompilerId${lang}.${ext} @ONLY)
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    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()
245 246
    # Match the compiler location line printed out.
    if("${CMAKE_${lang}_COMPILER_ID_OUTPUT}" MATCHES "CMAKE_${lang}_COMPILER=([^%\r\n]+)[\r\n]")
247 248
      # Strip VS diagnostic output from the end of the line.
      string(REGEX REPLACE " \\(TaskId:[0-9]*\\)$" "" _comp "${CMAKE_MATCH_1}")
249 250 251 252 253 254
      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")
255 256 257
    set(id_lang "${lang}")
    set(id_type ${CMAKE_${lang}_COMPILER_XCODE_TYPE})
    set(id_dir ${CMAKE_${lang}_COMPILER_ID_DIR})
258
    set(id_src "${src}")
259 260 261 262 263
    if(CMAKE_XCODE_PLATFORM_TOOLSET)
      set(id_toolset "GCC_VERSION = ${CMAKE_XCODE_PLATFORM_TOOLSET};")
    else()
      set(id_toolset "")
    endif()
264 265 266 267 268
    if("${lang}" STREQUAL "Swift")
      set(id_lang_version "SWIFT_VERSION = 2.3;")
    else()
      set(id_lang_version "")
    endif()
269 270 271 272 273 274
    if(CMAKE_OSX_DEPLOYMENT_TARGET)
      set(id_deployment_target
        "MACOSX_DEPLOYMENT_TARGET = \"${CMAKE_OSX_DEPLOYMENT_TARGET}\";")
    else()
      set(id_deployment_target "")
    endif()
275
    set(id_product_type "com.apple.product-type.tool")
276 277
    if(CMAKE_OSX_SYSROOT)
      set(id_sdkroot "SDKROOT = \"${CMAKE_OSX_SYSROOT}\";")
278 279 280
      if(CMAKE_OSX_SYSROOT MATCHES "(^|/)[Ii][Pp][Hh][Oo][Nn][Ee]")
        set(id_product_type "com.apple.product-type.bundle.unit-test")
      endif()
281 282 283
    else()
      set(id_sdkroot "")
    endif()
284 285 286 287 288 289 290 291 292 293 294
    if(NOT ${XCODE_VERSION} VERSION_LESS 3)
      set(v 3)
      set(ext xcodeproj)
    elseif(NOT ${XCODE_VERSION} VERSION_LESS 2)
      set(v 2)
      set(ext xcodeproj)
    else()
      set(v 1)
      set(ext xcode)
    endif()
    configure_file(${CMAKE_ROOT}/Modules/CompilerId/Xcode-${v}.pbxproj.in
295
      ${id_dir}/CompilerId${lang}.${ext}/project.pbxproj @ONLY)
296 297 298 299 300
    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()
301 302 303 304 305 306
    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
      )
307 308 309
    if(DEFINED _ENV_MACOSX_DEPLOYMENT_TARGET)
      set(ENV{MACOSX_DEPLOYMENT_TARGET} "${_ENV_MACOSX_DEPLOYMENT_TARGET}")
    endif()
310

311 312 313 314 315 316
    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()
317 318
      endif()
    endif()
319
  else()
320 321 322 323 324 325 326 327 328 329 330
    execute_process(
      COMMAND "${CMAKE_${lang}_COMPILER}"
              ${CMAKE_${lang}_COMPILER_ID_ARG1}
              ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
              ${testflags}
              "${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
      )
331
  endif()
332 333

  # Check the result of compilation.
334 335 336 337
  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"
     )
338
    # Compilation failed.
339
    set(MSG
340 341 342 343 344 345 346
      "Compiling the ${lang} compiler identification source file \"${src}\" failed.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
347 348 349
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
    #if(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
    #  message(FATAL_ERROR "${MSG}")
350
    #endif()
351 352

    # No output files should be inspected.
353
    set(COMPILER_${lang}_PRODUCED_FILES)
354
    set(COMPILER_${lang}_PRODUCED_OUTPUT)
355
  else()
356
    # Compilation succeeded.
357
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
358 359 360 361 362 363 364
      "Compiling the ${lang} compiler identification source file \"${src}\" succeeded.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
365

366 367
    # Find the executable produced by the compiler, try all files in the
    # binary dir.
368
    string(REGEX REPLACE "([][])" "[\\1]" _glob_id_dir "${CMAKE_${lang}_COMPILER_ID_DIR}")
369
    file(GLOB files
370
      RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR}
371 372

      # normal case
373
      ${_glob_id_dir}/*
374 375

      # com.apple.package-type.bundle.unit-test
376
      ${_glob_id_dir}/*.xctest/*
377
      )
378 379 380 381 382 383 384 385 386
    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()
387
    endforeach()
388

389
    if(NOT COMPILER_${lang}_PRODUCED_FILES)
390
      # No executable was found.
391
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
392
        "Compilation of the ${lang} compiler identification source \""
393
        "${src}\" did not produce an executable in \""
394
        "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n")
395
    endif()
396 397

    set(COMPILER_${lang}_PRODUCED_OUTPUT "${CMAKE_${lang}_COMPILER_ID_OUTPUT}")
398
  endif()
399

400
  # Return the files produced by the compilation.
401
  set(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
402 403 404 405 406 407 408 409 410 411 412 413
  set(COMPILER_${lang}_PRODUCED_OUTPUT "${COMPILER_${lang}_PRODUCED_OUTPUT}" PARENT_SCOPE)
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)
414
endfunction()
415 416 417

#-----------------------------------------------------------------------------
# Function to extract the compiler id from an executable.
418
function(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
419
  # Look for a compiler id if not yet known.
420
  if(NOT CMAKE_${lang}_COMPILER_ID)
421
    # Read the compiler identification string from the executable file.
422 423
    set(COMPILER_ID)
    set(COMPILER_VERSION)
424 425 426 427 428 429 430 431
    set(COMPILER_VERSION_MAJOR 0)
    set(COMPILER_VERSION_MINOR 0)
    set(COMPILER_VERSION_PATCH 0)
    set(COMPILER_VERSION_TWEAK 0)
    set(HAVE_COMPILER_VERSION_MAJOR 0)
    set(HAVE_COMPILER_VERSION_MINOR 0)
    set(HAVE_COMPILER_VERSION_PATCH 0)
    set(HAVE_COMPILER_VERSION_TWEAK 0)
432
    set(COMPILER_WRAPPER)
433 434 435 436 437 438 439 440
    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)
441
    set(PLATFORM_ID)
442
    set(ARCHITECTURE_ID)
443 444
    set(SIMULATE_ID)
    set(SIMULATE_VERSION)
445
    file(STRINGS ${file}
446
      CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 38 REGEX "INFO:[A-Za-z0-9_]+\\[[^]]*\\]")
447
    set(COMPILER_ID_TWICE)
448
    foreach(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
449
      if("${info}" MATCHES "INFO:compiler\\[([^]\"]*)\\]")
450 451
        if(COMPILER_ID)
          set(COMPILER_ID_TWICE 1)
452
        endif()
453
        set(COMPILER_ID "${CMAKE_MATCH_1}")
454
      endif()
455
      if("${info}" MATCHES "INFO:platform\\[([^]\"]*)\\]")
456
        set(PLATFORM_ID "${CMAKE_MATCH_1}")
457
      endif()
458
      if("${info}" MATCHES "INFO:arch\\[([^]\"]*)\\]")
459
        set(ARCHITECTURE_ID "${CMAKE_MATCH_1}")
460
      endif()
461
      if("${info}" MATCHES "INFO:compiler_version\\[([^]\"]*)\\]")
462
        string(REGEX REPLACE "^0+([0-9])" "\\1" COMPILER_VERSION "${CMAKE_MATCH_1}")
463
        string(REGEX REPLACE "\\.0+([0-9])" ".\\1" COMPILER_VERSION "${COMPILER_VERSION}")
464
      endif()
465 466 467 468 469 470 471 472 473
      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()
474 475 476
      if("${info}" MATCHES "INFO:compiler_wrapper\\[([^]\"]*)\\]")
        set(COMPILER_WRAPPER "${CMAKE_MATCH_1}")
      endif()
477
      if("${info}" MATCHES "INFO:simulate\\[([^]\"]*)\\]")
478 479
        set(SIMULATE_ID "${CMAKE_MATCH_1}")
      endif()
480
      if("${info}" MATCHES "INFO:simulate_version\\[([^]\"]*)\\]")
481
        string(REGEX REPLACE "^0+([0-9])" "\\1" SIMULATE_VERSION "${CMAKE_MATCH_1}")
482 483
        string(REGEX REPLACE "\\.0+([0-9])" ".\\1" SIMULATE_VERSION "${SIMULATE_VERSION}")
      endif()
484
      if("${info}" MATCHES "INFO:qnxnto\\[\\]")
485 486
        set(COMPILER_QNXNTO 1)
      endif()
487 488 489
      if("${info}" MATCHES "INFO:dialect_default\\[([^]\"]*)\\]")
        set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_MATCH_1}")
      endif()
490
    endforeach()
491

492 493 494 495
    # 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)
496
        string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_MINOR}")
497
        if(HAVE_COMPILER_VERSION_PATCH)
498
          string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_PATCH}")
499
          if(HAVE_COMPILER_VERSION_TWEAK)
500
            string(APPEND COMPILER_VERSION ".${COMPILER_VERSION_TWEAK}")
501 502 503 504 505
          endif()
        endif()
      endif()
    endif()

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
    # 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()

533
    # Check if a valid compiler and platform were found.
534 535 536 537 538
    if(COMPILER_ID AND NOT COMPILER_ID_TWICE)
      set(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}")
      set(CMAKE_${lang}_PLATFORM_ID "${PLATFORM_ID}")
      set(MSVC_${lang}_ARCHITECTURE_ID "${ARCHITECTURE_ID}")
      set(CMAKE_${lang}_COMPILER_VERSION "${COMPILER_VERSION}")
539 540
      set(CMAKE_${lang}_SIMULATE_ID "${SIMULATE_ID}")
      set(CMAKE_${lang}_SIMULATE_VERSION "${SIMULATE_VERSION}")
541
    endif()
542 543

    # Check the compiler identification string.
544
    if(CMAKE_${lang}_COMPILER_ID)
545
      # The compiler identification was found.
546
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
547 548
        "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \""
        "${file}\"\n\n")
549
    else()
550
      # The compiler identification could not be found.
551
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
552 553
        "The ${lang} compiler identification could not be found in \""
        "${file}\"\n\n")
554 555
    endif()
  endif()
556 557

  # try to figure out the executable format: ELF, COFF, Mach-O
558 559
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    file(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX)
560 561

    # ELF files start with 0x7f"ELF"
562 563
    if("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
      set(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format")
564
    endif()
565 566

#    # COFF (.exe) files start with "MZ"
567 568
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
#      set(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
569
#    endif()
570 571
#
#    # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html
572 573
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
574
#    endif()
575 576
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
577
#    endif()
578

579
  endif()
580 581 582
  if(NOT DEFINED CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT)
  endif()
583
  # Return the information extracted.
584 585 586
  set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
  set(MSVC_${lang}_ARCHITECTURE_ID "${MSVC_${lang}_ARCHITECTURE_ID}"
587
    PARENT_SCOPE)
588
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
589
  set(CMAKE_${lang}_COMPILER_WRAPPER "${COMPILER_WRAPPER}" PARENT_SCOPE)
590 591
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
592
  set(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE)
593
  set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE)
594
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
595
endfunction()
596 597 598 599 600 601 602 603 604

#-----------------------------------------------------------------------------
# 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.
605
function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang)
606

607
  if(NOT CMAKE_${lang}_COMPILER_ID_DIR)
608 609 610
    # 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.
611
    set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
612 613
    file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
    file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
614
  endif()
615 616


617 618 619 620
  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(
621
      COMMAND "${CMAKE_${lang}_COMPILER}"
622 623 624 625 626 627
      ${CMAKE_${lang}_COMPILER_ID_ARG1}
      ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
      ${flags}
      WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
      OUTPUT_VARIABLE output ERROR_VARIABLE output
      RESULT_VARIABLE result
628
      TIMEOUT 10
629
      )
630

631 632
    if("${output}" MATCHES "${regex}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
633 634
        "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
        "matched \"${regex}\":\n${output}")
635 636 637 638 639
      set(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE)
      break()
    else()
      if("${result}" MATCHES  "timeout")
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
640 641
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "terminated after 10 s due to timeout.")
642 643
      else()
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
644 645
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "did not match \"${regex}\":\n${output}")
646 647 648
       endif()
    endif()
  endforeach()
649
endfunction()
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667

function(CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX lang)
  # 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}
            ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
            /nologo /showIncludes /c main.c
    WORKING_DIRECTORY ${showdir}
    OUTPUT_VARIABLE out
    ERROR_VARIABLE err
    RESULT_VARIABLE res
    )
668 669
  if(res EQUAL 0 AND "${out}" MATCHES "(^|\n)([^:\n]*:[^:\n]*:[ \t]*)")
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_MATCH_2}" PARENT_SCOPE)
670 671 672 673
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "" PARENT_SCOPE)
  endif()
endfunction()