3

I am writing a code for macOS application. The application would be running on M1 based Macs as well as Intel based Macs also. What would be the switch to differentiate M1 and Intel?

if (M1)
{
   do something for M1
}
else if (Intel)
{
   do something for Intel
}
NJP
  • 63
  • 6

3 Answers3

3

I think, you can use __arm__ to detect arm architecture:

#ifdef __arm__
//do smth on arm (M1)
#else
//do smth on x86 (Intel)
#endif
Andrew Romanov
  • 4,774
  • 3
  • 25
  • 40
  • 2
    Note to the OP, who I suspect is under the false impression they're going to be able to do this in-code *with a single build*: you can't. The above solution will build two different versions, dependent and based on the toolchain used, the chosen target platform at build-time, and the predefined macros provided therein. The result is two different builds; one for M1 and one for anything-not-arm, and distribution of said-same to the appropriate target is on the onus of the OP. – WhozCraig Feb 18 '21 at 08:46
  • 2
    When you archive an application, the Xcode creates a fat application or library (one executor has code for both platform). If you just build (with a run button), you will get application only for one platform (not for all). – Andrew Romanov Feb 18 '21 at 08:50
  • To detect a processor name, you can use "hw.cputype", https://stackoverflow.com/questions/19859388/how-can-i-get-the-ios-device-cpu-architecture-in-runtime . But, I think, also you will want to detect emulation mode for your application: https://developer.apple.com/forums/thread/652667 – Andrew Romanov Feb 18 '21 at 08:55
  • 2
    For me, `__arm__` was not defined on my M1 MacBook Pro. I had to use `__arm64__`. – Josh Sep 14 '22 at 17:30
2

I was just fooling around with this and found this reference for Objective-C from apple that seemed to work with clang for C++.

// Objective-C example
#include "TargetConditionals.h"
#if TARGET_OS_OSX
  // Put CPU-independent macOS code here.
  #if TARGET_CPU_ARM64
    // Put 64-bit Apple silicon macOS code here.
  #elif TARGET_CPU_X86_64
    // Put 64-bit Intel macOS code here.
  #endif
#elif TARGET_OS_MACCATALYST
   // Put Mac Catalyst-specific code here.
#elif TARGET_OS_IOS
  // Put iOS-specific code here.
#endif

https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary

I specifically checked to see if TARGET_CPU_ARM64 was defined in my header.

Hopefully this helps someone.

Luc
  • 87
  • 5
0

If you need a runtime check instead of compile time check, you can think of using something like below

#include <sys/sysctl.h>
#include <mach/machine.h>

int main(int argc, const char * argv[]) 
{
    cpu_type_t type;
    size_t size = sizeof(type);
    sysctlbyname("hw.cputype", &type, &size, NULL, 0);

    int procTranslated;
    size = sizeof(procTranslated);
    // Checks whether process is translated by Rosetta
    sysctlbyname("sysctl.proc_translated", &procTranslated, &size, NULL, 0);

    // Removes CPU_ARCH_ABI64 or CPU_ARCH_ABI64_32 encoded with the Type
    cpu_type_t typeWithABIInfoRemoved = type & ~CPU_ARCH_MASK;

    if (typeWithABIInfoRemoved == CPU_TYPE_X86)
    {
        if (procTranslated == 1)
        {
            cout << "ARM Processor (Running x86 application in Rosetta)";
        }
        else
        {
            cout << "Intel Processor";
        }
    }
    else if (typeWithABIInfoRemoved == CPU_TYPE_ARM)
    {
        cout << "ARM Processor";
    }
}
Titus
  • 907
  • 8
  • 18