mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Projucer: Generate moduleinfo.json file during VST3 build
This commit is contained in:
parent
0032e1ec86
commit
b8f116c5c5
10 changed files with 310 additions and 95 deletions
|
|
@ -78,7 +78,8 @@ namespace build_tools
|
|||
case Type::StaticLibrary:
|
||||
case Type::DynamicLibrary:
|
||||
case Type::LV2PlugIn:
|
||||
case Type::LV2TurtleProgram:
|
||||
case Type::LV2Helper:
|
||||
case Type::VST3Helper:
|
||||
case Type::SharedCodeTarget:
|
||||
case Type::AggregateTarget:
|
||||
case Type::unspecified:
|
||||
|
|
@ -109,7 +110,8 @@ namespace build_tools
|
|||
case Type::StaticLibrary:
|
||||
case Type::DynamicLibrary:
|
||||
case Type::LV2PlugIn:
|
||||
case Type::LV2TurtleProgram:
|
||||
case Type::LV2Helper:
|
||||
case Type::VST3Helper:
|
||||
case Type::SharedCodeTarget:
|
||||
case Type::AggregateTarget:
|
||||
case Type::unspecified:
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ namespace build_tools
|
|||
SharedCodeTarget = 20, // internal
|
||||
AggregateTarget = 21,
|
||||
|
||||
LV2TurtleProgram = 25, // internal
|
||||
LV2Helper = 25, // internal
|
||||
VST3Helper = 26, // internal
|
||||
|
||||
unspecified = 30
|
||||
};
|
||||
|
|
@ -118,7 +119,8 @@ namespace build_tools
|
|||
case LV2PlugIn: return "LV2 Plugin";
|
||||
case SharedCodeTarget: return "Shared Code";
|
||||
case AggregateTarget: return "All";
|
||||
case LV2TurtleProgram: return "LV2 Manifest Helper";
|
||||
case LV2Helper: return "LV2 Manifest Helper";
|
||||
case VST3Helper: return "VST3 Manifest Helper";
|
||||
case unspecified: break;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +143,8 @@ namespace build_tools
|
|||
if (name == "LV2 Plugin") return Type::LV2PlugIn;
|
||||
if (name == "Shared Code") return Type::SharedCodeTarget;
|
||||
if (name == "All") return Type::AggregateTarget;
|
||||
if (name == "LV2 Manifest Helper") return Type::LV2TurtleProgram;
|
||||
if (name == "LV2 Manifest Helper") return Type::LV2Helper;
|
||||
if (name == "VST3 Manifest Helper") return Type::VST3Helper;
|
||||
|
||||
jassertfalse;
|
||||
return Type::ConsoleApp;
|
||||
|
|
@ -164,7 +167,8 @@ namespace build_tools
|
|||
case UnityPlugIn: return pluginBundle;
|
||||
case LV2PlugIn: return pluginBundle;
|
||||
case SharedCodeTarget: return staticLibrary;
|
||||
case LV2TurtleProgram: return executable;
|
||||
case LV2Helper: return executable;
|
||||
case VST3Helper: return executable;
|
||||
case AggregateTarget:
|
||||
case unspecified:
|
||||
break;
|
||||
|
|
@ -249,7 +253,8 @@ namespace build_tools
|
|||
case Target::StandalonePlugIn:
|
||||
case Target::UnityPlugIn:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
case Target::VST3Helper:
|
||||
case Target::SharedCodeTarget:
|
||||
case Target::AggregateTarget:
|
||||
return true;
|
||||
|
|
@ -295,7 +300,8 @@ namespace build_tools
|
|||
case Target::DynamicLibrary:
|
||||
case Target::unspecified:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
case Target::VST3Helper:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -369,6 +369,8 @@ void Project::initialiseAudioPluginValues()
|
|||
pluginVSTNumMidiOutputsValue.referTo (projectRoot, Ids::pluginVSTNumMidiOutputs, getUndoManager(), 16);
|
||||
|
||||
pluginLV2URIValue.referTo (projectRoot, Ids::lv2Uri, getUndoManager(), getDefaultLV2URI());
|
||||
|
||||
vst3ManifestEnabledValue.referTo (projectRoot, Ids::vst3ManifestEnabled, getUndoManager(), false);
|
||||
}
|
||||
|
||||
void Project::updateOldStyleConfigList()
|
||||
|
|
@ -1262,6 +1264,8 @@ bool Project::shouldBuildTargetType (build_tools::ProjectType::Target::Type targ
|
|||
return shouldBuildVST();
|
||||
case Target::VST3PlugIn:
|
||||
return shouldBuildVST3();
|
||||
case Target::VST3Helper:
|
||||
return shouldBuildVST3() && isVst3ManifestEnabled();
|
||||
case Target::AAXPlugIn:
|
||||
return shouldBuildAAX();
|
||||
case Target::AudioUnitPlugIn:
|
||||
|
|
@ -1273,7 +1277,7 @@ bool Project::shouldBuildTargetType (build_tools::ProjectType::Target::Type targ
|
|||
case Target::UnityPlugIn:
|
||||
return shouldBuildUnityPlugin();
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
return shouldBuildLV2();
|
||||
case Target::AggregateTarget:
|
||||
case Target::SharedCodeTarget:
|
||||
|
|
@ -1537,6 +1541,14 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props)
|
|||
"If neither of these are selected, the appropriate one will be automatically added based on the \"Plugin is a synth\" option.");
|
||||
}
|
||||
|
||||
props.add (new ChoicePropertyComponent (vst3ManifestEnabledValue, "Plugin VST3 moduleinfo.json Enabled"),
|
||||
"Check this box if you want a moduleinfo.json file to be generated as part of the VST3 build. "
|
||||
"This may improve startup/scanning time for hosts that understand the contents of this file. "
|
||||
"This setting is disabled by default because the moduleinfo.json path can cause problems during code signing on macOS. "
|
||||
"Bundles containing a moduleinfo.json may be rejected by code signing verification at any point in the future without notice per https://developer.apple.com/library/archive/technotes/tn2206."
|
||||
"If you enable this setting, be aware that the code signature for the moduleinfo.json will be stored in its extended file attributes. "
|
||||
"Therefore, you will need to ensure that these attributes are not changed or removed when distributing the VST3.");
|
||||
|
||||
props.add (new MultiChoicePropertyComponent (pluginAAXCategoryValue, "Plugin AAX Category", getAllAAXCategoryStrings(), getAllAAXCategoryVars()),
|
||||
"AAX category.");
|
||||
|
||||
|
|
@ -1570,7 +1582,6 @@ void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props)
|
|||
|
||||
props.add (new TextPropertyComponent (pluginARACompatibleArchiveIDsValue, "Plugin ARA Compatible Document Archive IDs", 1024, true),
|
||||
"List of compatible ARA Document Archive IDs - one per line");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ public:
|
|||
static String getJuceSourceHFilename() { return "JuceHeader.h"; }
|
||||
static String getJuceLV2DefinesFilename() { return "JuceLV2Defines.h"; }
|
||||
static String getLV2FileWriterName() { return "juce_lv2_helper"; }
|
||||
static String getVST3FileWriterName() { return "juce_vst3_helper"; }
|
||||
|
||||
//==============================================================================
|
||||
template <class FileType>
|
||||
|
|
@ -291,6 +292,8 @@ public:
|
|||
bool isPluginAAXBypassDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableBypass); }
|
||||
bool isPluginAAXMultiMonoDisabled() const { return checkMultiChoiceVar (pluginCharacteristicsValue, Ids::pluginAAXDisableMultiMono); }
|
||||
|
||||
bool isVst3ManifestEnabled() const { return vst3ManifestEnabledValue.get(); }
|
||||
|
||||
void disableStandaloneForARAPlugIn();
|
||||
|
||||
static StringArray getAllAUMainTypeStrings() noexcept;
|
||||
|
|
@ -583,7 +586,7 @@ private:
|
|||
pluginCodeValue, pluginChannelConfigsValue, pluginCharacteristicsValue, pluginAUExportPrefixValue, pluginAAXIdentifierValue,
|
||||
pluginAUMainTypeValue, pluginAUSandboxSafeValue, pluginVSTCategoryValue, pluginVST3CategoryValue, pluginAAXCategoryValue,
|
||||
pluginEnableARA, pluginARAAnalyzableContentValue, pluginARAFactoryIDValue, pluginARAArchiveIDValue, pluginARACompatibleArchiveIDsValue, pluginARATransformFlagsValue,
|
||||
pluginVSTNumMidiInputsValue, pluginVSTNumMidiOutputsValue, pluginLV2URIValue;
|
||||
pluginVSTNumMidiInputsValue, pluginVSTNumMidiOutputsValue, pluginLV2URIValue, vst3ManifestEnabledValue;
|
||||
|
||||
//==============================================================================
|
||||
std::unique_ptr<EnabledModulesList> enabledModulesList;
|
||||
|
|
|
|||
|
|
@ -122,8 +122,9 @@ public:
|
|||
case Target::AAXPlugIn:
|
||||
case Target::UnityPlugIn:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
case Target::VST3PlugIn:
|
||||
case Target::VST3Helper:
|
||||
case Target::AudioUnitPlugIn:
|
||||
case Target::AudioUnitv3PlugIn:
|
||||
case Target::unspecified:
|
||||
|
|
|
|||
|
|
@ -228,9 +228,12 @@ public:
|
|||
{
|
||||
using Target = build_tools::ProjectType::Target::Type;
|
||||
|
||||
if (type == Target::LV2TurtleProgram)
|
||||
if (type == Target::LV2Helper)
|
||||
return Project::getLV2FileWriterName() + suffix;
|
||||
|
||||
if (type == Target::VST3Helper)
|
||||
return Project::getVST3FileWriterName() + suffix;
|
||||
|
||||
const auto forceUnityPrefix = type == Target::UnityPlugIn;
|
||||
auto target = File::createLegalFileName (getTargetBinaryNameString (forceUnityPrefix).trim());
|
||||
|
||||
|
|
@ -655,12 +658,12 @@ public:
|
|||
}
|
||||
|
||||
auto externalLibraries = getExternalLibraries (config, getOwner().getExternalLibrariesStringArray());
|
||||
auto additionalDependencies = type != SharedCodeTarget && type != LV2TurtleProgram && ! externalLibraries.isEmpty()
|
||||
auto additionalDependencies = type != SharedCodeTarget && type != LV2Helper && type != VST3Helper && ! externalLibraries.isEmpty()
|
||||
? externalLibraries.joinIntoString (";") + ";%(AdditionalDependencies)"
|
||||
: String();
|
||||
|
||||
auto librarySearchPaths = config.getLibrarySearchPaths();
|
||||
auto additionalLibraryDirs = type != SharedCodeTarget && type != LV2TurtleProgram && librarySearchPaths.size() > 0
|
||||
auto additionalLibraryDirs = type != SharedCodeTarget && type != LV2Helper && type != VST3Helper && librarySearchPaths.size() > 0
|
||||
? getOwner().replacePreprocessorTokens (config, librarySearchPaths.joinIntoString (";")) + ";%(AdditionalLibraryDirectories)"
|
||||
: String();
|
||||
|
||||
|
|
@ -672,7 +675,7 @@ public:
|
|||
: "%(IgnoreSpecificDefaultLibraries)");
|
||||
link->createNewChildElement ("GenerateDebugInformation")->addTextElement ((isDebug || config.shouldGenerateDebugSymbols()) ? "true" : "false");
|
||||
link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename);
|
||||
link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows");
|
||||
link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2Helper || type == VST3Helper ? "Console" : "Windows");
|
||||
|
||||
if (config.getArchitectureString() == "Win32")
|
||||
link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");
|
||||
|
|
@ -718,7 +721,7 @@ public:
|
|||
bsc->createNewChildElement ("OutputFile")->addTextElement (getOwner().getIntDirFile (config, config.getOutputFilename (".bsc", true, type)));
|
||||
}
|
||||
|
||||
if (type != SharedCodeTarget && type != LV2TurtleProgram)
|
||||
if (type != SharedCodeTarget && type != LV2Helper && type != VST3Helper)
|
||||
{
|
||||
auto* lib = group->createNewChildElement ("Lib");
|
||||
|
||||
|
|
@ -729,14 +732,27 @@ public:
|
|||
lib->createNewChildElement ("AdditionalLibraryDirectories")->addTextElement (additionalLibraryDirs);
|
||||
}
|
||||
|
||||
auto manifestFile = getOwner().getManifestPath();
|
||||
if (manifestFile.getRoot() != build_tools::RelativePath::unknown)
|
||||
if (auto manifestFile = getOwner().getManifestPath(); manifestFile.getRoot() != build_tools::RelativePath::unknown || type == VST3Helper)
|
||||
{
|
||||
auto* bsc = group->createNewChildElement ("Manifest");
|
||||
bsc->createNewChildElement ("AdditionalManifestFiles")
|
||||
->addTextElement (manifestFile.rebased (getOwner().getProject().getFile().getParentDirectory(),
|
||||
getOwner().getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder).toWindowsStyle());
|
||||
auto* additional = bsc->createNewChildElement ("AdditionalManifestFiles");
|
||||
|
||||
if (manifestFile.getRoot() != build_tools::RelativePath::unknown)
|
||||
{
|
||||
additional->addTextElement (manifestFile.rebased (getOwner().getProject().getFile().getParentDirectory(),
|
||||
getOwner().getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder).toWindowsStyle());
|
||||
}
|
||||
|
||||
if (type == VST3Helper)
|
||||
{
|
||||
const auto manifest = getOwner().getModuleFolderRelativeToProject ("juce_audio_processors").getChildFile ("format_types")
|
||||
.getChildFile ("VST3_SDK")
|
||||
.getChildFile ("helper.manifest");
|
||||
additional->addTextElement (manifest.rebased (getOwner().getProject().getFile().getParentDirectory(),
|
||||
getOwner().getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder).toWindowsStyle());
|
||||
}
|
||||
}
|
||||
|
||||
if (getTargetFileType() == staticLibrary && config.getArchitectureString() == "Win32")
|
||||
|
|
@ -774,12 +790,21 @@ public:
|
|||
addFilesToCompile (group, *cppFiles, *headerFiles, *otherFilesGroup);
|
||||
}
|
||||
|
||||
if (type == LV2TurtleProgram)
|
||||
if (type == LV2Helper)
|
||||
{
|
||||
const auto location = owner.rebaseFromProjectFolderToBuildTarget (owner.getLV2TurtleDumpProgramSource())
|
||||
const auto location = owner.rebaseFromProjectFolderToBuildTarget (owner.getLV2HelperProgramSource())
|
||||
.toWindowsStyle();
|
||||
cppFiles->createNewChildElement ("ClCompile")->setAttribute ("Include", location);
|
||||
}
|
||||
else if (type == VST3Helper)
|
||||
{
|
||||
for (const auto& source : owner.getVST3HelperProgramSources (owner))
|
||||
{
|
||||
const auto location = owner.rebaseFromProjectFolderToBuildTarget (source)
|
||||
.toWindowsStyle();
|
||||
cppFiles->createNewChildElement ("ClCompile")->setAttribute ("Include", location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getOwner().iconFile.existsAsFile())
|
||||
|
|
@ -1274,7 +1299,7 @@ public:
|
|||
const auto* writerTarget = [&]() -> MSVCTargetBase*
|
||||
{
|
||||
for (auto* target : owner.targets)
|
||||
if (target->type == LV2TurtleProgram)
|
||||
if (target->type == LV2Helper)
|
||||
return target;
|
||||
|
||||
return nullptr;
|
||||
|
|
@ -1298,10 +1323,42 @@ public:
|
|||
if (type == VST3PlugIn)
|
||||
{
|
||||
const auto segments = getVst3BundleStructure (config);
|
||||
|
||||
const auto manifestScript = [&]() -> String
|
||||
{
|
||||
const auto* writerTarget = [&]() -> MSVCTargetBase*
|
||||
{
|
||||
for (auto* target : owner.targets)
|
||||
if (target->type == VST3Helper)
|
||||
return target;
|
||||
|
||||
return nullptr;
|
||||
}();
|
||||
|
||||
if (writerTarget == nullptr)
|
||||
return "";
|
||||
|
||||
const auto writer = writerTarget->getConfigTargetPath (config)
|
||||
+ "\\"
|
||||
+ writerTarget->getBinaryNameWithSuffix (config);
|
||||
|
||||
// moduleinfotool doesn't handle Windows-style path separators properly when computing the bundle name
|
||||
const auto normalisedBundlePath = getOwner().getOutDirFile (config, segments[0]).replace ("\\", "/");
|
||||
|
||||
return "\r\n"
|
||||
+ writer.quoted()
|
||||
+ " -create -version "
|
||||
+ getOwner().project.getVersionString().quoted()
|
||||
+ " -path "
|
||||
+ normalisedBundlePath.quoted()
|
||||
+ " -output "
|
||||
+ (getOwner().getOutDirFile (config, segments[0]) + "\\Contents\\moduleinfo.json").quoted();
|
||||
}();
|
||||
|
||||
const auto pkgScript = copyBuildOutputIntoBundle (segments);
|
||||
const auto copyScript = copyBundleToInstallDirectory (segments, config.getVST3BinaryLocationString());
|
||||
|
||||
return pkgScript + copyScript;
|
||||
return pkgScript + manifestScript + copyScript;
|
||||
}
|
||||
|
||||
if (type == VSTPlugIn && config.isPluginBinaryCopyStepEnabled())
|
||||
|
|
@ -1365,7 +1422,7 @@ public:
|
|||
{
|
||||
auto librarySearchPaths = config.getLibrarySearchPaths();
|
||||
|
||||
if (type != SharedCodeTarget && type != LV2TurtleProgram)
|
||||
if (type != SharedCodeTarget && type != LV2Helper && type != VST3Helper)
|
||||
if (auto* shared = getOwner().getSharedCodeTarget())
|
||||
librarySearchPaths.add (shared->getConfigTargetPath (config));
|
||||
|
||||
|
|
@ -1388,7 +1445,7 @@ public:
|
|||
|
||||
result.addArray (msBuildEscape (getOwner().getModuleLibs()));
|
||||
|
||||
if (type != SharedCodeTarget && type != LV2TurtleProgram)
|
||||
if (type != SharedCodeTarget && type != LV2Helper && type != VST3Helper)
|
||||
if (auto* shared = getOwner().getSharedCodeTarget())
|
||||
result.add (msBuildEscape (shared->getBinaryNameWithSuffix (config)));
|
||||
|
||||
|
|
@ -1487,10 +1544,11 @@ public:
|
|||
case Target::AggregateTarget:
|
||||
case Target::VSTPlugIn:
|
||||
case Target::VST3PlugIn:
|
||||
case Target::VST3Helper:
|
||||
case Target::AAXPlugIn:
|
||||
case Target::UnityPlugIn:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
case Target::DynamicLibrary:
|
||||
return true;
|
||||
case Target::AudioUnitPlugIn:
|
||||
|
|
@ -1690,7 +1748,8 @@ protected:
|
|||
void writeProjectDependencies (OutputStream& out) const
|
||||
{
|
||||
const auto sharedCodeGuid = getTargetGuid (MSVCTargetBase::SharedCodeTarget);
|
||||
const auto turtleGuid = getTargetGuid (MSVCTargetBase::LV2TurtleProgram);
|
||||
const auto lv2HelperGuid = getTargetGuid (MSVCTargetBase::LV2Helper);
|
||||
const auto vst3HelperGuid = getTargetGuid (MSVCTargetBase::VST3Helper);
|
||||
|
||||
for (int addingOtherTargets = 0; addingOtherTargets < (sharedCodeGuid.isNotEmpty() ? 2 : 1); ++addingOtherTargets)
|
||||
{
|
||||
|
|
@ -1706,13 +1765,17 @@ protected:
|
|||
|
||||
if (sharedCodeGuid.isNotEmpty()
|
||||
&& target->type != MSVCTargetBase::SharedCodeTarget
|
||||
&& target->type != MSVCTargetBase::LV2TurtleProgram)
|
||||
&& target->type != MSVCTargetBase::LV2Helper
|
||||
&& target->type != MSVCTargetBase::VST3Helper)
|
||||
{
|
||||
out << "\tProjectSection(ProjectDependencies) = postProject" << newLine
|
||||
<< "\t\t" << sharedCodeGuid << " = " << sharedCodeGuid << newLine;
|
||||
|
||||
if (target->type == MSVCTargetBase::LV2PlugIn && turtleGuid.isNotEmpty())
|
||||
out << "\t\t" << turtleGuid << " = " << turtleGuid << newLine;
|
||||
if (target->type == MSVCTargetBase::LV2PlugIn && lv2HelperGuid.isNotEmpty())
|
||||
out << "\t\t" << lv2HelperGuid << " = " << lv2HelperGuid << newLine;
|
||||
|
||||
if (target->type == MSVCTargetBase::VST3PlugIn && vst3HelperGuid.isNotEmpty() && project.isVst3ManifestEnabled())
|
||||
out << "\t\t" << vst3HelperGuid << " = " << vst3HelperGuid << newLine;
|
||||
|
||||
out << "\tEndProjectSection" << newLine;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,10 +221,14 @@ public:
|
|||
s.add ("JUCE_LV2DIR := " + escapeQuotesAndSpaces (targetName) + ".lv2");
|
||||
targetName = "$(JUCE_LV2DIR)/" + targetName + ".so";
|
||||
}
|
||||
else if (type == LV2TurtleProgram)
|
||||
else if (type == LV2Helper)
|
||||
{
|
||||
targetName = Project::getLV2FileWriterName();
|
||||
}
|
||||
else if (type == VST3Helper)
|
||||
{
|
||||
targetName = Project::getVST3FileWriterName();
|
||||
}
|
||||
|
||||
s.add ("JUCE_TARGET_" + getTargetVarName() + String (" := ") + escapeQuotesAndSpaces (targetName));
|
||||
|
||||
|
|
@ -331,9 +335,12 @@ public:
|
|||
|
||||
String getPhonyName() const
|
||||
{
|
||||
if (type == LV2TurtleProgram)
|
||||
if (type == LV2Helper)
|
||||
return "LV2_MANIFEST_HELPER";
|
||||
|
||||
if (type == VST3Helper)
|
||||
return "VST3_MANIFEST_HELPER";
|
||||
|
||||
return String (getName()).upToFirstOccurrenceOf (" ", false, false);
|
||||
}
|
||||
|
||||
|
|
@ -349,6 +356,8 @@ public:
|
|||
|
||||
if (type == LV2PlugIn)
|
||||
out << " $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_MANIFEST_HELPER)";
|
||||
else if (type == VST3PlugIn && owner.project.isVst3ManifestEnabled())
|
||||
out << " $(JUCE_OUTDIR)/$(JUCE_TARGET_VST3_MANIFEST_HELPER)";
|
||||
|
||||
out << newLine;
|
||||
|
||||
|
|
@ -399,6 +408,15 @@ public:
|
|||
|
||||
if (type == VST3PlugIn)
|
||||
{
|
||||
if (owner.project.isVst3ManifestEnabled())
|
||||
{
|
||||
out << "\t$(V_AT) $(JUCE_OUTDIR)/$(JUCE_TARGET_VST3_MANIFEST_HELPER) "
|
||||
"-create "
|
||||
"-version " << owner.project.getVersionString().quoted() << " "
|
||||
"-path \"$(JUCE_OUTDIR)/$(JUCE_VST3DIR)\" "
|
||||
"-output \"$(JUCE_OUTDIR)/$(JUCE_VST3DIR)/Contents/moduleinfo.json\" " << newLine;
|
||||
}
|
||||
|
||||
out << "\t-$(V_AT)[ ! \"$(JUCE_VST3DESTDIR)\" ] || (mkdir -p $(JUCE_VST3DESTDIR) && cp -R $(JUCE_COPYCMD_VST3))" << newLine;
|
||||
}
|
||||
else if (type == VSTPlugIn)
|
||||
|
|
@ -486,11 +504,12 @@ public:
|
|||
case Target::AggregateTarget:
|
||||
case Target::VSTPlugIn:
|
||||
case Target::VST3PlugIn:
|
||||
case Target::VST3Helper:
|
||||
case Target::StandalonePlugIn:
|
||||
case Target::DynamicLibrary:
|
||||
case Target::UnityPlugIn:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
return true;
|
||||
case Target::AAXPlugIn:
|
||||
case Target::AudioUnitPlugIn:
|
||||
|
|
@ -1172,13 +1191,23 @@ private:
|
|||
targetFiles.emplace_back (linuxSubprocessHelperProperties.getLinuxSubprocessHelperBinaryDataSource(), "");
|
||||
}
|
||||
|
||||
if (targetType == MakefileTarget::LV2TurtleProgram)
|
||||
if (targetType == MakefileTarget::LV2Helper)
|
||||
{
|
||||
targetFiles.emplace_back (getLV2TurtleDumpProgramSource().rebased (projectFolder,
|
||||
getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder),
|
||||
targetFiles.emplace_back (getLV2HelperProgramSource().rebased (projectFolder,
|
||||
getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder),
|
||||
String{});
|
||||
}
|
||||
else if (targetType == MakefileTarget::VST3Helper)
|
||||
{
|
||||
for (const auto& source : getVST3HelperProgramSources (*this))
|
||||
{
|
||||
targetFiles.emplace_back (source.rebased (projectFolder,
|
||||
getTargetFolder(),
|
||||
build_tools::RelativePath::buildTargetFolder),
|
||||
String{});
|
||||
}
|
||||
}
|
||||
|
||||
return targetFiles;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -298,10 +298,10 @@ public:
|
|||
case Target::AudioUnitPlugIn:
|
||||
case Target::UnityPlugIn:
|
||||
case Target::LV2PlugIn:
|
||||
case Target::LV2TurtleProgram:
|
||||
case Target::LV2Helper:
|
||||
case Target::VST3Helper:
|
||||
return ! iOS;
|
||||
case Target::unspecified:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1068,11 +1068,16 @@ public:
|
|||
break;
|
||||
|
||||
case ConsoleApp:
|
||||
case LV2TurtleProgram:
|
||||
case LV2Helper:
|
||||
case VST3Helper:
|
||||
xcodeFileType = "compiled.mach-o.executable";
|
||||
xcodeBundleExtension = String();
|
||||
xcodeProductType = "com.apple.product-type.tool";
|
||||
xcodeCopyToProductInstallPathAfterBuild = false;
|
||||
|
||||
if (type == VST3Helper)
|
||||
xcodeFrameworks.add ("Cocoa");
|
||||
|
||||
break;
|
||||
|
||||
case StaticLibrary:
|
||||
|
|
@ -1216,9 +1221,12 @@ public:
|
|||
if (xcodeFileType == "archive.ar")
|
||||
return getStaticLibbedFilename (binaryName);
|
||||
|
||||
if (type == LV2TurtleProgram)
|
||||
if (type == LV2Helper)
|
||||
return Project::getLV2FileWriterName();
|
||||
|
||||
if (type == VST3Helper)
|
||||
return Project::getVST3FileWriterName();
|
||||
|
||||
return binaryName + xcodeBundleExtension;
|
||||
}();
|
||||
|
||||
|
|
@ -1257,37 +1265,43 @@ public:
|
|||
if (! owner.project.isAudioPluginProject())
|
||||
return;
|
||||
|
||||
if (type == XcodeTarget::StandalonePlugIn) // depends on AUv3 and shared code
|
||||
{
|
||||
if (auto* auv3Target = owner.getTargetOfType (XcodeTarget::AudioUnitv3PlugIn))
|
||||
dependencyIDs.add (auv3Target->addDependencyFor (*this));
|
||||
|
||||
if (auto* sharedCodeTarget = owner.getTargetOfType (XcodeTarget::SharedCodeTarget))
|
||||
dependencyIDs.add (sharedCodeTarget->addDependencyFor (*this));
|
||||
}
|
||||
else if (type == XcodeTarget::AggregateTarget) // depends on all other targets
|
||||
if (type == XcodeTarget::AggregateTarget) // depends on all other targets
|
||||
{
|
||||
for (auto* target : owner.targets)
|
||||
if (target->type != XcodeTarget::AggregateTarget)
|
||||
dependencyIDs.add (target->addDependencyFor (*this));
|
||||
}
|
||||
else if (type == XcodeTarget::LV2PlugIn)
|
||||
{
|
||||
if (auto* helperTarget = owner.getTargetOfType (XcodeTarget::LV2TurtleProgram))
|
||||
dependencyIDs.add (helperTarget->addDependencyFor (*this));
|
||||
|
||||
if (auto* sharedCodeTarget = owner.getTargetOfType (XcodeTarget::SharedCodeTarget))
|
||||
dependencyIDs.add (sharedCodeTarget->addDependencyFor (*this));
|
||||
return;
|
||||
}
|
||||
else if (type == XcodeTarget::LV2TurtleProgram)
|
||||
|
||||
if (type == XcodeTarget::LV2Helper || type == XcodeTarget::VST3Helper)
|
||||
{
|
||||
// No thanks
|
||||
return;
|
||||
}
|
||||
else if (type != XcodeTarget::SharedCodeTarget) // shared code doesn't depend on anything; all other targets depend only on the shared code
|
||||
|
||||
if (type != XcodeTarget::SharedCodeTarget) // everything else depends on the sharedCodeTarget
|
||||
{
|
||||
if (auto* sharedCodeTarget = owner.getTargetOfType (XcodeTarget::SharedCodeTarget))
|
||||
dependencyIDs.add (sharedCodeTarget->addDependencyFor (*this));
|
||||
}
|
||||
|
||||
if (type == LV2PlugIn)
|
||||
{
|
||||
if (auto* helperTarget = owner.getTargetOfType (LV2Helper))
|
||||
dependencyIDs.add (helperTarget->addDependencyFor (*this));
|
||||
}
|
||||
|
||||
if (type == VST3PlugIn && owner.project.isVst3ManifestEnabled())
|
||||
{
|
||||
if (auto* helperTarget = owner.getTargetOfType (VST3Helper))
|
||||
dependencyIDs.add (helperTarget->addDependencyFor (*this));
|
||||
}
|
||||
|
||||
if (type == XcodeTarget::StandalonePlugIn)
|
||||
{
|
||||
if (auto* auv3Target = owner.getTargetOfType (XcodeTarget::AudioUnitv3PlugIn))
|
||||
dependencyIDs.add (auv3Target->addDependencyFor (*this));
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1479,9 +1493,12 @@ public:
|
|||
|
||||
const auto productName = [&]
|
||||
{
|
||||
if (type == LV2TurtleProgram)
|
||||
if (type == LV2Helper)
|
||||
return Project::getLV2FileWriterName().quoted();
|
||||
|
||||
if (type == VST3Helper)
|
||||
return Project::getVST3FileWriterName().quoted();
|
||||
|
||||
return owner.replacePreprocessorTokens (config, config.getTargetBinaryNameString (type == UnityPlugIn)).quoted();
|
||||
}();
|
||||
|
||||
|
|
@ -1815,7 +1832,8 @@ public:
|
|||
case LV2PlugIn: return config.isPluginBinaryCopyStepEnabled() ? config.getLV2PluginBinaryLocationString() : String();
|
||||
case SharedCodeTarget: return owner.isiOS() ? "@executable_path/Frameworks" : "@executable_path/../Frameworks";
|
||||
case StaticLibrary:
|
||||
case LV2TurtleProgram:
|
||||
case LV2Helper:
|
||||
case VST3Helper:
|
||||
case DynamicLibrary:
|
||||
case AudioUnitv3PlugIn:
|
||||
case StandalonePlugIn:
|
||||
|
|
@ -1831,7 +1849,7 @@ public:
|
|||
if (getTargetFileType() == pluginBundle)
|
||||
flags.add (owner.isiOS() ? "-bitcode_bundle" : "-bundle");
|
||||
|
||||
if (type != Target::SharedCodeTarget && type != Target::LV2TurtleProgram)
|
||||
if (type != Target::SharedCodeTarget && type != Target::LV2Helper && type != Target::VST3Helper)
|
||||
{
|
||||
if (owner.project.isAudioPluginProject())
|
||||
{
|
||||
|
|
@ -2104,10 +2122,10 @@ private:
|
|||
|
||||
target->addMainBuildProduct();
|
||||
|
||||
if (target->type == XcodeTarget::LV2TurtleProgram
|
||||
if (target->type == XcodeTarget::LV2Helper
|
||||
&& project.getEnabledModules().isModuleEnabled ("juce_audio_plugin_client"))
|
||||
{
|
||||
const auto path = rebaseFromProjectFolderToBuildTarget (getLV2TurtleDumpProgramSource());
|
||||
const auto path = rebaseFromProjectFolderToBuildTarget (getLV2HelperProgramSource ());
|
||||
addFile (FileOptions().withRelativePath ({ expandPath (path.toUnixStyle()), path.getRoot() })
|
||||
.withSkipPCHEnabled (true)
|
||||
.withCompilationEnabled (true)
|
||||
|
|
@ -2116,6 +2134,21 @@ private:
|
|||
.withXcodeTarget (target));
|
||||
}
|
||||
|
||||
if (target->type == XcodeTarget::VST3Helper
|
||||
&& project.getEnabledModules().isModuleEnabled ("juce_audio_processors"))
|
||||
{
|
||||
for (const auto& source : getVST3HelperProgramSources (*this))
|
||||
{
|
||||
const auto path = rebaseFromProjectFolderToBuildTarget (source);
|
||||
addFile (FileOptions().withRelativePath ({ expandPath (path.toUnixStyle()), path.getRoot() })
|
||||
.withSkipPCHEnabled (true)
|
||||
.withCompilationEnabled (true)
|
||||
.withInhibitWarningsEnabled (true)
|
||||
.withCompilerFlags ("-std=c++17 -fobjc-arc")
|
||||
.withXcodeTarget (target));
|
||||
}
|
||||
}
|
||||
|
||||
auto targetName = String (target->getName());
|
||||
auto fileID = createID (targetName + "__targetbuildref");
|
||||
auto fileRefID = createID ("__productFileID" + targetName);
|
||||
|
|
@ -2266,7 +2299,8 @@ private:
|
|||
|
||||
if (! projectType.isStaticLibrary()
|
||||
&& target->type != XcodeTarget::SharedCodeTarget
|
||||
&& target->type != XcodeTarget::LV2TurtleProgram
|
||||
&& target->type != XcodeTarget::LV2Helper
|
||||
&& target->type != XcodeTarget::VST3Helper
|
||||
&& ! skipAUv3)
|
||||
target->addBuildPhase ("PBXResourcesBuildPhase", resourceIDs);
|
||||
|
||||
|
|
@ -2286,42 +2320,68 @@ private:
|
|||
|
||||
if (! projectType.isStaticLibrary()
|
||||
&& target->type != XcodeTarget::SharedCodeTarget
|
||||
&& target->type != XcodeTarget::LV2TurtleProgram)
|
||||
&& target->type != XcodeTarget::LV2Helper)
|
||||
{
|
||||
target->addBuildPhase ("PBXFrameworksBuildPhase", target->frameworkIDs);
|
||||
}
|
||||
}
|
||||
|
||||
if (target->type == XcodeTarget::LV2PlugIn)
|
||||
// When building LV2 and VST3 plugins on Arm macs, we need to load and run the plugin
|
||||
// bundle during a post-build step in order to generate the plugin's supporting files.
|
||||
// Arm macs will only load shared libraries if they are signed, but Xcode runs its
|
||||
// signing step after any post-build scripts. As a workaround, we check whether the
|
||||
// plugin is signed and generate an adhoc certificate if necessary, before running
|
||||
// the manifest-generator.
|
||||
if (target->type == XcodeTarget::VST3PlugIn || target->type == XcodeTarget::LV2PlugIn)
|
||||
{
|
||||
// When building LV2 plugins on Arm macs, we need to load and run the plugin bundle
|
||||
// during a post-build step in order to generate the plugin's supporting files. Arm
|
||||
// macs will only load shared libraries if they are signed, but Xcode runs its
|
||||
// signing step after any post-build scripts. As a workaround, we check whether the
|
||||
// plugin is signed and generate an adhoc certificate if necessary, before running
|
||||
// the manifest-generator.
|
||||
auto script = "set -e\n"
|
||||
"xcrun codesign --verify \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\" "
|
||||
"|| xcrun codesign -s - \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n"
|
||||
"\"$CONFIGURATION_BUILD_DIR/../"
|
||||
+ Project::getLV2FileWriterName()
|
||||
+ "\" \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n";
|
||||
String script = "set -e\n";
|
||||
|
||||
for (ConstConfigIterator config (*this); config.next();)
|
||||
// Delete manifest if it's left over from an old build
|
||||
if (target->type == XcodeTarget::VST3PlugIn)
|
||||
script << "rm -f \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME/Contents/moduleinfo.json\"\n";
|
||||
|
||||
// Sign the bundle so that it can be loaded by the manifest generator tools
|
||||
script << "xcrun codesign --verify \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\" "
|
||||
"|| xcrun codesign -f -s - \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\"\n";
|
||||
|
||||
if (target->type == XcodeTarget::LV2PlugIn)
|
||||
{
|
||||
auto& xcodeConfig = dynamic_cast<const XcodeBuildConfiguration&> (*config);
|
||||
const auto installPath = target->getInstallPathForConfiguration (xcodeConfig);
|
||||
// Note: LV2 has a non-standard config build dir
|
||||
script << "\"$CONFIGURATION_BUILD_DIR/../"
|
||||
+ Project::getLV2FileWriterName()
|
||||
+ "\" \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\"\n";
|
||||
|
||||
if (installPath.isNotEmpty())
|
||||
for (ConstConfigIterator config (*this); config.next();)
|
||||
{
|
||||
const auto destination = installPath.replace ("$(HOME)", "$HOME");
|
||||
auto& xcodeConfig = dynamic_cast<const XcodeBuildConfiguration&> (*config);
|
||||
const auto installPath = target->getInstallPathForConfiguration (xcodeConfig);
|
||||
|
||||
script << "if [ \"$CONFIGURATION\" = \"" << config->getName() << "\" ]; then\n"
|
||||
"mkdir -p \"" << destination << "\"\n"
|
||||
"/bin/ln -sfh \"$CONFIGURATION_BUILD_DIR\" \"" << destination << "\"\n"
|
||||
"fi\n";
|
||||
if (installPath.isNotEmpty())
|
||||
{
|
||||
const auto destination = installPath.replace ("$(HOME)", "$HOME");
|
||||
|
||||
script << R"(if [ "$CONFIGURATION" = ")" << config->getName() << "\" ]; then\n"
|
||||
"mkdir -p \"" << destination << "\"\n"
|
||||
"/bin/ln -sfh \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\" \"" << destination << "\"\n"
|
||||
"fi\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (target->type == XcodeTarget::VST3PlugIn && project.isVst3ManifestEnabled())
|
||||
{
|
||||
// Generate the manifest
|
||||
script << "\"$CONFIGURATION_BUILD_DIR/" << Project::getVST3FileWriterName() << "\" "
|
||||
"-create "
|
||||
"-version " << project.getVersionString().quoted() << " "
|
||||
"-path \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\" "
|
||||
"-output \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME/Contents/moduleinfo.json\"\n";
|
||||
// Sign the manifest (a prerequisite of signing the containing bundle)
|
||||
script << "xcrun codesign -f -s - \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME/Contents/moduleinfo.json\"\n";
|
||||
// Sign the full bundle
|
||||
script << "xcrun codesign -f -s - \"$CONFIGURATION_BUILD_DIR/$FULL_PRODUCT_NAME\"\n";
|
||||
}
|
||||
|
||||
target->addShellScriptBuildPhase ("Generate manifest", script);
|
||||
target->addShellScriptBuildPhase ("Update manifest", script);
|
||||
}
|
||||
|
||||
target->addShellScriptBuildPhase ("Post-build script", getPostBuildScript());
|
||||
|
|
|
|||
|
|
@ -216,13 +216,52 @@ public:
|
|||
void createPropertyEditors (PropertyListBuilder&);
|
||||
void addSettingsForProjectType (const build_tools::ProjectType&);
|
||||
|
||||
build_tools::RelativePath getLV2TurtleDumpProgramSource() const
|
||||
build_tools::RelativePath getLV2HelperProgramSource() const
|
||||
{
|
||||
return getModuleFolderRelativeToProject ("juce_audio_plugin_client")
|
||||
.getChildFile ("LV2")
|
||||
.getChildFile ("juce_LV2TurtleDumpProgram.cpp");
|
||||
}
|
||||
|
||||
std::vector<build_tools::RelativePath> getVST3HelperProgramSources (const ProjectExporter& exporter) const
|
||||
{
|
||||
const auto base = getModuleFolderRelativeToProject ("juce_audio_processors").getChildFile ("format_types")
|
||||
.getChildFile ("VST3_SDK");
|
||||
const auto vst = base.getChildFile ("public.sdk")
|
||||
.getChildFile ("source")
|
||||
.getChildFile ("vst");
|
||||
const auto hosting = vst.getChildFile ("hosting");
|
||||
|
||||
std::vector<build_tools::RelativePath> result
|
||||
{
|
||||
base.getChildFile ("public.sdk")
|
||||
.getChildFile ("samples")
|
||||
.getChildFile ("vst-utilities")
|
||||
.getChildFile ("moduleinfotool")
|
||||
.getChildFile ("source")
|
||||
.getChildFile ("main.cpp"),
|
||||
base.getChildFile ("pluginterfaces")
|
||||
.getChildFile ("base")
|
||||
.getChildFile ("coreiids.cpp"),
|
||||
hosting.getChildFile ("module.cpp"),
|
||||
vst.getChildFile ("moduleinfo")
|
||||
.getChildFile ("moduleinfocreator.cpp"),
|
||||
vst.getChildFile ("moduleinfo")
|
||||
.getChildFile ("moduleinfoparser.cpp"),
|
||||
vst.getChildFile ("utility")
|
||||
.getChildFile ("stringconvert.cpp"),
|
||||
};
|
||||
|
||||
if (exporter.isOSX())
|
||||
result.push_back (hosting.getChildFile ("module_mac.mm"));
|
||||
else if (exporter.isLinux())
|
||||
result.push_back (hosting.getChildFile ("module_linux.cpp"));
|
||||
else if (exporter.isWindows())
|
||||
result.push_back (hosting.getChildFile ("module_win32.cpp"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void copyMainGroupFromProject();
|
||||
Array<Project::Item>& getAllGroups() noexcept { jassert (itemGroups.size() > 0); return itemGroups; }
|
||||
|
|
|
|||
|
|
@ -391,6 +391,7 @@ namespace Ids
|
|||
DECLARE_ID (lv2Uri);
|
||||
DECLARE_ID (lv2UriUi);
|
||||
DECLARE_ID (lv2BinaryLocation);
|
||||
DECLARE_ID (vst3ManifestEnabled);
|
||||
|
||||
DECLARE_ID (osxSDK);
|
||||
DECLARE_ID (osxCompatibility);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue