Apple M1 and VST SDK 3.7.1

I have been running a bunch of tests with Apple M1 and wanted to share my results.

Here are the test results.

Now for some explanation:

  • all the tests are using VST3 SDK 3.7.1 which is the most recent SDK at the time I ran the tests

  • Intel is a (“old”) MacBook pro running macOS Mojave v10.14.6 and Xcode 11.3.1 and is of course using the intel / chipset [x86_64]

  • M1 is a new MacBook Air running macOS Big Sur v11.0 and Xcode 12.3 and is using the new Apple M1 arm chipset [arm64]

  • The first column (column A) shows the hardware running the test (rows 3-6 are on Intel, 8-11 are on M1)

  • I have then built the validator tool and a test plugin 4 different ways:

  1. intel x86_64 means it was built on the Intel hardware using the x86_64 architecture (note that this is the only possible way of building for this platform)
  2. m1 x86_64 means it was built on the M1 hardware using the x86_64 architecture
  3. m1 arm64 means it was built on the M1 hardware using the arm64 architecture (which is native for this platform)
  4. m1 univeral means it was built on the M1 hardware using the x86_64 and arm64 architectures so it contains both

In order to build for a specific architecture I have used this CMake variable (defined before project()) (see this forum thread https://discourse.cmake.org/t/looking-for-someone-willing-verify-a-minimal-xcode-project-on-apple-silicon/2415):

    set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "") # for x86_64
    set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "") # for arm64
    set(CMAKE_OSX_ARCHITECTURES "x86_64;amr64" CACHE STRING "") # for universal
  • Columns are for the validator and Rows are for the plugin.

  • For example cell C6 represents running the test on the Intel hardware, test consisting of running the validator which was built on M1 hardware with universal architecture and using the test plugin which was built on the Intel hardware with x86_64 architecture.

  • Row 5 is all N/A because you cannot run the validator with architecture arm64 on an Intel hardware… Technically E3, E4 and E6 falls under the same category: an arm64 plugin cannot run on Intel platform. I marked it as N because it fails gracefully and cannot load it due to not being the correct platform (but at least it doesn’t core dumps…).

I think the results are a bit puzzling:

  • I do not understand why I am getting core dumps. For example Cell C3 which is all the same architecture generates a core dump when the plugin is built on the M1 hardware with x86_64 architecture and ran on Intel hardware. In other words, if you build a plugin on Apple M1, even with x86_64 architecture it does not run on Intel platform.

  • Cell C11 seems to show that the validator (which would be a DAW) if recompiled as a universal binary will not load any of the plugins that have been built with Intel (which at this time is 100% of them…)

From a plugin developer point of view I would like to produce a universal built plugin, but F3 shows that it core dumps when loaded on Intel platform.

From a host developer point of view I would like to produce a universal built host which shows that it works on intel platform (C6) but unfortunately does not load Intel plugins (C11).

The “good” news is that staying x86_64 on the new platform on both sides (which goes through the Rosetta 2 translation layer) works.

Disclaimer: What I am stating here is based on the tests I have ran based on my knowledge of how things work. There may be different compiler options to provide that would trigger a different outcome (core dumps are definitely puzzling). Also I have used the validator as-is from SDK 3.7.1 and I do not know if there are changes in the code that need to be made so that Cell C11 is a Y instead of a N

I wonder if the core dumps are due to the section " Enable Strict Type Enforcement for Dynamic Method Dispatching" https://developer.apple.com/documentation/apple_silicon/addressing_architectural_differences_in_your_macos_code which talks about changes that would need to be made in the SDK itself.

I am not sure how to set this flag from CMake to check: "To locate places where you’re not calling objc_msgSend in a type-safe way, enable the Enable strict Checking of objc_msgSend Calls build setting. When the value of that setting is YES , the compiler flags your code where you’re not using a type-safe function pointer with objc_msgSend".

I figured out what the problem was with my test, so here a revised test matrix:

The core dump was due to the fact that I was compiling on macOS 10.15 and running on 10.14. In order to address the issue, you can actually compile and set an earlier target in your CMakeLists.txt (before project()):

set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14 CACHE STRING "")

Making this change and recompiling shows that you can compile your plugin on the new M1 chipset and target either x86_64 or universal (x86_64;arm64) and it will run under the Intel platform just fine.

This does not change the fact that an “old” (Intel) plugin will only run in an Intel DAW (C8) or a universal DAW which is forced to go through the Rosetta translation layer (right click on the executable and select Open using Rosetta source).

For a plugin developer, moving forward, it makes sense to build a universal plugin because the matrix shows that it will run in all cases (column F). And this is achieved by setting this in your CMakeLists.txt (before project()):

set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14 CACHE STRING "") # whichever macOS version you are targeting...
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "") # for universal