# This is to detect the target architecture. # The detection relies on the compiler's "#error" preprocessor directive to emit the architecture. # This is inspired by https://github.com/axr/solar-cmake/blob/master/TargetArch.cmake # which is inspired by # https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h set(archdetect_c_code " #if defined(__arm__) || defined(__TARGET_ARCH_ARM) \ || defined(__aarch64__) || defined(_M_ARM64) #error cmake_ARCH OJPH_ARCH_ARM #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) #error cmake_ARCH OJPH_ARCH_I386 #elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) #error cmake_ARCH OJPH_ARCH_X86_64 #elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) #error cmake_ARCH OJPH_ARCH_IA64 #elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ || defined(_M_MPPC) || defined(_M_PPC) #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) #error cmake_ARCH OJPH_ARCH_PPC64 #else #error cmake_ARCH OJPH_ARCH_PPC #endif #endif #error cmake_ARCH OJPH_ARCH_UNKNOWN ") function(target_architecture output_var) file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") enable_language(C) # Detect the architecture in a rather creative way... # This compiles a small C program which is a series of ifdefs that selects a # particular #error preprocessor directive whose message string contains the # target architecture. The program will always fail to compile (both because # file is not a valid C program, and obviously because of the presence of the # #error preprocessor directives... but by exploiting the preprocessor in this # way, we can detect the correct target architecture even when cross-compiling, # since the program itself never needs to be run (only the compiler/preprocessor) try_run( run_result_unused compile_result_unused "${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}/arch.c" COMPILE_OUTPUT_VARIABLE ARCH ) # Parse the architecture name from the compiler output string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") # Get rid of the value marker leaving just the architecture name string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") # If we are compiling with an unknown architecture this variable should # already be set to "unknown" but in the case that it's empty (i.e. due # to a typo in the code), then set it to unknown if (NOT ARCH) set(ARCH OJPH_ARCH_UNKNOWN) endif() set(${output_var} "${ARCH}" PARENT_SCOPE) endfunction()