VST3 build with JUCE 7.0.6 on MacOS is Broken

Hello, I just installed JUCE 7.0.6. I did not have the problem below with 7.0.5.

On MacOS, there is a new build phase, I think only for VST3 builds, named Update manifest, that was not there before, and it is in this new phase that my build is failing. The Xcode build window includes the lines below.

Run custom shell script 'Update manifest'
/Users/david/emvoice/dev/working/VOICE/sohoplugin/Builds/MacOSX/build/Debug/emvoiceone.vst3: code object is not signed at all
In architecture: arm64
The bundle “emvoiceone” couldn’t be loaded.
Command PhaseScriptExecution failed with a nonzero exit code

I don’t quite understand why the plugin should be loaded and executed at this point in the build. I think that the failure to load the VST3 plugin is what leads to the PhaseScriptExecution failure, but really I am not certain about this.

The failure occurs before the post build script runs.

Thanks for your help

2 Likes

It took me a couple of days to understand this issue.

We link our plugin with multiple external libraries. On MacOS this means that our plugin links with multiple *.dylib libraries. Our plugin can not run unless all of these dylib files are available.

In our case, whether for the AU build, the (legacy) VST2 build, the AAX build or the VST3 build, the dylib files are copied into the plugin bundle, always into the folder Contents/Frameworks, and the plugin ships with these dylibs. Otherwise, we can not be certain that these dylibs will be on the user’s machine. So for example, our post-build script has the following lines (surrounded by, of course, a lot of other logic)

