CheckCompilerToolchain.cmake 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. # Copyright (c) 2008-2022 the Urho3D project
  2. # License: MIT
  3. # Check the chosen compiler toolchain in the build tree
  4. #
  5. # Native ABI:
  6. # NATIVE_64BIT
  7. #
  8. # Target architecture:
  9. # ARM
  10. # MIPS
  11. # POWERPC
  12. # WEB
  13. # X86
  14. # E2K
  15. #
  16. # CPU SIMD instruction extensions support for x86/x86_64/e2k archs:
  17. # HAVE_MMX
  18. # HAVE_3DNOW
  19. # HAVE_SSE
  20. # HAVE_SSE2
  21. # HAVE_SSE3
  22. # HAVE_SSE4
  23. # HAVE_AVX
  24. # HAVE_AVX2
  25. #
  26. # CPU SIMD instruction extension support for powerpc/powerpc64 archs:
  27. # HAVE_ALTIVEC
  28. #
  29. # CPU SIMD instruction extension support for arm/arm64 archs:
  30. # HAVE_NEON
  31. # NEON
  32. #
  33. # C++ features:
  34. # RTTI
  35. # EXCEPTIONS
  36. #
  37. # C++11 type traits standard:
  38. # IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE
  39. # IS_TRIVIALLY_DESTRUCTIBLE
  40. # IS_TRIVIALLY_COPY_ASSIGNABLE
  41. # IS_TRIVIALLY_COPY_CONSTRUCTIBLE
  42. # CLANG_PRE_STANDARD (Clang with pre-standard type trait templates)
  43. if (EMSCRIPTEN AND CMAKE_HOST_WIN32)
  44. set (EMCC_FIX EMCC_FIX)
  45. set (NULL_DEVICE${EMCC_FIX} ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/null.c)
  46. execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${NULL_DEVICE${EMCC_FIX}})
  47. endif ()
  48. # Macro for checking if a predefined macro is emitted by the chosen compiler toolchain natively
  49. macro (check_native_define REGEX OUTPUT_VAR)
  50. if (INVALIDATE_CCT OR NOT DEFINED ${OUTPUT_VAR})
  51. string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${NATIVE_PREDEFINED_MACROS}")
  52. if (matched)
  53. string (REGEX MATCH "\\(.*\\)" captured "${REGEX}")
  54. if (captured)
  55. set (GROUP 2)
  56. else ()
  57. set (GROUP 1)
  58. endif ()
  59. string (REGEX REPLACE "#define +${REGEX} +([^;]+)" \\${GROUP} matched "${matched}")
  60. set (${OUTPUT_VAR} ${matched})
  61. else ()
  62. set (${OUTPUT_VAR} 0)
  63. endif ()
  64. set (${OUTPUT_VAR} ${${OUTPUT_VAR}} CACHE INTERNAL "Compiler toolchain has predefined macros matching ${REGEX}")
  65. endif ()
  66. endmacro ()
  67. # Macro for checking if a CPU instruction extension is supported by the chosen compiler toolchain
  68. macro (check_extension EXTENSION)
  69. string (TOUPPER "${EXTENSION}" UCASE_EXT_NAME) # Stringify to guard against empty variable
  70. string (REGEX REPLACE [^=]+= "" UCASE_EXT_NAME "${UCASE_EXT_NAME}")
  71. if (INVALIDATE_CCT OR NOT DEFINED HAVE_${UCASE_EXT_NAME})
  72. 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)
  73. if (NOT CC_EXIT_STATUS EQUAL 0)
  74. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
  75. endif ()
  76. if (NOT ${ARGN} STREQUAL "")
  77. set (EXPECTED_MACRO ${ARGN})
  78. else ()
  79. set (EXPECTED_MACRO __${UCASE_EXT_NAME}__)
  80. endif ()
  81. if (PREDEFINED_MACROS MATCHES "#define +${EXPECTED_MACRO} +1")
  82. set (matched 1)
  83. else ()
  84. set (matched 0)
  85. endif ()
  86. set (HAVE_${UCASE_EXT_NAME} ${matched} CACHE INTERNAL "Compiler toolchain supports ${UCASE_EXT_NAME} CPU instruction extension")
  87. endif ()
  88. endmacro ()
  89. # Macro for checking if a C++ feature is enabled by the configured CXX compiler flags
  90. macro (check_feature_enabled FEATURE)
  91. if (INVALIDATE_CCT OR NOT DEFINED ${FEATURE})
  92. set (COMPILER_FLAGS ${CMAKE_CXX_FLAGS})
  93. separate_arguments (COMPILER_FLAGS)
  94. execute_process (COMMAND ${CMAKE_CXX_COMPILER} ${ARCH_FLAGS} ${COMPILER_FLAGS} -E -dM -xc++ ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CXX_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  95. if (NOT CXX_EXIT_STATUS EQUAL 0)
  96. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
  97. endif ()
  98. if (NOT ${ARGN} STREQUAL "")
  99. set (EXPECTED_MACRO ${ARGN})
  100. else ()
  101. set (EXPECTED_MACRO __${FEATURE})
  102. endif ()
  103. if (PREDEFINED_MACROS MATCHES "#define +${EXPECTED_MACRO} +1")
  104. set (matched 1)
  105. else ()
  106. set (matched 0)
  107. endif ()
  108. set (${FEATURE} ${matched} CACHE INTERNAL "Is ${FEATURE} enabled")
  109. endif ()
  110. endmacro ()
  111. include (CheckCXXSourceCompiles)
  112. # Macro for checking if the type trait template is matching the C++11 standard
  113. macro (check_type_trait TYPE_TRAIT)
  114. string (TOUPPER ${TYPE_TRAIT} UPPERCASE_${TYPE_TRAIT})
  115. if (INVALIDATE_CCT)
  116. unset (${UPPERCASE_${TYPE_TRAIT}} CACHE)
  117. endif ()
  118. if (CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang)
  119. set (ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
  120. set (CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}")
  121. endif ()
  122. check_cxx_source_compiles ("#include <type_traits>\nint main() { return std::${TYPE_TRAIT}<bool>::value; }" ${UPPERCASE_${TYPE_TRAIT}})
  123. if (CMAKE_CXX_COMPILER_ID MATCHES GNU|Clang)
  124. set (CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
  125. endif ()
  126. endmacro ()
  127. # Macro for checking if a native compiler toolchain exists for building the host tool targets
  128. # This macro is designed to be used in cross-compiling build
  129. macro (check_native_compiler_exist)
  130. if (NOT HAVE_NATIVE_COMPILER)
  131. message (STATUS "Performing Test HAVE_NATIVE_COMPILER")
  132. file (WRITE ${CMAKE_BINARY_DIR}/generated/CMakeLists.txt "message (\"Probing native compiler toolchain...\")\n")
  133. execute_process (COMMAND ${CMAKE_COMMAND} -E env CC=${SAVED_CC} CXX=${SAVED_CXX} ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} .
  134. WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/generated RESULT_VARIABLE EXIT_CODE ERROR_VARIABLE ERR_VAR OUTPUT_QUIET)
  135. if (NOT EXIT_CODE EQUAL 0)
  136. message (STATUS "Performing Test HAVE_NATIVE_COMPILER - Failed")
  137. execute_process (COMMAND ${CMAKE_COMMAND} -E remove ${CMAKE_BINARY_DIR}/generated/CMakeCache.txt)
  138. message (FATAL_ERROR "Could not find native compiler toolchain. This is usually caused by wrong PATH env-var value.\n${ERR_VAR}")
  139. endif ()
  140. message (STATUS "Performing Test HAVE_NATIVE_COMPILER - Success")
  141. set (HAVE_NATIVE_COMPILER 1 CACHE INTERNAL "Check native compiler exist")
  142. endif ()
  143. endmacro ()
  144. if (MSVC)
  145. # TODO: revisit this later because VS may use Clang as compiler in the future
  146. # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
  147. set (NATIVE_64BIT ${CMAKE_CL_64})
  148. # We only support one target arch when using MSVC for now and make certain assumptions as per documentation instead of querying the compiler
  149. foreach (VAR X86 HAVE_MMX HAVE_SSE HAVE_SSE2 RTTI EXCEPTIONS IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE IS_TRIVIALLY_DESTRUCTIBLE IS_TRIVIALLY_COPY_ASSIGNABLE IS_TRIVIALLY_COPY_CONSTRUCTIBLE)
  150. set (${VAR} 1)
  151. endforeach ()
  152. else ()
  153. # The 'invalidate event' will be sent by toolchain file when it reconfigures the cross-compiler or compiler flags
  154. if (INVALIDATE_CCT OR NOT DEFINED NATIVE_PREDEFINED_MACROS)
  155. if (IOS OR TVOS)
  156. # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
  157. set (ARCH_FLAGS -arch arm64)
  158. elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
  159. # Use the same target flag as configured by CMake toolchain file, if any
  160. if (ANDROID)
  161. set (ARCH_FLAGS -target ${ANDROID_LLVM_TRIPLE})
  162. elseif (CMAKE_CXX_FLAGS MATCHES -target)
  163. string (REGEX REPLACE "^.*-target ([^ ]+).*$" "-target;\\1" ARCH_FLAGS "${CMAKE_CXX_FLAGS}")
  164. endif ()
  165. endif ()
  166. 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)
  167. if (NOT CC_EXIT_STATUS EQUAL 0)
  168. message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler flags correctly")
  169. endif ()
  170. string (REPLACE \n ";" NATIVE_PREDEFINED_MACROS "${NATIVE_PREDEFINED_MACROS}") # Stringify for string replacement
  171. set (NATIVE_PREDEFINED_MACROS ${NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
  172. endif ()
  173. # Determine the native ABI based on the size of pointer
  174. check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
  175. if (SIZEOF_POINTER EQUAL 8)
  176. set (NATIVE_64BIT 1)
  177. endif ()
  178. # Android arm64 compiler only emits __aarch64__ while iOS/tvOS arm64 emits __aarch64__ and __arm64__; for armv7a all emit __arm__
  179. check_native_define ("__(arm|aarch64)__" ARM)
  180. # For completeness sake as currently we do not support MIPS and PowerPC (yet)
  181. check_native_define (__MIPSEL__ MIPS)
  182. check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
  183. # For now we only support Emscripten compiler toolchain when targeting Web platform
  184. check_native_define (__EMSCRIPTEN__ WEB)
  185. # Compiler should emit __x86_64__, __i686__, or __i386__, etc when targeting archs using Intel or AMD processors
  186. check_native_define ("__(i.86|x86_64)__" X86)
  187. # MCST lcc compiler only emits __e2k__ when targeting arch using MCST Elbrus 2000 processor
  188. check_native_define ("__e2k__" E2K)
  189. if (ARM)
  190. check_feature_enabled (NEON __ARM_NEON)
  191. if (NEON)
  192. # 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
  193. set (HAVE_NEON 1)
  194. else ()
  195. check_extension (fpu=neon __ARM_NEON)
  196. endif ()
  197. elseif (POWERPC)
  198. check_extension (altivec)
  199. elseif (X86 OR E2K)
  200. foreach (ext sse sse2 sse3 sse4 avx avx2)
  201. check_extension (${ext})
  202. endforeach ()
  203. if (CMAKE_SYSTEM_NAME STREQUAL Linux)
  204. check_native_define (__MMX__ HAVE_MMX)
  205. check_native_define (__3dNOW__ HAVE_3DNOW)
  206. endif ()
  207. endif ()
  208. # Check if C++ feature is being turned on/off in the configured compiler flags
  209. check_feature_enabled (RTTI __GXX_RTTI)
  210. check_feature_enabled (EXCEPTIONS)
  211. # Check if C++11 type trait standard is being followed
  212. check_type_trait (is_trivially_default_constructible)
  213. check_type_trait (is_trivially_destructible)
  214. check_type_trait (is_trivially_copy_assignable)
  215. check_type_trait (is_trivially_copy_constructible)
  216. if (CMAKE_CXX_COMPILER_ID MATCHES Clang AND NOT IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE AND IS_TRIVIALLY_DESTRUCTIBLE)
  217. set (CLANG_PRE_STANDARD 1)
  218. endif ()
  219. endif ()