CheckCompilerToolchain.cmake 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #
  2. # Copyright (c) 2008-2017 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. # MIPS
  30. # POWERPC
  31. # WEB
  32. # X86
  33. #
  34. # CPU SIMD instruction extensions support for x86/x86_64 archs:
  35. # HAVE_MMX
  36. # HAVE_3DNOW
  37. # HAVE_SSE
  38. # HAVE_SSE2
  39. # HAVE_ALTIVEC
  40. #
  41. # CPU SIMD instruction extension support for arm/arm64 archs:
  42. # HAVE_NEON
  43. # NEON
  44. #
  45. # C++ features:
  46. # RTTI
  47. # EXCEPTIONS
  48. #
  49. if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
  50. set (EMCC_FIX EMCC_FIX)
  51. set (NULL_DEVICE${EMCC_FIX} ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/null.c)
  52. execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${NULL_DEVICE${EMCC_FIX}})
  53. endif ()
  54. # Macro for checking if a predefined macro is emitted by the chosen compiler toolchain natively
  55. macro (check_native_define REGEX OUTPUT_VAR)
  56. if (INVALIDATE_CCT OR NOT DEFINED ${OUTPUT_VAR})
  57. string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${NATIVE_PREDEFINED_MACROS}")
  58. if (matched)
  59. string (REGEX MATCH "\\(.*\\)" captured "${REGEX}")
  60. if (captured)
  61. set (GROUP 2)
  62. else ()
  63. set (GROUP 1)
  64. endif ()
  65. string (REGEX REPLACE "#define +${REGEX} +([^;]+)" \\${GROUP} matched "${matched}")
  66. set (${OUTPUT_VAR} ${matched})
  67. else ()
  68. set (${OUTPUT_VAR} 0)
  69. endif ()
  70. set (${OUTPUT_VAR} ${${OUTPUT_VAR}} CACHE INTERNAL "Compiler toolchain has predefined macros matching ${REGEX}")
  71. endif ()
  72. endmacro ()
  73. # Macro for checking if a CPU instruction extension is supported by the chosen compiler toolchain
  74. macro (check_extension EXTENSION)
  75. string (TOUPPER "${EXTENSION}" UCASE_EXT_NAME) # Stringify to guard against empty variable
  76. string (REGEX REPLACE [^=]+= "" UCASE_EXT_NAME "${UCASE_EXT_NAME}")
  77. if (INVALIDATE_CCT OR NOT DEFINED HAVE_${UCASE_EXT_NAME})
  78. execute_process (COMMAND ${CMAKE_C_COMPILER} ${ARCH_FLAGS} -m${EXTENSION} -E -dM -xc ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  79. if (NOT CC_EXIT_STATUS EQUAL 0)
  80. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
  81. endif ()
  82. if (NOT ${ARGN} STREQUAL "")
  83. set (EXPECTED_MACRO ${ARGN})
  84. else ()
  85. set (EXPECTED_MACRO __${UCASE_EXT_NAME}__)
  86. endif ()
  87. if (PREDEFINED_MACROS MATCHES "#define +${EXPECTED_MACRO} +1")
  88. set (matched 1)
  89. else ()
  90. set (matched 0)
  91. endif ()
  92. set (HAVE_${UCASE_EXT_NAME} ${matched} CACHE INTERNAL "Compiler toolchain supports ${UCASE_EXT_NAME} CPU instruction extension")
  93. endif ()
  94. endmacro ()
  95. # Macro for checking if a C++ feature is enabled by the configured CXX compiler flags
  96. macro (check_feature_enabled FEATURE)
  97. if (INVALIDATE_CCT OR NOT DEFINED ${FEATURE})
  98. set (COMPILER_FLAGS ${CMAKE_CXX_FLAGS})
  99. separate_arguments (COMPILER_FLAGS)
  100. execute_process (COMMAND ${CMAKE_CXX_COMPILER} ${COMPILER_FLAGS} -E -dM -xc++ ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CXX_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  101. if (NOT CXX_EXIT_STATUS EQUAL 0)
  102. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
  103. endif ()
  104. if (NOT ${ARGN} STREQUAL "")
  105. set (EXPECTED_MACRO ${ARGN})
  106. else ()
  107. set (EXPECTED_MACRO __${FEATURE})
  108. endif ()
  109. if (PREDEFINED_MACROS MATCHES "#define +${EXPECTED_MACRO} +1")
  110. set (matched 1)
  111. else ()
  112. set (matched 0)
  113. endif ()
  114. set (${FEATURE} ${matched} CACHE INTERNAL "Is ${FEATURE} enabled")
  115. endif ()
  116. endmacro ()
  117. # Macro for checking if a native compiler toolchain exists for building the host tool targets
  118. # This macro is designed to be used in cross-compiling build
  119. macro (check_native_compiler_exist)
  120. if (NOT HAVE_NATIVE_COMPILER)
  121. message (STATUS "Performing Test HAVE_NATIVE_COMPILER")
  122. file (WRITE ${CMAKE_BINARY_DIR}/generated/CMakeLists.txt "message (\"Probing native compiler toolchain...\")\n")
  123. execute_process (COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} .
  124. WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/generated RESULT_VARIABLE EXIT_CODE ERROR_VARIABLE ERR_VAR OUTPUT_QUIET)
  125. if (NOT EXIT_CODE EQUAL 0)
  126. message (STATUS "Performing Test HAVE_NATIVE_COMPILER - Failed")
  127. execute_process (COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/generated/CMakeCache.txt)
  128. message (FATAL_ERROR "Could not find native compiler toolchain. This is usually caused by wrong PATH env-var value.\n${ERR_VAR}")
  129. endif ()
  130. message (STATUS "Performing Test HAVE_NATIVE_COMPILER - Success")
  131. set (HAVE_NATIVE_COMPILER 1 CACHE INTERNAL "Check native compiler exist")
  132. endif ()
  133. endmacro ()
  134. if (MSVC)
  135. # TODO: revisit this later because VS may use Clang as compiler in the future
  136. # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
  137. set (NATIVE_64BIT ${CMAKE_CL_64})
  138. # We only support one target arch when using MSVC for now and make certain assumptions as per documentation instead of querying the compiler
  139. foreach (VAR X86 HAVE_MMX HAVE_SSE HAVE_SSE2 RTTI EXCEPTIONS)
  140. set (${VAR} 1)
  141. endforeach ()
  142. else ()
  143. # The 'invalidate event' will be sent by toolchain file when it reconfigures the cross-compiler or compiler flags
  144. if (INVALIDATE_CCT OR NOT DEFINED NATIVE_PREDEFINED_MACROS)
  145. if (IOS OR TVOS)
  146. # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
  147. set (ARCH_FLAGS -arch arm64)
  148. elseif (ANDROID AND CMAKE_CXX_COMPILER_ID MATCHES Clang)
  149. # Use the same target flag as configured by Android/CMake toolchain file
  150. string (REGEX REPLACE "^.*-target ([^ ]+).*$" "-target;\\1" ARCH_FLAGS "${CMAKE_CXX_FLAGS}")
  151. endif ()
  152. execute_process (COMMAND ${CMAKE_C_COMPILER} ${ARCH_FLAGS} -E -dM -xc ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE NATIVE_PREDEFINED_MACROS ERROR_QUIET)
  153. if (NOT CC_EXIT_STATUS EQUAL 0)
  154. message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler flags correctly")
  155. endif ()
  156. string (REPLACE \n ";" NATIVE_PREDEFINED_MACROS "${NATIVE_PREDEFINED_MACROS}") # Stringify for string replacement
  157. set (NATIVE_PREDEFINED_MACROS ${NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
  158. endif ()
  159. # Determine the native ABI based on the size of pointer
  160. check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
  161. if (SIZEOF_POINTER EQUAL 8)
  162. set (NATIVE_64BIT 1)
  163. endif ()
  164. # Android arm64 compiler only emits __aarch64__ while iOS arm64 emits __aarch64__, __arm64__, and __arm__; for armv7a all emit __arm__
  165. check_native_define ("__(arm|aarch64)__" ARM)
  166. # For completeness sake as currently we do not support MIPS and PowerPC (yet)
  167. check_native_define (__MIPSEL__ MIPS)
  168. check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
  169. # For now we only support Emscripten compiler toolchain when targeting Web platform
  170. check_native_define (__EMSCRIPTEN__ WEB)
  171. # Compiler should emit __x86_64__, __i686__, or __i386__, etc when targeting archs using Intel or AMD processors
  172. check_native_define ("__(i.86|x86_64)__" X86)
  173. if (ARM)
  174. check_feature_enabled (NEON __ARM_NEON)
  175. if (NEON)
  176. # NEON is enabled by default on aarch64 arch so its compiler emits __ARM_NEON by default even though it does not support '-mfpu' compiler flag
  177. set (HAVE_NEON 1)
  178. else ()
  179. check_extension (fpu=neon __ARM_NEON)
  180. endif ()
  181. elseif (POWERPC)
  182. check_extension (altivec)
  183. elseif (X86)
  184. check_extension (sse)
  185. check_extension (sse2)
  186. if (CMAKE_SYSTEM_NAME STREQUAL Linux)
  187. check_extension (mmx)
  188. check_extension (3dnow __3dNOW__)
  189. endif ()
  190. endif ()
  191. # Check if C++ feature is being turned on/off in the configured compiler flags
  192. check_feature_enabled (RTTI __GXX_RTTI)
  193. check_feature_enabled (EXCEPTIONS)
  194. endif ()