CheckCompilerToolchain.cmake 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. # RPI
  30. # POWERPC
  31. #
  32. # Compiler version in major.minor.patch format, except MSVC where it follows its own 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 (EMSCRIPTEN AND CMAKE_HOST_WIN32)
  43. set (EMCC_FIX EMCC_FIX)
  44. set (NULL_DEVICE${EMCC_FIX} ${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/null.c)
  45. execute_process (COMMAND ${CMAKE_COMMAND} -E touch ${NULL_DEVICE${EMCC_FIX}})
  46. endif ()
  47. if (NOT MSVC AND NOT DEFINED NATIVE_PREDEFINED_MACROS)
  48. if (IOS OR TVOS)
  49. # Assume arm64 is the native arch (this does not prevent our build system to target armv7 later in universal binary build)
  50. set (ARCH_FLAGS -arch arm64)
  51. elseif (ANDROID_COMPILER_IS_CLANG)
  52. # Use the same target flag as configured by Android/CMake toolchain file
  53. string (REGEX REPLACE "^.*-target ([^ ]+).*$" "-target;\\1" ARCH_FLAGS "${ANDROID_CXX_FLAGS}") # Stringify for string replacement
  54. endif ()
  55. 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)
  56. if (NOT CC_EXIT_STATUS EQUAL 0)
  57. message (FATAL_ERROR "Could not check compiler toolchain as it does not handle '-E -dM' compiler flags correctly")
  58. endif ()
  59. string (REPLACE \n ";" NATIVE_PREDEFINED_MACROS "${NATIVE_PREDEFINED_MACROS}") # Stringify for string replacement
  60. set (NATIVE_PREDEFINED_MACROS ${NATIVE_PREDEFINED_MACROS} CACHE INTERNAL "Compiler toolchain native predefined macros")
  61. endif ()
  62. macro (check_native_define REGEX OUTPUT_VAR)
  63. if (NOT DEFINED ${OUTPUT_VAR})
  64. string (REGEX MATCH "#define +${REGEX} +([^;]+)" matched "${NATIVE_PREDEFINED_MACROS}")
  65. if (matched)
  66. string (REGEX MATCH "\\(.*\\)" captured "${REGEX}")
  67. if (captured)
  68. set (GROUP 2)
  69. else ()
  70. set (GROUP 1)
  71. endif ()
  72. string (REGEX REPLACE "#define +${REGEX} +([^;]+)" \\${GROUP} matched "${matched}")
  73. set (${OUTPUT_VAR} ${matched})
  74. else ()
  75. set (${OUTPUT_VAR} 0)
  76. endif ()
  77. set (${OUTPUT_VAR} ${${OUTPUT_VAR}} CACHE INTERNAL "Compiler toolchain has predefined macros matching ${REGEX}")
  78. endif ()
  79. endmacro ()
  80. if (MSVC)
  81. # TODO: revisit this later because VS may use Clang as compiler in the future
  82. # On MSVC compiler, use the chosen CMake/VS generator to determine the ABI
  83. set (NATIVE_64BIT ${CMAKE_CL_64})
  84. # Determine MSVC compiler version based on CMake informational variables
  85. set (COMPILER_VERSION ${MSVC_VERSION})
  86. else ()
  87. # Determine the native ABI based on the size of pointer
  88. check_native_define (__SIZEOF_POINTER__ SIZEOF_POINTER)
  89. if (SIZEOF_POINTER EQUAL 8)
  90. set (NATIVE_64BIT 1)
  91. endif ()
  92. # Android arm64 compiler only emits __aarch64__ while iOS arm64 emits __aarch64__, __arm64__, and __arm__; for armv7a all emit __arm__
  93. check_native_define ("__(arm|aarch64)__" ARM)
  94. # For completeness sake as currently we do not support PowerPC (yet)
  95. check_native_define ("__(ppc|PPC|powerpc|POWERPC)(64)*__" POWERPC)
  96. # GCC/Clang and all their derivatives should understand this command line option to get the compiler version
  97. if (NOT DEFINED COMPILER_VERSION)
  98. execute_process (COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE COMPILER_VERSION ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
  99. set (COMPILER_VERSION ${COMPILER_VERSION} CACHE INTERNAL "GCC/Clang Compiler version")
  100. endif ()
  101. endif ()
  102. macro (check_extension CPU_INSTRUCTION_EXTENSION)
  103. string (TOUPPER "${CPU_INSTRUCTION_EXTENSION}" UCASE_EXT_NAME) # Stringify to guard against empty variable
  104. if (NOT DEFINED HAVE_${UCASE_EXT_NAME})
  105. execute_process (COMMAND ${CMAKE_C_COMPILER} -m${CPU_INSTRUCTION_EXTENSION} -E -dM -xc ${NULL_DEVICE${EMCC_FIX}} RESULT_VARIABLE CC_EXIT_STATUS OUTPUT_VARIABLE PREDEFINED_MACROS ERROR_QUIET)
  106. if (NOT CC_EXIT_STATUS EQUAL 0)
  107. message (FATAL_ERROR "Could not check compiler toolchain CPU instruction extension as it does not handle '-E -dM' compiler flags correctly")
  108. endif ()
  109. if (NOT ${ARGN} STREQUAL "")
  110. set (EXPECTED_MACRO ${ARGN})
  111. else ()
  112. set (EXPECTED_MACRO __${UCASE_EXT_NAME}__)
  113. endif ()
  114. string (REGEX MATCH "#define +${EXPECTED_MACRO} +1" matched "${PREDEFINED_MACROS}")
  115. if (matched)
  116. set (matched 1)
  117. else ()
  118. set (matched 0)
  119. endif ()
  120. set (HAVE_${UCASE_EXT_NAME} ${matched} CACHE INTERNAL "Compiler toolchain supports ${UCASE_EXT_NAME} CPU instruction extension")
  121. endif ()
  122. endmacro ()
  123. if (NOT ARM)
  124. if (MSVC)
  125. # 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
  126. foreach (VAR HAVE_MMX HAVE_SSE HAVE_SSE2)
  127. set (${VAR} 1)
  128. endforeach ()
  129. else ()
  130. if (MINGW AND COMPILER_VERSION VERSION_LESS 4.9.1)
  131. if (NOT DEFINED URHO3D_SSE) # Only give the warning once during initial configuration
  132. # Certain MinGW versions fail to compile SSE code. This is the initial guess for known "bad" version range, and can be tightened later
  133. message (WARNING "Disabling SSE by default due to MinGW version. It is recommended to upgrade to MinGW with GCC >= 4.9.1. You can also try to re-enable SSE with CMake option -DURHO3D_SSE=1, but this may result in compile errors.")
  134. endif ()
  135. elseif (NOT EMSCRIPTEN) # Emscripten does not support SSE/SSE2 (yet) now but erroneously responding positively to our probe, so skip them for Emscripten for now
  136. check_extension (sse)
  137. check_extension (sse2)
  138. endif ()
  139. if (NOT APPLE AND NOT WIN32) # Linux only
  140. check_extension (mmx)
  141. check_extension (3dnow __3dNOW__)
  142. endif ()
  143. endif ()
  144. # For completeness sake as currently we do not support PowerPC (yet)
  145. if (POWERPC)
  146. check_extension (altivec)
  147. endif ()
  148. endif ()
  149. # Explicitly set the variable to 1 when it is defined and truthy or 0 when it is not defined or falsy
  150. foreach (VAR NATIVE_64BIT HAVE_MMX HAVE_3DNOW HAVE_SSE HAVE_SSE2 HAVE_ALTIVEC)
  151. if (${VAR})
  152. set (${VAR} 1)
  153. else ()
  154. set (${VAR} 0)
  155. endif ()
  156. endforeach ()