Cross-compiling to Intel-only on M3 Mac?

In the past I used my Intel-only Mac to build two plugin versions: an Intel-only version with AVX optimzations and an universal binary with SSE (emulation) that supports both intel and native arm64. That worked well on my old Intel Mac Pro.

Now I am a proud user of a new M3 Pro Mac (silicon). I managed without issues to build the universal binary. But building (cross-compiling) the Intel-only AVX version fails.
Reason: the juce_vst3_helper is compiled for Intel and cannot be executed on the silicon Mac. So i get “illegal hardware instruction” during the build (both Projucer and CMake). And running the custom shell script “Update manifest” fails.

Any ideas? My assumption would be that in this scenario the juce_vst3_helper should be build as universal binary for silicon instead of Intel-only.

Any ideas? I am really stuck here. I have not found a way to build the Intel-version of the VST3 on the M3 Mac. My other targets (standalone, VST, …) are not a problem. Any help appreciated.

Do you have Rosetta installed? Will that allow the juce_vst3_helper to run?

1 Like

Any chance an unsupported AVX instruction is somewhere in juce_vst3_helper?

Does your CMake configuration accidentally set compiler flags for AVX support for juce_vst3_helper (e.g. because you set these globally)? If you’re using Ninja, you can easily look in the generated ninja files.

1 Like

Thank you. This is probably the case. You are right. I have in CmakeLists.txt

  if(BUILD_AVX)  
    set_xcode_property(${PROJECT_NAME} CLANG_X86_VECTOR_INSTRUCTIONS "avx")
  endif(BUILD_AVX)

This is set globally. Now I have to figure out how I can set it for all targets except the juce_vst3_helper. And I have no clue :frowning:

I tried with Ninja and also with Xcode/Projucer. In all cases in the ende it fails to execute the
juce_vst3_helper.

Build target ... - VST3 Run custom shell script 'Update manifest' Command PhaseScriptExecution failed with a nonzero exit code The bundle “...” couldn’t be loaded because it doesn’t contain a version for the current architecture.

I came to the conclusion that this scenario is not possible. JUCE does not support to build (cross-compile) LV2 or VST3 bundles for architectures that cannot be executed on the build system itself.
In my case:

  • building an x86_64 VST3 with AVX on an arm64 M3 is not possible since the juce_vst3_helper needs to execute the bundle binary - which fails due to being for Intel AVX only. Rosetta does not seem to help.
  • building an x86_64;arm64 universal binary on an Intel Mac is possible since the juce_vst3_helper will be build as universal binary, which has the x86_64 that can be run on the machine.

So it seems I will have to use my old Intel Mac forever.

Can somebody confirm that?

you can maybe set explicitely
set_source_files_properties(PathToSourceFileforVST3Helper
PROPERTIES
COMPILE_FLAGS
“-mno-avx”)

I think you’re probably right as the helper needs to load your plugin to generate the manifest files.

What if you were to

  • build the universal binary with SSE first
  • disable the update manifest step for the Intel-only AVX version
  • copy the manifest files from the universal binary into the Intel-only AVX version

In the case of VST3 I think you can disable the step by setting VST3_AUTO_MANIFEST to FALSE. I’m not sure we currently have a way to do that for LV2 but you could at least test the basic idea with VST3?

1 Like

I should also add we have an internal MR I’ve been working on that aims to make failure to generate manifest files a warning as opposed to an error which might make this a lot easier for you.

2 Likes

Oha. Yes. That might be a workaround. I will try and report back. Thanks.

1 Like

Thank you. Yes, I tried that.

target_compile_options(juce_vst3_helper PUBLIC -mno-avx)

I also tried to build the juce_vst3_helper as universal binary first and exchanged the executables in a post build command step in CMake.

Which works but does not help finally. It solves the illegal hardware instruction with juce_vst3_helper. But it does not solve the fact that the juce_vst3_helper needs to load the plugin itself to generate the manifest, which is not possible on the architecture.

As a quick check this seems to work for VST3. But now the LV2 manifest step fails. So I would need an LV2_AUTO_MANIFEST FALSE option :open_mouth:

1 Like

maybe just vst3 helper should always be built universal and then depending on the platform and the format of the target call
arch -arm64 vst3helper
arch -x86_64 vst3helper

I would leave it to Anthony to comment. My understanding is limited here, but from what I got so far:
To generate the manifest, the juce_vst3_helper and the juce_lv2_helper actually need to load (run, execute) the plugin binary during the build, make process.

With this process it seems to be impossible to build a manifest on a system that cannot run the plugin itself.

I think in this case, if I understand correctly, the plugin can’t be loaded not because of x86_64 instructions but because Rosetta doesn’t support AVX instructions.

Rosetta translates all x86_64 instructions, but it doesn’t support the execution of some newer instruction sets and processor features, such as AVX, AVX2, and AVX512 vector instructions.

Therefore I don’t think there is anyway to load a plugin containing AVX instructions on an Apple Silicon device. The best we can do is build the plugin for another architecture and load that instead.

1 Like