CMakeDetermineCompilerId.cmake 27.3 KB
Newer Older
1

2
3
4
5
6
7
8
9
10
11
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
12
# (To distribute this file outside of CMake, substitute the full
13
14
#  License text for the above reference.)

15
# Function to compile a source file to identify the compiler.  This is
16
# used internally by CMake and should not be included by user code.
Alexander Neundorf's avatar
   
Alexander Neundorf committed
17
18
# If successful, sets CMAKE_<lang>_COMPILER_ID and CMAKE_<lang>_PLATFORM_ID

19
function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
20
  # Make sure the compiler arguments are clean.
21
22
  string(STRIP "${CMAKE_${lang}_COMPILER_ARG1}" CMAKE_${lang}_COMPILER_ID_ARG1)
  string(REGEX REPLACE " +" ";" CMAKE_${lang}_COMPILER_ID_ARG1 "${CMAKE_${lang}_COMPILER_ID_ARG1}")
23

24
  # Make sure user-specified compiler flags are used.
25
26
  if(CMAKE_${lang}_FLAGS)
    set(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS})
27
  else()
28
    set(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}})
29
  endif()
30
  string(REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}")
31

32
  # Compute the directory in which to run the test.
33
  set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
34
35
36

  # Try building with no extra flags and then try each set
  # of helper flags.  Stop when the compiler is identified.
37
38
39
  foreach(flags ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS_FIRST}
                ""
                ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
40
    CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}")
41
42
43
44
    CMAKE_DETERMINE_COMPILER_ID_MATCH_VENDOR("${lang}" "${COMPILER_${lang}_PRODUCED_OUTPUT}")
    if(CMAKE_${lang}_COMPILER_ID)
      break()
    endif()
45
46
47
48
49
    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()
50
51
    endif()
  endforeach()
52

53
  # If the compiler is still unknown, try to query its vendor.
54
  if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID)
55
    CMAKE_DETERMINE_COMPILER_ID_VENDOR(${lang})
56
  endif()
57

58
  if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    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()

73
  # if the format is unknown after all files have been checked, put "Unknown" in the cache
74
75
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
76
  endif()
77

78
79
80
81
82
83
  if(CMAKE_GENERATOR STREQUAL "Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
    CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang})
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "")
  endif()

84
  # Display the final identification result.
85
86
87
88
89
90
91
  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 "
92
      "${CMAKE_${lang}_COMPILER_ID}${_version}")
93
  else()
94
    message(STATUS "The ${lang} compiler identification is unknown")
95
  endif()
96

97
  # Check if compiler id detection gave us the compiler tool.
98
99
100
101
  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)
102
103
  endif()

104
105
106
  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}"
107
    PARENT_SCOPE)
108
  set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX}" PARENT_SCOPE)
109
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
110
  set(CMAKE_${lang}_COMPILER_WRAPPER "${CMAKE_${lang}_COMPILER_WRAPPER}" PARENT_SCOPE)
111
112
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
113
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
114
endfunction()
115

116
include(CMakeCompilerIdDetection)
117

