Skip to content

Instantly share code, notes, and snippets.

@webmaster128
Last active January 31, 2025 22:39
Show Gist options
  • Select an option

  • Save webmaster128/e08067641df1dd784eb195282fd0912f to your computer and use it in GitHub Desktop.

Select an option

Save webmaster128/e08067641df1dd784eb195282fd0912f to your computer and use it in GitHub Desktop.
//
// https://gist.github.com/webmaster128/e08067641df1dd784eb195282fd0912f
//
// The resulting values must not be defined as macros, which
// happens e.g. for 'i386', which is a macro in clang.
// For safety reasons, we undefine everything we output later
//
// For CMake literal compatibility, this file must have no double quotes
//
#ifdef _WIN32
#ifdef _WIN64
#undef x86_64
x86_64
#else
#undef x86
x86
#endif
#elif defined __APPLE__
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#if TARGET_CPU_X86
#undef x86
x86
#elif TARGET_CPU_X86_64
#undef x86_64
x86_64
#elif TARGET_CPU_ARM
#undef armv7
armv7
#elif TARGET_CPU_ARM64
#undef armv8
armv8
#else
#error Unsupported platform
#endif
#elif TARGET_OS_MAC
#undef x86_64
x86_64
#else
#error Unsupported platform
#endif
#elif defined __linux
#ifdef __ANDROID__
#ifdef __i386__
#undef x86
x86
#elif defined __arm__
#undef armv7
armv7
#elif defined __aarch64__
#undef armv8
armv8
#else
#error Unsupported platform
#endif
#else
#ifdef __LP64__
#undef x86_64
x86_64
#else
#undef x86
x86
#endif
#endif
#else
#error Unsupported platform
#endif
@MarkCallow
Copy link
Copy Markdown

MarkCallow commented Mar 15, 2021

I'm including this in my CMakeLists.txt with

EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -E ${CMAKE_SOURCE_DIR}/platformtest.c COMMAND tail -1 COMMAND tr -d '\n' OUTPUT_VARIABLE CPU_ARCHITECTURE )

but I get an error that TargetConditionals.h could not be found. (I'm running on Mac.) When I run cc -E platformtest.c in a terminal there is no problem. I changed it to the following and it compiles.

EXECUTE_PROCESS( COMMAND ${CMAKE_C_COMPILER} -E -I /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk ${CMAKE_SOURCE_DIR}/platformtest.c COMMAND tail -1 COMMAND tr -d '\n' OUTPUT_VARIABLE CPU_ARCHITECTURE )

but I'm not too happy with that as the user may not have the command line tools installed. How did you get it working?

The tail -1 is to strip all the line number directives that the compiler prints as part of the -E output. The tr is to remove the trailing new line so the string comparison in CMake works.

Thanks for this but a complete working example would have been even more useful. I've spent an hour getting it to function.

@webmaster128
Copy link
Copy Markdown
Author

I embedded this as follows. However, it might not be working anymore. I don't actually use this anymore, so I can only dump how it was integrated, not test or support the gist.

cmake_minimum_required(VERSION 2.8.12)

set(platformtest_code "
//
// https://gist.github.com/webmaster128/e08067641df1dd784eb195282fd0912f
//
// The resulting values must not be defined as macros, which
// happens e.g. for 'i386', which is a macro in clang.
// For safety reasons, we undefine everything we output later
//
// For CMake literal compatibility, this file must have no double quotes
//
#ifdef _WIN32
    #ifdef _WIN64

#undef x86_64
x86_64

    #else

#undef x86_32
x86_32

    #endif
#elif defined __APPLE__
    #include <TargetConditionals.h>
    #if TARGET_OS_IPHONE
        #if TARGET_CPU_X86

#undef x86_32
x86_32

        #elif TARGET_CPU_X86_64

#undef x86_64
x86_64

        #elif TARGET_CPU_ARM

#undef armv7
armv7

        #elif TARGET_CPU_ARM64

#undef armv8
armv8

        #else
            #error Unsupported platform
        #endif
    #elif TARGET_OS_MAC

#undef x86_64
x86_64

    #else
        #error Unsupported platform
    #endif
#elif defined __linux
    #ifdef __ANDROID__
        #ifdef __i386__

#undef x86_32
x86_32

        #elif defined __arm__

#undef armv7
armv7

        #elif defined __aarch64__

#undef armv8
armv8

        #else
            #error Unsupported platform
        #endif
    #else
        #ifdef __LP64__

#undef x86_64
x86_64

        #else

#undef x86_32
x86_32

        #endif
    #endif
#else
    #error Unsupported platform
#endif
")
file(WRITE "${CMAKE_BINARY_DIR}/platformtest.c" "${platformtest_code}")

function(set_crosscompile_target_processor_type out)
    if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
        set(${out} armv7 PARENT_SCOPE)
    elseif(${ANDROID_ABI} STREQUAL "arm64-v8a")
        set(${out} armv8 PARENT_SCOPE)
    elseif(${ANDROID_ABI} STREQUAL "x86")
        set(${out} x86_32 PARENT_SCOPE)
    elseif(${ANDROID_ABI} STREQUAL "x86_64")
        set(${out} x86_64 PARENT_SCOPE)

    else()
        # Workaround for CMake < 3.1: Variables such as 'MSVC' are expanded in 'if'
        # statements even if they are quoted. We can't enable the policy CMP0054 because
        # we need to support CMake 2.8. Therefore, we append a space on both sides,
        # which disables automatic expansion.
        if("${CMAKE_CXX_COMPILER_ID} " STREQUAL "MSVC ")
            set(C_PREPROCESS ${CMAKE_C_COMPILER} /EP /nologo)
        else()
            set(C_PREPROCESS ${CMAKE_C_COMPILER} -E -P)
        endif()

        execute_process(
            COMMAND ${C_PREPROCESS} "${CMAKE_BINARY_DIR}/platformtest.c"
            OUTPUT_VARIABLE processor
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        string(STRIP "${processor}" processor)
        set(${out} ${processor} PARENT_SCOPE)
    endif()
endfunction(set_crosscompile_target_processor_type)

@MarkCallow
Copy link
Copy Markdown

Thank you for this. I still need the -I to find TargetConditionals.h and I had to change the ANDROID_ABI part as follows to avoid "STREQUAL being taken as an argument to if rather than an operator.

    if(${ANDROID_ABI} AND ${ANDROID_ABI} STREQUAL "armeabi-v7a")
        set(${out} armv7 PARENT_SCOPE)
    elseif(${ANDROID_ABI} AND ${ANDROID_ABI} STREQUAL "arm64-v8a")
        set(${out} armv8 PARENT_SCOPE)
    elseif(${ANDROID_ABI} AND ${ANDROID_ABI} STREQUAL "x86")
        set(${out} x86_32 PARENT_SCOPE)
    elseif(${ANDROID_ABI} AND ${ANDROID_ABI} STREQUAL "x86_64")
        set(${out} x86_64 PARENT_SCOPE)

With those changes, it works!.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment