Apple announced the transition from PowerPC to Intel processors at its developer conference in June 2005. The company then released the first Intel Macs in 2006 and completed the hardware end of the transition by the end of that year, ahead of its original schedule. That meant you could still buy PowerPC Macs as late as 2006. Three years later, the Mac OS X 10.6 update dropped support for PowerPC Macs entirely, and those computers stopped getting new features or access to then-new apps like Google Chrome. PowerPC Macs did receive security updates until 2011, five years after they had last been sold, but no new features or other upgrades.
Longtime Apple users have been through all this before, with the transition from PowerPC to Intel and now for Intel x86 to ARM. All the big platform transition hits are coming back. The transition to ARM from x86 means that some Mac apps will be native and some won't. For apps that support both x86 and ARM, Apple is introducing the "Universal 2" binary that will package both codebases together. For apps that haven't made the transition to ARM yet, the Rosetta emulator is back as "Rosetta 2" and will now let x86 apps run on your ARM Mac, albeit with reduced performance.
Port Powerpc Mac Os Apps To Intel
To help developers with the transition, Apple announced what is technically the first ARM Mac ever: the "Developer Transition Kit." This is a Mac Mini enclosure with an Apple A12Z SoC, the same SoC as an iPad Pro. As the name suggests, it's meant for developers who want to port their x86 apps to ARM macOS, and it comes with a beta version of Big Sur.
In 2006 Apple began the switch to Intel processors, moving away from the PowerPC chip for which both Bungie and The Omni Group had built Oni. For a while, PPC apps could be run on Intel Macs using Rosetta, but support for the old architecture was expected to eventually phase out. In 2009, Feral Interactive (Oni's Mac distributor outside of North America) expressed an interest in putting out an Intel-native build of Oni. They obtained the latest version of Oni's source code from The Omni Group (who had already begun porting it to Intel), and made their initial public release of Oni for Intel Macs in the spring of 2011, a few months before the first version of OS X without Rosetta was released. The Feral build of Oni incorporates a number of changes requested by fans, detailed HERE.
MacPorts variants are conditional modifications of port installation behavior during port installation. There are two types of variants: user-selected variants and platform variants. User-selected variants are options selected by a user when a port is installed; platform variants are selected automatically by MacPorts base according to the OS or hardware platform (darwin, freebsd, linux, i386, powerpc, etc.).
Your porting questions, answered: Learn how to recompile your macOS app for Apple silicon Macs and build universal apps that launch faster, have better performance, and support the future of the platform. We'll show you how Xcode makes it simple to build a universal macOS binary and go through running, debugging, and testing your app. Learn what changes to low-level code you might need to make, find out how to handle in-process and out-of-process plug-ins, and discover some useful tips for working with universal apps.We've designed this session for experienced macOS developers who want to get their existing apps running natively on Apple silicon Macs. You can learn more about doing so in the Apple silicon documentation.For more information on the transition to Apple silicon, watch "Explore the new system architecture of Apple silicon Macs", "Bring your Metal app to Apple silicon Macs", and "Optimize Metal Performance for Apple silicon Macs". And to learn how to run your iPhone and iPad apps on Mac, check out "iPad and iPhone apps on Apple silicon Macs".
If you have any existing Intel only apps, or if for some reason you can't start building your app natively right away, Apple Silicon computers have Rosetta, a translation environment that can seamlessly run these. In Rosetta, the entire process is always translated. You cannot load native code into a translated process or vice versa. You also cannot use Rosetta for kernel extensions, AVX vector instructions, or virtualization. Xcode fully supports building and running apps for Rosetta. Let's look at how that works. As we've noticed before, the run destination in Xcode allows you to target Rosetta. Pressing Run will build the code for Intel and then run it in Rosetta. In Activity Monitor, the app now shows as Intel CPU. So it is running in translation. All aspects of development from Xcode, including testing, debugging, and profiling are supported, and it's all translated on the fly. So if you perhaps happen to use the debugger to look at individual CPU instructions, you'll notice that they are Intel instructions. Don't be surprised by that. They're all being transparently translated by Rosetta. Let's now focus on getting your apps ported over to run natively on Apple Silicon Mac computers. And the first step here is building your apps as universal. Let me start by explaining why I think building your apps for Apple Silicon is actually going to be a very easy task. First of all, the endianness of arm64 is the same as x86. So if you remember the PowerPC to Intel transition, you will not have to deal with any byte order swapping problems this time.
Second, if you have any shared code with iOS apps, that code is almost certainly already fully ported to arm64, because iOS uses the same CPU architecture as Apple Silicon Mac computers. And third, you can use any Mac that you already have to build apps as universal. Xcode 12, the SDK, and the entire toolchain fully support cross compilation. That is, it's able to produce code for a different architecture than the one you're using Xcode on.
In this example project, we've seen a few typical problems when building universal apps. Please see the documentation on the Apple Silicon page on developer.apple.com which covers many of the porting problems that we've run into. If you prefer building on command line with xcodebuild, it's important to select the right destination for building. Use the -showdestinations option to get a list of available run destinations.
In general, use GCD when possible, and avoid splitting your work based on number of available CPUs. Instead, prefer splitting tasks into smaller sized units. For details about GCD, please watch a video from WWDC 2017. And if you're using threading for audio processing, the Meet Audio Workgroups session from this year will help you fine-tune your audio apps and plug-ins. So when you're debugging, testing, and profiling your app, remember that you can build on any Mac, but running native arm64 code needs an Apple Silicon Mac. When running your tests, try to run them under both native and translated modes to discover non-portable code in your tests. And watch out for any Intel-specific code optimizations and any code that is using busy-waiting instead of blocking. The next topic I'd like to talk about is plug-ins, because these need some special considerations on Apple Silicon computers. Plug-ins are a way to dynamically load and execute code. Using plug-ins that just implement standard system extension points via NSExtension is going to just work: both native and translated plug-ins are supported. However, if your app is a plug-in host, and if it's using a custom plug-in loading mechanism, you will need to consider how plug-ins work on Apple Silicon Macs. Your app's process at runtime will contain the code that you wrote and also code from system frameworks. If your app supports plug-ins, it will typically discover them at runtime and then load them when needed. That's called an in-process plug-in model, and typically the app uses a call to dlopen or Bundle.load for this.
Alternatively, the plug-ins can be spawned as new processes, and we call those out-of-process plug-ins. The app and the plug-in process then use some interprocess communication mechanism like XPC. Loading another plug-in typically spawns another process. While out-of-process plug-ins generally provide better security and stability, in-process plug-ins are still very common. If your app is using in-process plug-ins, you need to consider that on macOS on Apple Silicon, all code in one process must always have the same CPU architecture. Let's look at typical use cases for plug-ins. As I've mentioned, there's out-of-process and in-process plug-ins. What's also important is whether the plug-in is first party, which means you are building it from source code and ship it inside your app, or whether it's a third party plug-in that some other software vendor distributes in pre-compiled binary form. If your plug-ins are first party and you can rebuild them, make sure to build them as universal plug-ins, and everything will work. For third party plug-ins using the out-of-process plug-in model, you can make some small changes in your loading code to support both CPU architectures. If you make sure to load the plug-in executable as the right CPU architecture, your app will be able to load both native and translated plug-ins. In-process third party plug-ins have some restrictions. Native apps can only load native plug-ins and Rosetta translated apps can only load Intel-based plug-ins.
Now if this was a third party precompiled plug-in, the right solution would be to contact that third party and urge them to publish a universal build of the plug-in as soon as possible. But let's go back into Xcode because in this case I do have the source code of this plug-in and I should be able to rebuild it as universal. Let's go into my project, and let's open the TLS plug-in target, and let's inspect its Build Settings. It looks like I have some unusual configuration here. I am forcing Architectures to always be x86_64. Now this is probably some leftover from when I wanted to drop 32-bit support, but hard-coding x86_64 is incorrect now. We should instead be using Standard Architectures everywhere. But an even better option is just to avoid setting Architectures altogether. So I will just select the build setting and hit the Delete key. This way Xcode will use the correct default settings. Let's build and run the app again, and this time if I switch to the TLS mode, the plug-in will get loaded correctly now. A typical pattern to load a plug-in is to use dlopen with a file path. It is very important to always check the return value from dlopen, and if it's NULL, the full error message explaining what is wrong is provided by calling dlerror. When running this code with a mismatching plug-in CPU architecture, you will get an error explaining what file on disk has a wrong architecture. That indicates that the plug-in is not universal. I'd like to point out that the out-of-process plug-in model doesn't have this restriction. If you're using in-process plug-ins, I encourage you to explore XPC as a solution. You can have one process per plug-in, but also one process per CPU architecture. In this case, you'll only ever use up to two extra processes. Out-of-process plug-ins provide better stability and security for your app, and for details about XPC I recommend watching a WWDC session from 2013 called Efficient Design with XPC. If your users are stuck with an Intel-only plug-in, they can still force the app to run in Rosetta, which will allow loading those plug-ins. For universal apps, the Info dialog in Finder has a checkbox called Open using Rosetta to do that. This checkbox can be disallowed with an Info.plist key. Details are explained in the Apple Silicon documentation so please refer to it if you'd like to know more. Let me finally share a few tips when working on apps that run on both Intel-based Macs and Apple Silicon Macs. Once your app is building, running, and it's tested and verified to work correctly on each architecture, you're going to start distributing your app, either on the App Store or perhaps by a download link on your web site, in which case you'll need your entire software package to be notarized. Please watch a WWDC session from 2019 called All About Notarization for details. 2ff7e9595c
Comments