TargetArch.cmake 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # Based on the Qt 5 processor detection code, so should be very accurate
  2. # https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/global/qprocessordetection.h
  3. # Currently handles ARM (v5, v6, v7, v8), ARM64, x86 (32/64), ia64, and ppc (32/64)
  4. # Regarding POWER/PowerPC, just as is noted in the Qt source,
  5. # "There are many more known variants/revisions that we do not handle/detect."
  6. set(archdetect_c_code "
  7. #if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
  8. #if defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64)
  9. #error cmake_ARCH ARM64
  10. #else
  11. #error cmake_ARCH ARM
  12. #endif
  13. #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
  14. #error cmake_ARCH x64
  15. #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
  16. #error cmake_ARCH ia64
  17. #elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
  18. #error cmake_ARCH x86
  19. #else
  20. #error cmake_ARCH unknown
  21. #endif
  22. ")
  23. # Set ppc_support to TRUE before including this file or ppc and ppc64
  24. # will be treated as invalid architectures since they are no longer supported by Apple
  25. message (STATUS ${CMAKE_GENERATOR})
  26. function(get_target_architecture output_var)
  27. if (MSVC AND (${CMAKE_GENERATOR} MATCHES "X64$"))
  28. set (ARCH x64)
  29. elseif (MSVC AND (${CMAKE_GENERATOR} MATCHES "ARM$"))
  30. set (ARCH ARM)
  31. elseif (MSVC AND (${CMAKE_GENERATOR} MATCHES "ARM64$"))
  32. set (ARCH ARM64)
  33. else()
  34. file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
  35. enable_language(C)
  36. # Detect the architecture in a rather creative way...
  37. # This compiles a small C program which is a series of ifdefs that selects a
  38. # particular #error preprocessor directive whose message string contains the
  39. # target architecture. The program will always fail to compile (both because
  40. # file is not a valid C program, and obviously because of the presence of the
  41. # #error preprocessor directives... but by exploiting the preprocessor in this
  42. # way, we can detect the correct target architecture even when cross-compiling,
  43. # since the program itself never needs to be run (only the compiler/preprocessor)
  44. try_run(
  45. run_result_unused
  46. compile_result_unused
  47. "${CMAKE_BINARY_DIR}"
  48. "${CMAKE_BINARY_DIR}/arch.c"
  49. COMPILE_OUTPUT_VARIABLE ARCH
  50. )
  51. # Parse the architecture name from the compiler output
  52. string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}")
  53. # Get rid of the value marker leaving just the architecture name
  54. string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}")
  55. # If we are compiling with an unknown architecture this variable should
  56. # already be set to "unknown" but in the case that it's empty (i.e. due
  57. # to a typo in the code), then set it to unknown
  58. if (NOT ARCH AND MSVC)
  59. set (ARCH x86)
  60. endif()
  61. endif()
  62. set(${output_var} "${ARCH}" PARENT_SCOPE)
  63. endfunction()