CMake Plugin Demo, won't load on M1 - arm64 Reaper or pluginval? (SOLVED)

I just build the CMake plugin demo on a new m1 Mac. The VST3 will not load, and neither will the other plugin formats. When I scan the vst3 I get an assertion here:

    IPluginFactory* JUCE_CALLTYPE getPluginFactory()
    {
        if (factory == nullptr)
            if (auto* proc = (GetFactoryProc) getFunction (factoryFnName))
                factory = proc();

        // The plugin NEEDS to provide a factory to be able to be called a VST3!
        // Most likely you are trying to load a 32-bit VST3 from a 64-bit host
        // or vice versa.
        jassert (factory != nullptr);
        return factory;
    }

If I try the project generated with the Projucer it works fine. Any ideas? I’m pretty new to CMake…

For what it’s worth, I’m running CMake with:

add_subdirectory(JUCE)

[edit], hmmm looks like user error. I just did a fresh clone of JUCE, went through all the steps, nuked by cmake dir, etc, now it’s working. I was still scanning the good version from the Projucer generated project…

Perhaps the arch of the plugin does not match the arch of the host. You can check the plugin arch with the file command (e.g. file /path/to/plugin.component/Contents/MacOS/thelibrary), and control the arches that CMake builds by setting "-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64" during configuration.

Thanks @reuk That was the issue :see_no_evil: I was setting this in Xcode project settings, but I think it was being overwritten by CMake. I have to remember that I should set all project settings in the Cmake file and not in Xcode :wink:

Sorry, me again! I note that if I set both the host AND the plugin to build as arm64 only, I get the same problem again?

pluginval: Mach-O 64-bit executable arm64
Audio Plugin Example: Mach-O 64-bit bundle arm64

So Reaper, which has an arm64 only build, will not load the plugin even if it has a matching arch?

I’m having one of those days. Seems to work fine :see_no_evil: That’s what I get for working on a Saturday!

Sorry to return to this again, but I just did a fresh clone of the master branch, and built both pluginval and the CMake based plugin example once again. Both are built with the same architecture, yet the plugin won’t load in any arm64 DAW, and I hit the getPluginFactory assertion when I try to load it in pluginval. Here is the file command on the plugin and the host:

/Users/rwalsh/Library/Audio/Plug-Ins/VST3/Audio Plugin Example.vst3/Contents/MacOS/Audio Plugin Example: Mach-O 64-bit bundle arm64
    
/Users/rwalsh/sourcecode/pluginval/Builds/MacOSX/build/Debug/pluginval.app/Contents/MacOS/pluginval: Mach-O 64-bit executable arm64

The plugins built using the Projucer generated projects are fine.

I’ve debugged this a bit. As far as I can tell, the Xcode generator is copying the plugins to the install directory before signing them, which means that the version that gets installed is unsigned. Then, other apps (AudioPluginHost, Pluginval) fail to load the unsigned bundles.

To check on your system, you could try running codesign -dv --verbose=4 /path/to/plugin.vst on the plugins located here:

  • /Library/Audio/Plug-Ins/VST3/Audio Plugin Example.vst3
  • cmake-build/examples/CMake/AudioPlugin/AudioPluginExample_artefacts/Debug/VST3/Audio Plugin Example.vst3

I expect that the copy in the build tree has a signature, while the version in Library does not. You could then try manually copying the version from the build tree into Library and check whether you can load it successfully.

I’d appreciate if you could confirm the above on your machine. Supposing I’ve correctly identified the problem, we should be able to get a fix onto develop shortly.

Thanks @reuk for looking into this. Your suspicions are correct regarding the signing. The one copied over to ~/Library is not signed, while the one in the build folder is. :+1:

However, manually copying the VST did not help. FWIW, this is the output from the codesign on the manually copied plugin:

Executable=/Users/rwalsh/Library/Audio/Plug-Ins/VST3/Audio Plugin Example.vst3/Contents/MacOS/Audio Plugin Example
Identifier=com.yourcompany.AudioPluginExample
Format=bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=223259 flags=0x2(adhoc) hashes=6968+5 location=embedded
VersionPlatform=1
VersionMin=721664
VersionSDK=721664
Hash type=sha256 size=32
CandidateCDHash sha256=acd808c7083173a8f09cbf78d3101e5d9de673b3
CandidateCDHashFull
sha256=acd808c7083173a8f09cbf78d3101e5d9de673b30e7b778f1d2595ef89c03edb
Hash choices=sha256
CMSDigest=acd808c7083173a8f09cbf78d3101e5d9de673b30e7b778f1d2595ef89c03edb
CMSDigestType=2
Executable Segment base=0
Executable Segment limit=7372800
Executable Segment flags=0x0
Page size=4096
CDHash=acd808c7083173a8f09cbf78d3101e5d9de673b3
Signature=adhoc
Info.plist entries=21
TeamIdentifier=not set
Sealed Resources version=2 rules=13 files=0
Internal requirements count=0 size=12
rwalsh@Rorys-Mac-mini build %

I’m happy to test anything else you can think of. Thanks again.

Did you definitely quit and restart the AudioPluginHost or Pluginval after replacing the unsigned plugin with the signed version? JUCE will cache previously loaded VST3s and will reuse the cached version when a new plugin is loaded with a previously-scanned filepath. Restarting the host is necessary to force the new version of the plugin to be loaded.

We’ve tested on two M1 machines here, and signing the plugin allows it to be loaded on both machines.

Thanks @reuk, it could be that I simply tried scanning again without closing pluginval. Either way, I’m happy to say that it works fine now. :+1:

Great, thanks for confirming. We’ll have a fix out for this shortly.

Btw, slightly off-topic, but are all plugins created using either the Projucer or CMake automatically signed? Sorry, I’m coming from 5.4.7…

On M1 machines, Xcode will automatically sign code to run locally. Running clang++ manually will also produce a signed binary. This is a behaviour of the build tools themselves, rather than a change in JUCE.

The bug you were seeing was happening because Xcode was disabling clang’s automatic signing. Normally this would be fine, because Xcode runs its own dedicated signing step. However, CMake-generated projects run POST_BUILD commands (used to install the plugin after build) before Xcode’s signing step, which meant that the plugin was being installed before it was signed. I think we can fix the issue by re-enabling clang’s default signing.

Fix here:

Please let us know if you run into any further problems with this change.

2 Likes