CMakeDetermineCompilerId.cmake 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #=============================================================================
  2. # Copyright 2007-2009 Kitware, Inc.
  3. #
  4. # Distributed under the OSI-approved BSD License (the "License");
  5. # see accompanying file Copyright.txt for details.
  6. #
  7. # This software is distributed WITHOUT ANY WARRANTY; without even the
  8. # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  9. # See the License for more information.
  10. #=============================================================================
  11. # (To distributed this file outside of CMake, substitute the full
  12. # License text for the above reference.)
  13. # Function to compile a source file to identify the compiler. This is
  14. # used internally by CMake and should not be included by user code.
  15. # If successful, sets CMAKE_<lang>_COMPILER_ID and CMAKE_<lang>_PLATFORM_ID
  16. FUNCTION(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
  17. # Make sure the compiler arguments are clean.
  18. STRING(STRIP "${CMAKE_${lang}_COMPILER_ARG1}" CMAKE_${lang}_COMPILER_ID_ARG1)
  19. # Make sure user-specified compiler flags are used.
  20. IF(CMAKE_${lang}_FLAGS)
  21. SET(CMAKE_${lang}_COMPILER_ID_FLAGS ${CMAKE_${lang}_FLAGS})
  22. ELSE(CMAKE_${lang}_FLAGS)
  23. SET(CMAKE_${lang}_COMPILER_ID_FLAGS $ENV{${flagvar}})
  24. ENDIF(CMAKE_${lang}_FLAGS)
  25. STRING(REGEX REPLACE " " ";" CMAKE_${lang}_COMPILER_ID_FLAGS_LIST "${CMAKE_${lang}_COMPILER_ID_FLAGS}")
  26. # Compute the directory in which to run the test.
  27. SET(CMAKE_${lang}_COMPILER_ID_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CompilerId${lang})
  28. # Try building with no extra flags and then try each set
  29. # of helper flags. Stop when the compiler is identified.
  30. FOREACH(flags "" ${CMAKE_${lang}_COMPILER_ID_TEST_FLAGS})
  31. IF(NOT CMAKE_${lang}_COMPILER_ID)
  32. CMAKE_DETERMINE_COMPILER_ID_BUILD("${lang}" "${flags}" "${src}")
  33. FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES})
  34. CMAKE_DETERMINE_COMPILER_ID_CHECK("${lang}" "${CMAKE_${lang}_COMPILER_ID_DIR}/${file}" "${src}")
  35. ENDFOREACH(file)
  36. ENDIF(NOT CMAKE_${lang}_COMPILER_ID)
  37. ENDFOREACH(flags)
  38. # if the format is unknown after all files have been checked, put "Unknown" in the cache
  39. IF(NOT CMAKE_EXECUTABLE_FORMAT)
  40. SET(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
  41. ENDIF(NOT CMAKE_EXECUTABLE_FORMAT)
  42. # Display the final identification result.
  43. IF(CMAKE_${lang}_COMPILER_ID)
  44. MESSAGE(STATUS "The ${lang} compiler identification is "
  45. "${CMAKE_${lang}_COMPILER_ID}")
  46. ELSE(CMAKE_${lang}_COMPILER_ID)
  47. MESSAGE(STATUS "The ${lang} compiler identification is unknown")
  48. ENDIF(CMAKE_${lang}_COMPILER_ID)
  49. SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  50. SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
  51. ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID)
  52. #-----------------------------------------------------------------------------
  53. # Function to write the compiler id source file.
  54. FUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE lang src)
  55. FILE(READ ${CMAKE_ROOT}/Modules/${src}.in ID_CONTENT_IN)
  56. STRING(CONFIGURE "${ID_CONTENT_IN}" ID_CONTENT_OUT @ONLY)
  57. FILE(WRITE ${CMAKE_${lang}_COMPILER_ID_DIR}/${src} "${ID_CONTENT_OUT}")
  58. ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_WRITE)
  59. #-----------------------------------------------------------------------------
  60. # Function to build the compiler id source file and look for output
  61. # files.
  62. FUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
  63. # Create a clean working directory.
  64. FILE(REMOVE_RECURSE ${CMAKE_${lang}_COMPILER_ID_DIR})
  65. FILE(MAKE_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR})
  66. CMAKE_DETERMINE_COMPILER_ID_WRITE("${lang}" "${src}")
  67. # Construct a description of this test case.
  68. SET(COMPILER_DESCRIPTION
  69. "Compiler: ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_ARG1}
  70. Build flags: ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
  71. Id flags: ${testflags}
  72. ")
  73. # Compile the compiler identification source.
  74. IF(COMMAND EXECUTE_PROCESS)
  75. EXECUTE_PROCESS(
  76. COMMAND ${CMAKE_${lang}_COMPILER}
  77. ${CMAKE_${lang}_COMPILER_ID_ARG1}
  78. ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
  79. ${testflags}
  80. "${src}"
  81. WORKING_DIRECTORY ${CMAKE_${lang}_COMPILER_ID_DIR}
  82. OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
  83. ERROR_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
  84. RESULT_VARIABLE CMAKE_${lang}_COMPILER_ID_RESULT
  85. )
  86. ELSE(COMMAND EXECUTE_PROCESS)
  87. EXEC_PROGRAM(
  88. ${CMAKE_${lang}_COMPILER} ${CMAKE_${lang}_COMPILER_ID_DIR}
  89. ARGS ${CMAKE_${lang}_COMPILER_ID_ARG1}
  90. ${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}
  91. ${testflags}
  92. \"${src}\"
  93. OUTPUT_VARIABLE CMAKE_${lang}_COMPILER_ID_OUTPUT
  94. RETURN_VALUE CMAKE_${lang}_COMPILER_ID_RESULT
  95. )
  96. ENDIF(COMMAND EXECUTE_PROCESS)
  97. # Check the result of compilation.
  98. IF(CMAKE_${lang}_COMPILER_ID_RESULT)
  99. # Compilation failed.
  100. SET(MSG
  101. "Compiling the ${lang} compiler identification source file \"${src}\" failed.
  102. ${COMPILER_DESCRIPTION}
  103. The output was:
  104. ${CMAKE_${lang}_COMPILER_ID_RESULT}
  105. ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
  106. ")
  107. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "${MSG}")
  108. #IF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
  109. # MESSAGE(FATAL_ERROR "${MSG}")
  110. #ENDIF(NOT CMAKE_${lang}_COMPILER_ID_ALLOW_FAIL)
  111. # No output files should be inspected.
  112. SET(COMPILER_${lang}_PRODUCED_FILES)
  113. ELSE(CMAKE_${lang}_COMPILER_ID_RESULT)
  114. # Compilation succeeded.
  115. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  116. "Compiling the ${lang} compiler identification source file \"${src}\" succeeded.
  117. ${COMPILER_DESCRIPTION}
  118. The output was:
  119. ${CMAKE_${lang}_COMPILER_ID_RESULT}
  120. ${CMAKE_${lang}_COMPILER_ID_OUTPUT}
  121. ")
  122. # Find the executable produced by the compiler, try all files in the
  123. # binary dir.
  124. FILE(GLOB COMPILER_${lang}_PRODUCED_FILES
  125. RELATIVE ${CMAKE_${lang}_COMPILER_ID_DIR}
  126. ${CMAKE_${lang}_COMPILER_ID_DIR}/*)
  127. LIST(REMOVE_ITEM COMPILER_${lang}_PRODUCED_FILES "${src}")
  128. FOREACH(file ${COMPILER_${lang}_PRODUCED_FILES})
  129. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  130. "Compilation of the ${lang} compiler identification source \""
  131. "${src}\" produced \"${file}\"\n\n")
  132. ENDFOREACH(file)
  133. IF(NOT COMPILER_${lang}_PRODUCED_FILES)
  134. # No executable was found.
  135. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  136. "Compilation of the ${lang} compiler identification source \""
  137. "${src}\" did not produce an executable in \""
  138. "${CMAKE_${lang}_COMPILER_ID_DIR}\".\n\n")
  139. ENDIF(NOT COMPILER_${lang}_PRODUCED_FILES)
  140. ENDIF(CMAKE_${lang}_COMPILER_ID_RESULT)
  141. # Return the files produced by the compilation.
  142. SET(COMPILER_${lang}_PRODUCED_FILES "${COMPILER_${lang}_PRODUCED_FILES}" PARENT_SCOPE)
  143. ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_BUILD lang testflags src)
  144. #-----------------------------------------------------------------------------
  145. # Function to extract the compiler id from an executable.
  146. FUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang file)
  147. # Look for a compiler id if not yet known.
  148. IF(NOT CMAKE_${lang}_COMPILER_ID)
  149. # Read the compiler identification string from the executable file.
  150. SET(COMPILER_ID)
  151. SET(PLATFORM_ID)
  152. FILE(STRINGS ${file}
  153. CMAKE_${lang}_COMPILER_ID_STRINGS LIMIT_COUNT 2 REGEX "INFO:")
  154. SET(HAVE_COMPILER_TWICE 0)
  155. FOREACH(info ${CMAKE_${lang}_COMPILER_ID_STRINGS})
  156. IF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*")
  157. IF(COMPILER_ID)
  158. SET(COMPILER_ID_TWICE 1)
  159. ENDIF(COMPILER_ID)
  160. STRING(REGEX REPLACE ".*INFO:compiler\\[([^]]*)\\].*" "\\1"
  161. COMPILER_ID "${info}")
  162. ENDIF("${info}" MATCHES ".*INFO:compiler\\[([^]\"]*)\\].*")
  163. IF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*")
  164. STRING(REGEX REPLACE ".*INFO:platform\\[([^]]*)\\].*" "\\1"
  165. PLATFORM_ID "${info}")
  166. ENDIF("${info}" MATCHES ".*INFO:platform\\[([^]\"]*)\\].*")
  167. ENDFOREACH(info)
  168. # Check if a valid compiler and platform were found.
  169. IF(COMPILER_ID AND NOT COMPILER_ID_TWICE)
  170. SET(CMAKE_${lang}_COMPILER_ID "${COMPILER_ID}")
  171. SET(CMAKE_${lang}_PLATFORM_ID "${PLATFORM_ID}")
  172. ENDIF(COMPILER_ID AND NOT COMPILER_ID_TWICE)
  173. # Check the compiler identification string.
  174. IF(CMAKE_${lang}_COMPILER_ID)
  175. # The compiler identification was found.
  176. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
  177. "The ${lang} compiler identification is ${CMAKE_${lang}_COMPILER_ID}, found in \""
  178. "${file}\"\n\n")
  179. ELSE(CMAKE_${lang}_COMPILER_ID)
  180. # The compiler identification could not be found.
  181. FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
  182. "The ${lang} compiler identification could not be found in \""
  183. "${file}\"\n\n")
  184. ENDIF(CMAKE_${lang}_COMPILER_ID)
  185. ENDIF(NOT CMAKE_${lang}_COMPILER_ID)
  186. # try to figure out the executable format: ELF, COFF, Mach-O
  187. IF(NOT CMAKE_EXECUTABLE_FORMAT)
  188. FILE(READ ${file} CMAKE_EXECUTABLE_MAGIC LIMIT 4 HEX)
  189. # ELF files start with 0x7f"ELF"
  190. IF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
  191. SET(CMAKE_EXECUTABLE_FORMAT "ELF" CACHE INTERNAL "Executable file format")
  192. ENDIF("${CMAKE_EXECUTABLE_MAGIC}" STREQUAL "7f454c46")
  193. # # COFF (.exe) files start with "MZ"
  194. # IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
  195. # SET(CMAKE_EXECUTABLE_FORMAT "COFF" CACHE STRING "Executable file format")
  196. # ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "4d5a....")
  197. #
  198. # # Mach-O files start with CAFEBABE or FEEDFACE, according to http://radio.weblogs.com/0100490/2003/01/28.html
  199. # IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
  200. # SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
  201. # ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "cafebabe")
  202. # IF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
  203. # SET(CMAKE_EXECUTABLE_FORMAT "MACHO" CACHE STRING "Executable file format")
  204. # ENDIF("${CMAKE_EXECUTABLE_MAGIC}" MATCHES "feedface")
  205. ENDIF(NOT CMAKE_EXECUTABLE_FORMAT)
  206. # Return the information extracted.
  207. SET(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
  208. SET(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
  209. SET(CMAKE_EXECUTABLE_FORMAT "${CMAKE_EXECUTABLE_FORMAT}" PARENT_SCOPE)
  210. ENDFUNCTION(CMAKE_DETERMINE_COMPILER_ID_CHECK lang)