CheckCompilerToolchain.cmake 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #
  2. # Copyright (c) 2008-2016 the Urho3D project.
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to deal
  6. # in the Software without restriction, including without limitation the rights
  7. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. # copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. # THE SOFTWARE.
  21. #
  22. # Check the chosen compiler toolchain in the build tree
  23. #
  24. # Native ABI:
  25. # NATIVE_64BIT
  26. #
  27. # Target architecture:
  28. # ARM
  29. # RPI
  30. # POWERPC
  31. #
  32. # Compiler version in major.minor.patch format:
  33. # COMPILER_VERSION
  34. #
  35. # CPU SIMD instruction extensions support:
  36. # HAVE_MMX
  37. # HAVE_3DNOW
  38. # HAVE_SSE
  39. # HAVE_SSE2
  40. # HAVE_ALTIVEC
  41. #
  42. if (NOT MSVC AND NOT DEFINED NATIVE_PREDEFINED_MACROS)
  43. if (IOS OR TVOS)
  44. set (ARCH_FLAGS -arch arm64) # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
  45. endif ()
  46. execute_process (COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_C_COMPILER} ${ARCH_FLAGS} -E -dM - RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE NATIVE_PREDEFINED_MACROS ERROR_QUIET)
  47. if (NOT CC_EXIT_STATUS EQUAL 0)
  48. # Some (fake) compiler front-ends do not understand stdin redirection as the other (real) compiler front-ends do, so workaround it by using a dummy input source file
  49. execute_process (COMMAND ${CMAKE_COMMAND} -E touch dummy.c)
  50. execute_process (COMMAND ${CMAKE_C_COMPILER} dummy.c -E -dM RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE NATIVE_PREDEFINED_MACROS ERROR_QUIET)
  51. execute_process (COMMAND ${CMAKE_COMMAND} -E remove dummy.c)
  52. if (NOT CC_EXIT_STATUS EQUAL 0)
  53. message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler options correctly")
  54. endif ()
  55. endif ()
  56. string (REPLACE \n ";" NATIVE_PREDEFINED_MACROS "${NATIVE_PREDEFINED_MACROS}") # Stringify for string replacement
  57. set (NATIVE_PREDEFINED_MACROS ${NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
  58. endif ()
  59. macro (check_native_define REGEX OUTPUT_VAR)
  60. if (NOT DEFINED ${OUTPUT_VAR})
  61. string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${NATIVE_PREDEFINED_MACROS}")
  62. if (matched)
  63. string (REGEX MATCH "\\(.*\\)" captured "${REGEX}")
  64. if (captured)
  65. set (GROUP 2)
  66. else ()
  67. set (GROUP 1)
  68. endif ()
  69. string (REGEX REPLACE "#define +${REGEX} +([^;]+)" \\${GROUP} matched "${matched}")
  70. set (${OUTPUT_VAR} ${matched})
  71. else ()
  72. set (${OUTPUT_VAR} 0)
  73. endif ()
  74. set (${OUTPUT_VAR} ${${OUTPUT_VAR}} CACHE INTERNAL "Compiler toolchain has predefined macros matching ${REGEX}")
  75. endif ()
  76. endmacro ()
  77. if (MSVC)
  78. # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
  79. # TODO: revisit this later because VS may use Clang as compiler in the future
  80. if (CMAKE_CL_64)
  81. set (NATIVE_64BIT 1)
  82. endif ()
  83. # Determine MSVC compiler version based on CMake informational variables
  84. if (NOT DEFINED COMPILER_VERSION)
  85. # TODO: fix this ugly hardcoding that needs to be constantly maintained
  86. if (MSVC_VERSION EQUAL 1200)
  87. set (COMPILER_VERSION 6.0)
  88. elseif (MSVC_VERSION EQUAL 1300)
  89. set (COMPILER_VERSION 7.0)
  90. elseif (MSVC_VERSION EQUAL 1310)
  91. set (COMPILER_VERSION 7.1)
  92. elseif (MSVC_VERSION EQUAL 1400)
  93. set (COMPILER_VERSION 8.0)
  94. elseif (MSVC_VERSION EQUAL 1500)
  95. set (COMPILER_VERSION 9.0)
  96. elseif (MSVC_VERSION EQUAL 1600)
  97. set (COMPILER_VERSION 10.0)
  98. elseif (MSVC_VERSION EQUAL 1700)
  99. set (COMPILER_VERSION 11.0)
  100. elseif (MSVC_VERSION EQUAL 1800)
  101. set (COMPILER_VERSION 12.0)
  102. elseif (MSVC_VERSION EQUAL 1900)
  103. set (COMPILER_VERSION 14.0)
  104. elseif (MSVC_VERSION GREATER 1900)
  105. set (COMPILER_VERSION 14.0+)
  106. else ()
  107. set (COMPILER_VERSION 6.0-)
  108. endif ()
  109. set (COMPILER_VERSION ${COMPILER_VERSION} CACHE INTERNAL "MSVC Compiler version")
  110. endif ()
  111. else ()
  112. # Determine the native ABI based on the size of pointer
  113. check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
  114. if (SIZEOF_POINTER EQUAL 8)
  115. set (NATIVE_64BIT 1)
  116. endif ()
  117. # Android arm64 compiler only emits __aarch64__ while iOS arm64 emits __aarch64__, __arm64__, and __arm__; for armv7a all emit __arm__
  118. check_native_define ("__(arm|aarch64)__" ARM)
  119. # For completeness sake as currently we do not support PowerPC (yet)
  120. check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
  121. # Check if the target arm platform is currently supported
  122. if (ARM AND NOT ANDROID AND NOT RPI AND NOT IOS AND NOT TVOS)
  123. # TODO: check the uname of the host system for the telltale sign of RPI, just in case this is a native build on the device itself
  124. message (FATAL_ERROR "Unsupported arm target architecture")
  125. endif ()
  126. # GCC/Clang and all their derivatives should understand this command line option to get the compiler version
  127. if (NOT DEFINED COMPILER_VERSION)
  128. execute_process (COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  129. set (COMPILER_VERSION ${COMPILER_VERSION} CACHE INTERNAL "GCC/Clang Compiler version")
  130. endif ()
  131. endif ()
  132. macro (check_extension CPU_INSTRUCTION_EXTENSION)
  133. string (TOUPPER "${CPU_INSTRUCTION_EXTENSION}" UCASE_EXT_NAME) # Stringify to guard against empty variable
  134. if (NOT DEFINED HAVE_${UCASE_EXT_NAME})
  135. execute_process (COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_C_COMPILER} -m${CPU_INSTRUCTION_EXTENSION} -E -dM - RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  136. if (NOT CC_EXIT_STATUS EQUAL 0)
  137. execute_process (COMMAND ${CMAKE_COMMAND} -E touch dummy.c)
  138. execute_process (COMMAND ${CMAKE_C_COMPILER} dummy.c -m${CPU_INSTRUCTION_EXTENSION} -E -dM RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  139. execute_process (COMMAND ${CMAKE_COMMAND} -E remove dummy.c)
  140. if (NOT CC_EXIT_STATUS EQUAL 0)
  141. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler options correctly")
  142. endif ()
  143. endif ()
  144. if (NOT ${ARGN} STREQUAL "")
  145. set (EXPECTED_MACRO ${ARGN})
  146. else ()
  147. set (EXPECTED_MACRO __${UCASE_EXT_NAME}__)
  148. endif ()
  149. string (REGEX MATCH "#define +${EXPECTED_MACRO} +1" matched "${PREDEFINED_MACROS}")
  150. if (matched)
  151. set (matched 1)
  152. else ()
  153. set (matched 0)
  154. endif ()
  155. set (HAVE_${UCASE_EXT_NAME} ${matched} CACHE INTERNAL "Compiler toolchain supports ${UCASE_EXT_NAME} CPU instruction extension")
  156. endif ()
  157. endmacro ()
  158. if (NOT ARM)
  159. if (MSVC)
  160. # In our documentation we have already declared that we only support CPU with SSE2 extension on Windows platform, so we can safely hard-code these for MSVC compiler
  161. foreach (VAR HAVE_MMX HAVE_SSE HAVE_SSE2)
  162. set (${VAR} 1)
  163. endforeach ()
  164. else ()
  165. check_extension (mmx)
  166. check_extension (sse)
  167. check_extension (sse2)
  168. endif ()
  169. # As newer CPUs from AMD do not support 3DNow! anymore, we cannot make any assumption for 3DNow! extension check
  170. # Don't bother with this check on AppleClang and MSVC compiler toolchains (Urho3D only supports CPU with SSE2 on the asscoiated platforms anyway)
  171. if (NOT APPLE AND NOT MSVC)
  172. check_extension (3dnow __3dNOW__)
  173. endif ()
  174. # For completeness sake as currently we do not support PowerPC (yet)
  175. if (POWERPC)
  176. check_extension (altivec)
  177. endif ()
  178. endif ()
  179. # Explicitly set the variable to 1 when it is defined and truthy or 0 when it is not defined or falsy
  180. foreach (VAR NATIVE_64BIT HAVE_MMX HAVE_3DNOW HAVE_SSE HAVE_SSE2 HAVE_ALTIVEC)
  181. if (${VAR})
  182. set (${VAR} 1)
  183. else ()
  184. set (${VAR} 0)
  185. endif ()
  186. endforeach ()