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