118
119
#-----------------------------------------------------------------------------
# Function to write the compiler id source file.
120
function(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
121
  find_file(src_in ${src}.in PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
122
  file(READ ${src_in} ID_CONTENT_IN)
123

124
125
126
  compiler_id_detection(CMAKE_${lang}_COMPILER_ID_CONTENT ${lang}
    ID_STRING
    VERSION_STRINGS
127
    PLATFORM_DEFAULT_COMPILER
128
  )
129

130
  unset(src_in CACHE)
131
132
  string(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
  file(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
133
endfunction()
134

135
136
137
#-----------------------------------------------------------------------------
# Function to build the compiler id source file and look for output
# files.
138
function(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
139
  # Create a clean working directory.
140
141
  file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
  file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
142
  CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}")
143

144
  # Construct a description of this test case.
145
  set(COMPILER_DESCRIPTION
146
147
148
149
    "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
Id flags: ${testflags}
")
150

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

320
321
322
323
324
325
    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()
326
327
      endif()
    endif()
328
  else()
329
330
331
332
333
334
335
336
337
338
339
    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
      )
340
  endif()
341
342

  # Check the result of compilation.
343
344
345
346
  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"
     )
347
    # Compilation failed.
348
    set(MSG
349
350
351
352
353
354
355
      "Compiling the ${lang} compiler identification source file \"${src}\" failed.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
356
357
358
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
    #if(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
    #  message(FATAL_ERROR "${MSG}")
359
    #endif()
360
361

    # No output files should be inspected.
362
    set(COMPILER_${lang}_PRODUCED_FILES)
363
    set(COMPILER_${lang}_PRODUCED_OUTPUT)
364
  else()
365
    # Compilation succeeded.
366
    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
367
368
369
370
371
372
373
      "Compiling the ${lang} compiler identification source file \"${src}\" succeeded.
${COMPILER_DESCRIPTION}
The output was:
${CMAKE_${lang}_COMPILER_ID_RESULT}
${CMAKE_${lang}_COMPILER_ID_OUTPUT}

")
374

375
376
    # Find the executable produced by the compiler, try all files in the
    # binary dir.
377
    file(GLOB files
378
      RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR}
379
380
381
382
383
384
385

      # normal case
      ${CMAKE_${lang}_COMPILER_ID_DIR}/*

      # com.apple.package-type.bundle.unit-test
      ${CMAKE_${lang}_COMPILER_ID_DIR}/*.xctest/*
      )
386
387
388
389
390
391
392
393
394
    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()
395
    endforeach()
396

397
    if(NOT COMPILER_${lang}_PRODUCED_FILES)
Alexander Neundorf's avatar
   
Alexander Neundorf committed
398
      # No executable was found.
399
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
400
        "Compilation of the ${lang} compiler identification source \""
401
        "${src}\" did not produce an executable in \""
402
        "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n")
403
    endif()
404
405

    set(COMPILER_${lang}_PRODUCED_OUTPUT "${CMAKE_${lang}_COMPILER_ID_OUTPUT}")
406
  endif()
407

408
  # Return the files produced by the compilation.
409
  set(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
410
411
412
413
414
415
416
417
418
419
420
421
  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)
422
endfunction()
423
424
425

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

500
501
502
503
504
505
506
507
508
509
510
511
512
513
    # 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)
        set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_MINOR}")
        if(HAVE_COMPILER_VERSION_PATCH)
          set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_PATCH}")
          if(HAVE_COMPILER_VERSION_TWEAK)
            set(COMPILER_VERSION "${COMPILER_VERSION}.${COMPILER_VERSION_TWEAK}")
          endif()
        endif()
      endif()
    endif()

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
    # 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()

541
    # Check if a valid compiler and platform were found.
542
543
544
545
546
    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}")
547
548
      set(CMAKE_${lang}_SIMULATE_ID "${SIMULATE_ID}")
      set(CMAKE_${lang}_SIMULATE_VERSION "${SIMULATE_VERSION}")
549
    endif()
550
551

    # Check the compiler identification string.
552
    if(CMAKE_${lang}_COMPILER_ID)
553
      # The compiler identification was found.
554
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
555
556
        "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \""
        "${file}\"\n\n")
557
    else()
558
      # The compiler identification could not be found.
559
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
560
561
        "The ${lang} compiler identification could not be found in \""
        "${file}\"\n\n")
562
563
    endif()
  endif()
564
565

  # try to figure out the executable format: ELF, COFF, Mach-O
566
567
  if(NOT CMAKE_EXECUTABLE_FORMAT)
    file(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX)
568
569

    # ELF files start with 0x7f"ELF"
570
571
    if("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
      set(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format")
572
    endif()
573
574

#    # COFF (.exe) files start with "MZ"
575
576
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
#      set(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
577
#    endif()
578
579
#
#    # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html
580
581
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
582
#    endif()
583
584
#    if("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
#      set(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
585
#    endif()
586

587
  endif()
588
589
590
  if(NOT DEFINED CMAKE_EXECUTABLE_FORMAT)
    set(CMAKE_EXECUTABLE_FORMAT)
  endif()
591
  # Return the information extracted.
592
593
594
  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}"
595
    PARENT_SCOPE)
596
  set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_${lang}_COMPILER_VERSION}" PARENT_SCOPE)
597
  set(CMAKE_${lang}_COMPILER_WRAPPER "${COMPILER_WRAPPER}" PARENT_SCOPE)
598
599
  set(CMAKE_${lang}_SIMULATE_ID "${CMAKE_${lang}_SIMULATE_ID}" PARENT_SCOPE)
  set(CMAKE_${lang}_SIMULATE_VERSION "${CMAKE_${lang}_SIMULATE_VERSION}" PARENT_SCOPE)
600
  set(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE)
601
  set(COMPILER_QNXNTO "${COMPILER_QNXNTO}" PARENT_SCOPE)
602
  set(CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT "${CMAKE_${lang}_STANDARD_COMPUTED_DEFAULT}" PARENT_SCOPE)
603
endfunction()
604
605
606
607
608
609
610
611
612

#-----------------------------------------------------------------------------
# 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.
613
function(CMAKE_DETERMINE_COMPILER_ID_VENDOR lang)
614

615
  if(NOT CMAKE_${lang}_COMPILER_ID_DIR)
616
617
618
    # 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.
619
    set(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_PLATFORM_INFO_DIR}/CompilerId${lang})
620
621
    file(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
    file(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
622
  endif()
623
624


625
626
627
628
  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(
629
      COMMAND "${CMAKE_${lang}_COMPILER}"
630
631
632
633
634
635
      ${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
636
      TIMEOUT 10
637
      )
638

639
640
    if("${output}" MATCHES "${regex}")
      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
641
642
        "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
        "matched \"${regex}\":\n${output}")
643
644
645
646
647
      set(CMAKE_${lang}_COMPILER_ID "${vendor}" PARENT_SCOPE)
      break()
    else()
      if("${result}" MATCHES  "timeout")
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
648
649
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "terminated after 10 s due to timeout.")
650
651
      else()
        file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
652
653
          "Checking whether the ${lang} compiler is ${vendor} using \"${flags}\" "
          "did not match \"${regex}\":\n${output}")
654
655
656
       endif()
    endif()
  endforeach()
657
endfunction()
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

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
    )
  if(res EQUAL 0 AND "${out}" MATCHES "\n([^:]*:[^:]*:[ \t]*)")
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "${CMAKE_MATCH_1}" PARENT_SCOPE)
  else()
    set(CMAKE_${lang}_CL_SHOWINCLUDES_PREFIX "" PARENT_SCOPE)
  endif()
endfunction()