String assertion during linking VST3

I’m getting a very hard to debug assertion during linking from the juce::String constructor.

I’m going to trace back commits to see if I can identify the issue but wonder if anyone can shine some light on this?

FAILED: MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/MacOS/MY Cool Plugin 
: && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -g -arch x86_64 -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -mmacosx-version-min=10.14 -bundle -Wl,-headerpad_max_install_names  -o "MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/MacOS/MY Cool Plugin" CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_ARA.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_Unity.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.mm.o  "MyCoolPlugin_artefacts/Debug/libMY Cool Plugin_SharedCode.a"  libMyCoolPluginData.a  libPresetData.a  -Xlinker -framework -Xlinker CoreAudioKit  -Xlinker -framework -Xlinker DiscRecording  -Xlinker -framework -Xlinker CoreAudio  -Xlinker -framework -Xlinker CoreMIDI  -Xlinker -framework -Xlinker AudioToolbox  -Xlinker -framework -Xlinker Accelerate  -weak_framework Metal  -weak_framework MetalKit  -Xlinker -framework -Xlinker QuartzCore  -Xlinker -framework -Xlinker Cocoa  -Xlinker -framework -Xlinker Foundation  -Xlinker -framework -Xlinker IOKit  -Xlinker -framework -Xlinker Security  -Xlinker -framework -Xlinker WebKit && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E copy /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/JuceLibraryCode/MyCoolPlugin_VST3/PkgInfo "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents" && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E remove -f "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/moduleinfo.json" && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E make_directory "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources" && /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/juce_vst3_helper -create -version 1.0.0 -path "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -output "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources/moduleinfo.json" && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" "-Dsrc=/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -P /Users/adamwilson/dev/cool-plugs/my-cool-plugin/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/extras/Build/CMake/checkBundleSigning.cmake && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" "-Dsrc=/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -Ddest=/Users/adamwilson/Library/Audio/Plug-Ins/VST3 -P /Users/adamwilson/dev/cool-plugs/my-cool-plugin/Cache/juce/a9d2bc271e78dded9a7ebb8b5d26c7383609bd1b/extras/Build/CMake/copyDir.cmake
JUCE v7.0.9
JUCE Assertion failure in juce_String.cpp:315
/bin/sh: line 1: 31261 Segmentation fault: 11  /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/juce_vst3_helper -create -version 1.0.0 -path "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -output "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources/moduleinfo.json"
ninja: build stopped: subcommand failed.

My CI builds pass, this error occurs in CLion building in Debug mode

Here’s what the comment to the assertion says:

String::String (const char* const t)
    : text (StringHolderUtils::createFromCharPointer (CharPointer_ASCII (t)))
{
    /*  If you get an assertion here, then you're trying to create a string from 8-bit data
        that contains values greater than 127. These can NOT be correctly converted to unicode
        because there's no way for the String class to know what encoding was used to
        create them. The source data could be UTF-8, ASCII or one of many local code-pages.

        To get around this problem, you must be more explicit when you pass an ambiguous 8-bit
        string to the String class - so for example if your source data is actually UTF-8,
        you'd call String (CharPointer_UTF8 ("my utf8 string..")), and it would be able to
        correctly convert the multi-byte characters to unicode. It's *highly* recommended that
        you use UTF-8 with escape characters in your source code to represent extended characters,
        because there's no other way to represent these strings in a way that isn't dependent on
        the compiler, source code editor and platform.

        Note that the Projucer has a handy string literal generator utility that will convert
        any unicode string to a valid C++ string literal, creating ascii escape sequences that will
        work in any compiler.
    */
    jassert (t == nullptr || CharPointer_ASCII::isValidString (t, std::numeric_limits<int>::max()));
}

Are your CI builds doing Release builds only? Because that would strip the assertion, removing symptom, but not the cause.

Yes CI is Release only. I’m aware of the assertion itself thanks.

My commit backtrack identified the cause. I’m adding presets as a separate binary data namespace. This did not cause any issues in Standalone and AU builds. However VST3 are crashing on start and debug builds give the linker error above.

diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -189,3 +190,15 @@
+File(GLOB_RECURSE PRESETS "Presets/Factory/*.preset")
+
+juce_add_binary_data(PresetData
+        HEADER_NAME "PresetData.h"
+        NAMESPACE "PresetData"
+
+        SOURCES
+        "Presets/Default.preset"
+        ${PRESETS}
+)
+
 target_link_libraries(MyCoolPlugin
         PRIVATE
         BinaryData
+        PresetData

So either the VST3 build does not like the separate BinaryData namespace, or there is some character somewhere in one of the presets that is throwing the error. What I don’t get this would be specific to VST3.

I’ve checked the preset files for non-UTF8 characters, and pulled the presets into one BinaryData namespace.

Now I get this output:

FAILED: MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/MacOS/MY Cool Plugin 
: && /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -g -arch x86_64 -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk -mmacosx-version-min=10.14 -bundle -Wl,-headerpad_max_install_names  -o "MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/MacOS/MY Cool Plugin" CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_ARA.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_Unity.cpp.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.mm.o CMakeFiles/MyCoolPlugin_VST3.dir/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.mm.o  "MyCoolPlugin_artefacts/Debug/libMY Cool Plugin_SharedCode.a"  libMyCoolPluginData.a  -Xlinker -framework -Xlinker CoreAudioKit  -Xlinker -framework -Xlinker DiscRecording  -Xlinker -framework -Xlinker CoreAudio  -Xlinker -framework -Xlinker CoreMIDI  -Xlinker -framework -Xlinker AudioToolbox  -Xlinker -framework -Xlinker Accelerate  -weak_framework Metal  -weak_framework MetalKit  -Xlinker -framework -Xlinker QuartzCore  -Xlinker -framework -Xlinker Cocoa  -Xlinker -framework -Xlinker Foundation  -Xlinker -framework -Xlinker IOKit  -Xlinker -framework -Xlinker Security  -Xlinker -framework -Xlinker WebKit && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E copy /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/JuceLibraryCode/MyCoolPlugin_VST3/PkgInfo "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents" && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" "-Dsrc=/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -P /Users/adamwilson/dev/cool-plugs/my-cool-plugin/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/extras/Build/CMake/checkBundleSigning.cmake && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E remove -f "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/moduleinfo.json" && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" -E make_directory "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources" && /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/juce_vst3_helper -create -version 1.0.0 -path "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -output "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources/moduleinfo.json" && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" "-Dsrc=/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -P /Users/adamwilson/dev/cool-plugs/my-cool-plugin/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/extras/Build/CMake/checkBundleSigning.cmake && cd /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug && "/Users/adamwilson/Applications/CLion Nova.app/Contents/bin/cmake/mac/aarch64/bin/cmake" "-Dsrc=/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -Ddest=/Users/adamwilson/Library/Audio/Plug-Ins/VST3 -P /Users/adamwilson/dev/cool-plugs/my-cool-plugin/Cache/juce/49ba7bd8674c4ef6c564fef16c52c30bf7ef0505/extras/Build/CMake/copyDir.cmake
/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3: code object is not signed at all
-- Replacing invalid signature with ad-hoc signature
/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3: replacing existing signature
JUCE v7.0.9
JUCE Assertion failure in juce_String.cpp:315
JUCE Assertion failure in juce_String.cpp:315
JUCE Assertion failure in juce_String.cpp:315
JUCE Assertion failure in juce_String.cpp:315
JUCE Assertion failure in juce_String.cpp:315
...

Could this be something to do with replacing with ad-hoc signature?
The last output before the assertion is replacing existing signature

The VST3 plugin is loaded as part of the build process. The sequence is something like:

  • C++ sources → .dll
  • .dll + VST3 helper → moduleinfo.json
  • .dll + moduleinfo.json → .vst3 bundle

It looks like the initial step, converting C++ → .dll is working fine. However, the plugin is crashing when loading it with the VST3 helper to create the moduleinfo.json.

You could try running the Standalone/AU to see whether they crash/assert when loaded. Alternatively, you could disable the step that generates the moduleinfo.json (temporarily) using the VST3_AUTO_MANIFEST CMake option (see docs/CMake API.md) and debug the VST3 plugin without the manifest.

1 Like

To find that call look for juce_vst3_helper in the build log.
You can also copy that command and arguments to run it in the debbuger.
A breakpoint at juce_String.cpp at line 315 could help to inspect the call stack.

According to the jassert, you have to look for any non-ASCII character.

2 Likes

It might also be the absence of a character, i.e the null terminator

1 Like

This was the key to help me debug the issue! Thanks !

@Daniel since the debugger is not attached when loading it to create the moduleinfo.json I was not able to inspect the call stack. Removing the manifest step did the trick.

Yes, but you might want to have the moduleinfo.json in future. It will speed up scanning in modern hosts.

I didn’t mean to add the debugger to the CI, but to copy the call into the debugger. and hit run. It calls your artefact, so it should expose the moment where it goes wrong.

in your case:

lldb /Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/juce_vst3_helper
r -create -version 1.0.0 -path "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3" -output "/Users/adamwilson/dev/cool-plugs/my-cool-plugin/cmake-build-debug/MyCoolPlugin_artefacts/Debug/VST3/MY Cool Plugin.vst3/Contents/Resources/moduleinfo.json"
bt

If the actual plugin runs well, this is an indicator of something asynchronous, that doesn’t like to be killed immediately. But that is guesswork.

1 Like

@Daniel oh I immediately put the manifest creation step back as soon as I found the problem area. It actually works like an automated test without needing to launch the VST3 in this case :slight_smile:

All fixed now. There was some unsafe iterating of the BinaryData resourcesNames array causing the issue, pulling out garbage non-UTF8 characters.