JUCE VST3 fails to load after signing and notarization

Hi everyone,

I made a distribution script for my JUCE VST3 plugin by following this awesome guide. In my script I codesign the vst3, bundle it into a pkg and I notarize and staple it, just like in the guide. I check the VST3 with codesign -dv and everything looks fine. A few months ago this same script created a pkg successfully that I was able to use for installing the VST3 in any computer.

A couple of days ago I wanted to release a new build of my plugin for testing in my 2nd computer. It created the pkg apparently susccesfully, throwing no error logs. But after I installed the plugin in a new computer, it wouldn’t load in Ableton or Pluginval. These are the logs I get in Pluginval from the 2nd computer:

Starting tests in: pluginval / Open plugin (cold)… The bundle couldn’t be loaded. JUCE Assertion failure in juce_VST3PluginFormatImpl.h:1104 !!! Test 1 failed: Expected value: , Actual value: Unable to load VST-3 plug-in file JUCE Assertion failure in juce_UnitTest.cpp:314 !!! Test 2 failed: Unable to create juce::AudioPluginInstance JUCE Assertion failure in juce_UnitTest.cpp:314 FAILED!! 2 tests failed, out of a total of 2 ----------------------------------------------------------------- Starting tests in: pluginval / Open plugin (warm)… The bundle couldn’t be loaded. JUCE Assertion failure in juce_VST3PluginFormatImpl.h:1104 !!! Test 1 failed: Expected value: , Actual value: Unable to load VST-3 plug-in file JUCE Assertion failure in juce_UnitTest.cpp:314 !!! Test 2 failed: Unable to create juce::AudioPluginInstance JUCE Assertion failure in juce_UnitTest.cpp:314 FAILED!! 2 tests failed, out of a total of 2 FAILURE *** FAILED

I checked juce_VST3PluginFormatImpl.h:1104 and it look like jassert (factory != nullptr) is triggered because it can’t find the VST3 GetPluginFactory function. This seems like a big clue, but I don’t know how to debug this error, any ideas?

I went back in my repo to the tag of the version that I was able to distribute successfully months ago, and I’m still getting the same error logs from Pluginval. I’m building exactly the same code with no changes, so I suspect there’s something wrong in the distribution process that now is going wrong. But I don’t know what to check.

These are the commands generated by my distribution script:

codesign --force -s “Developer ID Application: My Name (XXXXXXXXXX)” -v build/juce_plugin/MyPlugin_artefacts/Release/VST3/MY-PLUGIN_0.7.0.vst3 --deep --strict --options=runtime --timestamp

codesign -dv build/juce_plugin/myplugin_artefacts/Release/VST3/MY-PLUGIN_0.7.0.vst3

pkgbuild --identifier com.myplugin.myplugin.vst3 --version 0.7.0 --component build/juce_plugin/myplugin_artefacts/Release/VST3/MY-PLUGIN_0.7.0.vst3 --install-location /Library/Audio/Plug-Ins/VST3 myplugin.vst3.pkg

productbuild --resources ./resources --distribution distribution.xml --sign “Developer ID Installer: My Name (XXXXXXXXX)” --timestamp myplugin_0.7.0.pkg

pkgutil --check-signature myplugin_0.7.0.pkg

xcrun notarytool submit myplugin_0.7.0.pkg --apple-id myemail@domain.es --password xxxx-xxxx-xxxx-xxxx --team-id XXXXXXXXX --wait

Can you spot anything wrong in it?

Thank you for all the priceless information you share in this forum. I’ve been reading it a lot lately, now that I’m working on a JUCE plugin project. It has been a huge help!

As far as I know, if there is a problem regarding the signing/notarization and you install plugins via .pkg, the problem should only pop-up when you open the .pkg. Therefore, it is likely that the problem is not related to signing/notarization in your case.

At juce_VST3PluginFormatImpl.h:1104 it says, which does not seem to apply here?

// 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;

Have you used pluginval on your local machine (if you use .pkg on your own machine)? Have you tried AU version?

Thanks for your quick answer.

I don’t think the coment applies to my case. The plugin is compiled as a bundle for x86_64 and arm64. My computers are an Intel Mac and an Apple Silicon Mac. I tried both ways, building in the Intel and running in the Silicon, and the other way around. I get the same error doing both. I can see it is actually built for both when running codesign -dv.

I didn’t try building AU, only VST3 and Standalone. I’ll check

Sorry I didn’t answer your 2nd question: yes I’m using pluginval in the local computer, I run and build it with ASAN and TSAN and a strictness level of 10. It completes susccessfully

Still investigating this, and I got some new findings.

I’m now trying this by using the JUCE plugin example in JUCE/examples/CMake, and I get the same error when I run the installed plugin through Pluginval in my 2nd computer. Only modification I added is this line for building for both architectures:

set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")

When I run the AU plugin through Pluginval I get a similar issue:

!!! Test 1 failed: No types found. This usually means the plugin binary is missing or damaged, an incompatible format or that it is an AU that isn’t found by macOS so can’t be created.
JUCE Assertion failure in juce_UnitTest.cpp:314

After this, I tried building a new plugin project from the Projucer, compiling Release in Xcode and signing using my script… And finally the resulting plugin loads successfully in my 2nd computer!!!

But I would like to be able to do this from a CMake based project, because this is what I use in my projects… Any ideas what could be going wrong?

I FOUND IT!!!

It had nothing to do with signing or notarization.

The main issue was that my Mac OS target version was wrong. My build computer has Mac OS 15.X, and my test computer has Mac OS 13.X. Apparently if you don’t set CMAKE_OSX_DEPLOYMENT_TARGET in your CMake configuration, CMake sets the current OS version as the target. So I added this line to my CMakeLists.txt and it resolved the issue:

set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")

That fixed it for the example project. But in my project there was also another bug that was preventing the plugin from showing up in my 2nd computer: I recently added FFTW3 to my project and I was linking it dynamically… So the resulting VST3 was missing it. I’ve set it to link statically and this fixes the issue.

Took me 4 days to realise these things…

2 Likes

Gald you solve this! Previously I have also linked a library ( GitHub - stevengj/nlopt: library for nonlinear optimization, wrapping many algorithms for global and local, constrained or unconstrained, optimization · GitHub ) dynamically once … all binaries broke and took me quite a while to solve it :frowning:

By the way, if you have not paid FFTW3 already, KFR GitHub - kfrlib/kfr: Fast, modern C++ DSP framework, FFT, Sample Rate Conversion, FIR/IIR/Biquad Filters (SSE, AVX, AVX-512, ARM NEON, RISC-V RVV) · GitHub might be a better choice, or even Apple vDSP and Intel IPP. I have done some reserach recently (in case you are interested, Share some FFT benchmark results ) and it seems that FFTW3 performs kind of bad on M chips :slight_smile:

I have not paid FFTW3, but this is not a commercial product. I’ll explore the options you mention in future projects, thanks!