. . .
BUNDLE_VST3=~/Library/Audio/Plug-Ins/VST3/emvoiceone.vst3
. . .
cp $DIR/temp/osx/lib/*.dylib $BUNDLE_VST3/Contents/Frameworks
. . .

As far as I know, it is pretty standard stuff on MacOS to copy the dylib files into the bundle. We have made this work for about 5 years since JUCE 4.

So the problem we are having is that this copying happens during the post-build script (It can not be done during the pre-build script, since the bundle might not exist at that time.). But in JUCE 7.0.6, there is a new phase Update manifest that runs a script before the post-build script, and this Update manifest script attempts to run the VST3 build of our plugin before the dylibs are copied into position. So of course the VST3 plugin fails to load.

It seems to us that loading and running a plugin before the post-build script completes is a flaw in the JUCE 7.0.6 plugin build process.

Is there a work around for this? We don’t need the VST3 to be loaded during the build and before the post-build script runs. We really want to be able to use the latest version of JUCE, but can not now because of this problem.

3 Likes

The juce team now

ezgif-5-baffc26cab

1 Like

I wish I looked that cool. I’m actually scratching my head in front of my computer thinking about how to solve this.

8 Likes

The loading is required for a somewhat new VST3 feature, the manifest, that contains all the information that a DAW would want to find out when scanning a plugin first. This way, instead of scanning the plugin, it can just read a .json file, which is many times faster. In order to generate this .json file, we are scanning the plugin right after building it to populate the contents of the manifest.

I can see how this is causing a problem for you, and we should find a way to accomodate your build process.

I considered the options here and I have a suggestion that may work for you.

First of all I think the manifest generation is a very useful feature, that you may want to support if it only requires a one-time build modification. If all plugins supported it (and the idea is that eventually they all will), on a system with lots of plugins it can mean the difference between a DAW startup time of one minute vs. a couple of seconds.

Can you see please, if you could move the .dylib copy step into the Pre-Build script after all? There’s a good chance you could make something like the following work.

mkdir -p ${CONFIGURATION_BUILD_DIR}/emvoiceone.vst3/Contents/Frameworks
cp $DIR/temp/osx/lib/*.dylib ${CONFIGURATION_BUILD_DIR}/emvoiceone.vst3/Contents/Frameworks

This appears to be the best thing to try first, because the only alternatives I can see are

  • we provide a way to optionally disable manifest generation, but I think it’s a worthwhile feature, that may eventually become expected, or
  • add another “Mid-Build Shell Script” field that executes before the manifest generation.

But even in the second case you’d still have to modify your script before you’d specify it there, so we wouldn’t really gain anything with it.

3 Likes

Hi Attila,

Thank you very much. I moved the dylib copy step from the beginning of the post-build script to the end of the pre-build script. It works perfectly. Very good idea.

And thanks for the explanation of why JUCE added the update manifest step in the first place. It makes sense to have this info calculated once and saved in a JSON object that goes as part of the VST3 bundle instead of the DAW calculating it each time the VST3 is loaded.

Now I understand why in Windows builds of the VST3 in JUCE 7.0.6, a bundle is created (instead of just a single DLL): so that there is a place for the manifest.

One question: do you have any sense of if or when (in Windows) VST3s in the form of a single DLL will be forbidden, and the full bundle containing the DLL and the manifest will be required? Is this going to happen?

Thanks again. You have been a big help.

1 Like

If you mean when will DAWs refuse to load single DLL plugins, my guess is never. They wouldn’t want to lose backward compatibility with old plugins.

VST3 builds with JUCE 7.0.6 from Pipelines are Broken

MSBuild error:

PostBuildEvent:
  copy /Y “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.dll” “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.vst3\Contents\x86_64-win\My Plugin Name.vst3"
  del /s /q “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\moduleinfo.json”
  if not exist “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources” mkdir “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Pugin Name.vst3\Contents\Resources”
  “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3 Manifest Helper\juce_vst3_helper.exe” -create -version “3.8.0” -path “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3" -output “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources\moduleinfo.json”
  :VCEnd
          1 file(s) copied.
  Could Not Find D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\My Pugin Name.vst3\Contents\moduleinfo.json
##[error]C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): Error MSB3073: The command “copy /Y “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.dll” “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.vst3\Contents\x86_64-win\My Plugin Name.vst3"
del /s /q “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\moduleinfo.json”
if not exist “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources” mkdir “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources”
“D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3 Manifest Helper\juce_vst3_helper.exe” -create -version “3.8.0” -path “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3" -output “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources\moduleinfo.json”
:VCEnd” exited with code -1073740791.
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): error MSB3073: The command “copy /Y “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.dll” “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\\My Plugin Name.vst3\Contents\x86_64-win\My Plugin Name.vst3" [D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): error MSB3073: del /s /q “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\moduleinfo.json” [D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): error MSB3073: if not exist “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources” mkdir “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources” [D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): error MSB3073: “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3 Manifest Helper\juce_vst3_helper.exe” -create -version “3.8.0” -path “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3" -output “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\x64\Release\VST3\/My Plugin Name.vst3\Contents\Resources\moduleinfo.json” [D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj]
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(160,5): error MSB3073: :VCEnd” exited with code -1073740791. [D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj]
Done Building Project “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj” (default targets) -- FAILED.
Done Building Project “D:\a\1\s\Projects\My Project Name\Builds\VisualStudio2022\My Plugin Name_VST3.vcxproj.metaproj” (default targets) -- FAILED.

Xcode 14.2 error:

xcodebuild -configuration Release -project /Users/runner/work/1/s/Projects/My Project Name/Builds/MacOSX/My Plugin Name.xcodeproj build CODE_SIGNING_ALLOWED=NO | /usr/local/lib/ruby/gems/3.0.0/bin/xcpretty -r junit --no-color


Xcode build:
▸ Compiling include_juce_audio_plugin_client_VST3.mm
▸ Compiling include_juce_audio_plugin_client_VST3.mm
▸ Linking My\
▸ Linking My\
▸ Running script ‘Update manifest’
** BUILD FAILED **
The following build commands failed:
  PhaseScriptExecution Update\ manifest /Users/runner/work/1/s/Projects/My\ Project\ Name/Builds/MacOSX/build/My\ Plugin\ Name.build/Release/My\ Plugin\ Name\ -\ VST3.build/Script-1087FC8968FCA95716F6DC05.sh (in target ‘My Plugin Name - VST3’ from project ‘My Plugin Name’)

I’m able to compile locally, directly from Xcode and VisualStudio. I’ll have to configure the same setup of pipelines locally in order to find the problem

This whole moduleinfo.json feature seems too fragile at the moment to be imposed to everyone that switches to 7.0.6.
In my opinion it would be better to call it experimental, and to give developers a way to opt-out if it’s not working for them at present time.

3 Likes

I also think it should be optional at this stage so that we can adopt facilities like this at our own pace.

3 Likes

Hope the JUCE developers did research to know how commonly the bundle version is supported. I really have no idea myself so just waiting to see if complaints start to roll in.

So I am also facing the same error message (“DecentSampler.vst3: code object is not signed at all”), also in the Update Manifest step, but I don’t do any .dylib copying in a post-build step. In fact, I think I have a pretty vanilla build.

That message is actually a diagnostic message, after which the plugin is ad-hoc signed so that it can be loaded for manifest generation.

So even if you see that message, the build should complete unless there are other problems. Does the build successfully complete in your case?

Sadly, no. Xcode writes:

Command PhaseScriptExecution failed with a nonzero exit code

and refuses to continue with the Archive. The full error message is:

/Users/myuser/Documents/DecentSampler/Builds/MacOSX/build/Release/DecentSampler.vst3: code object is not signed at all

In architecture: arm64

The bundle “DecentSampler” couldn’t be loaded.Command PhaseScriptExecution failed with a nonzero exit code

Please can you run the following commands in a terminal and paste the output?

xcrun codesign --verify /path/to/plugin.vst3
echo $?
xcrun codesign -f -s - /path/to/plugin.vst3
echo $?

It sounds like the failure is probably happening when running the manifest-generator tool, but if the above commands complete successfully then we’ll know for sure.

Some other details that would be useful to know:

  • Do you have any non-default options set in the Projucer, e.g. hardened runtime, app sandbox, legacy build system
  • Does the path to the build directory contain any non-ascii characters such as diacritics?

Hi! I ran the commands:

dhilowitz@DH-MBP-M1 SDKs % xcrun codesign --verify /Users/dhilowitz/Library/Developer/Xcode/DerivedData/DecentSampler-gzjglykdpaankleydsturgincswf/Build/Intermediates.noindex/ArchiveIntermediates/DecentSampler\ -\ VST3/InstallationBuildProductsLocation/Users/dhilowitz/Library/Audio/Plug-Ins/VST3/DecentSampler.vst3
/Users/dhilowitz/Library/Developer/Xcode/DerivedData/DecentSampler-gzjglykdpaankleydsturgincswf/Build/Intermediates.noindex/ArchiveIntermediates/DecentSampler - VST3/InstallationBuildProductsLocation/Users/dhilowitz/Library/Audio/Plug-Ins/VST3/DecentSampler.vst3: a sealed resource is missing or invalid
dhilowitz@DH-MBP-M1 SDKs % echo $?
1
dhilowitz@DH-MBP-M1 SDKs % xcrun codesign -f -s - /Users/dhilowitz/Library/Developer/Xcode/DerivedData/DecentSampler-gzjglykdpaankleydsturgincswf/Build/Intermediates.noindex/ArchiveIntermediates/DecentSampler\ -\ VST3/InstallationBuildProductsLocation/Users/dhilowitz/Library/Audio/Plug-Ins/VST3/DecentSampler.vst3
/Users/dhilowitz/Library/Developer/Xcode/DerivedData/DecentSampler-gzjglykdpaankleydsturgincswf/Build/Intermediates.noindex/ArchiveIntermediates/DecentSampler - VST3/InstallationBuildProductsLocation/Users/dhilowitz/Library/Audio/Plug-Ins/VST3/DecentSampler.vst3: replacing existing signature
dhilowitz@DH-MBP-M1 SDKs % echo $?
0

Yes, I am using Hardened Runtime. My understanding is this is required in order to be able to notarize my plug-in, no?

– Dave

I just tried turning off Hardened Runtime and it didn’t change anything.

Light at the end of the tunnel! I have a bunch of Custom Xcode flags that I added for a bunch of different reasons, none of which I can remember anymore. I would need to search through the JUCE forums to figure out which thread the various flags were lifted from.

In any case, when I remove all of these flags, Xcode Archives my plugin just fine. I’m now working my way through to try to figure out which of these flags is causing the problem. Here are my Custom Xcode Flags:

CODE_SIGN_INJECT_BASE_ENTITLEMENTS=No,CODE_SIGN_STYLE=Automatic,OTHER_CODE_SIGN_FLAGS=--timestamp --options runtime,GCC_GENERATE_DEBUGGING_SYMBOLS = YES, 
GCC_DEBUGGING_SYMBOLS = full, 
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym,
COPY_PHASE_STRIP = NO,
DWARF_DSYM_FOLDER_PATH = "$(CONFIGURATION_BUILD_DIR)"

My guess is that the problem originates here - I think these flags will apply to all targets (not just the plugin), so the manifest generator will be built with the hardened runtime. This fails because apps using the hardened runtime can’t load adhoc-signed bundles, and the bundle isn’t release-signed until after the manifest is generated.

I recommend instead just setting OTHER_CODE_SIGN_FLAGS=--timestamp, and setting “Use Hardened Runtime” to “Enabled” in the Xcode (macOS) exporter in the Projucer. The Projucer knows that when the option is set here, it should only apply to the final plugin binary, rather than to every target in the project.