Magic, lipo and testing for Universal binaries

I apologise if my recent release of ArchiChect 2.4, and the Universal Binary check added to Mints version 1.0b4, may have brought some confusion. Let me explain why testing for Universal Binaries isn’t as simple as I’d wish.

Apps and other executable code which can run native on both Intel and Apple Silicon Macs aren’t the only ones known as Universal Apps or Binaries. They originated with Multi-Architecture Binaries on NeXTStep, and the Fat Apps and Binaries during the Mac’s first transition from Motorola 68K to PowerPC architectures. In the more recent past, they were general during the transition from PowerPC to Intel. However, the same mechanism also allows a single app or binary to contain both Intel 32- and 64-bit versions, and some files such as /usr/lib/libobjc.dylib support no less than three architectures, all of which are Intel. ‘Universal’ is more generic than just Intel and ARM.

The macOS SDK provides a straightforward way to check the supported architectures for an app or other code bundle, through Bundle.executableArchitectures, which returns an array of integers corresponding to those which are supported. Unfortunately, as far as I know there’s no equivalent call which can reveal those supported by a Mach-O file, such as a command tool.

The most specific and reliable way to check a Mach-O file uses the lipo command tool. However, that takes time, and – until there are ARM64-only versions of Mach-O files in common usage – is only worthwhile if the file is a Universal Binary in the first place.

archichect24

Because ArchiChect only handles single apps and small folders, it can take its time and do the job properly using lipo. The Universal Binary Checker in Mints may have to perform this test tens or even hundreds of thousands of times if you run it on a large folder. So Mints first checks whether a file has the ‘Magic’ indicating that it’s a Universal Binary; only those items which have the Universal ‘Magic’ of 0xCAFEBABE are then tested using lipo to see if they contain ARM64 code.

mintsb402

lipo is a command tool which has been around in Mac OS X for a long time. It not only checks Mach-O files for their support of different architectures, but creates Universal Binaries too. In the past, a basic version of lipo has been provided in /usr/bin, and a more advanced version with Xcode. As far as I can discover, until the release of Mojave, the normal user version of lipo had more limited features and support than that in Xcode. To be specific, prior to macOS 10.14, I suspect that /usr/bin/lipo wasn’t a reliable test for the presence of ARM64 code in a Mach-O file.

It was here that ArchiChect and Mints ran into problems. Apple’s current documentation for lipo states that it will report any support for ARM64 among a long list of architectures, but only since the version which shipped with Mojave. Prior to that, the few users and developers who needed those features normally found it better to use the version of lipo provided in Xcode, which of course may well not be available on any given Mac.

When I realised that it wouldn’t be possible in macOS 10.13 and earlier to test reliably for Mach-O files which run natively on ARM64, I decided that the only good way ahead was to limit the new version of ArchiChect, and the Universal Binary Checker in Mints, to Mojave and later. ArchiChect 2.4 won’t launch at all on High Sierra and earlier: if you want to use that app there, please stick to version 2.3. Mints 1.0b4 still runs fine on Sierra and later, but won’t offer the Universal Binary Checker when it’s running on Sierra or High Sierra.

I apologise for these limitations, and hope that they don’t inconvenience you. However, I think it’s important that both apps return the most accurate results possible, and I don’t think that’s likely on macOS before Mojave, unless proven otherwise.