@@ -36,11 +36,19 @@ public: | |||
bool isAndroidStudio() const override { return false; } | |||
bool isAndroidAnt() const override { return true; } | |||
bool supportsVST() const override { return false; } | |||
bool supportsVST3() const override { return false; } | |||
bool supportsAAX() const override { return false; } | |||
bool supportsRTAS() const override { return false; } | |||
bool supportsStandalone() const override { return false; } | |||
bool supportsTargetType (ProjectType::Target::Type type) const override | |||
{ | |||
switch (type) | |||
{ | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::StaticLibrary: | |||
return true; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
//============================================================================== | |||
static const char* getName() { return "Android Ant Project"; } | |||
@@ -340,7 +348,7 @@ private: | |||
flags << " -std=gnu++11"; | |||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs ()); | |||
return flags + createGCCPreprocessorFlags (defines); | |||
} | |||
@@ -58,13 +58,19 @@ public: | |||
bool isOSX() const override { return false; } | |||
bool isiOS() const override { return false; } | |||
bool supportsVST() const override { return false; } | |||
bool supportsVST3() const override { return false; } | |||
bool supportsAAX() const override { return false; } | |||
bool supportsRTAS() const override { return false; } | |||
bool supportsAU() const override { return false; } | |||
bool supportsAUv3() const override { return false; } | |||
bool supportsStandalone() const override { return false; } | |||
bool supportsTargetType (ProjectType::Target::Type type) const override | |||
{ | |||
switch (type) | |||
{ | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::StaticLibrary: | |||
return true; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
//============================================================================== | |||
void create (const OwnedArray<LibraryModule>& modules) const override | |||
@@ -51,7 +51,7 @@ public: | |||
AndroidStudioProjectExporter (Project& p, const ValueTree& t) | |||
: AndroidProjectExporterBase (p, t), | |||
gradleVersion (settings, Ids::gradleVersion, nullptr, "2.14.1"), | |||
gradleWrapperVersion (settings, Ids::gradleWrapperVersion, nullptr, "0.8.1"), | |||
gradleWrapperVersion (settings, Ids::androidPluginVersion, nullptr, "0.8.1"), | |||
gradleToolchain (settings, Ids::gradleToolchain, nullptr, "clang"), | |||
buildToolsVersion (settings, Ids::buildToolsVersion, nullptr, "23.0.2"), | |||
androidStudioExecutable (findAndroidStudioExecutable()) | |||
@@ -113,13 +113,25 @@ public: | |||
bool isOSX() const override { return false; } | |||
bool isiOS() const override { return false; } | |||
bool supportsVST() const override { return false; } | |||
bool supportsVST3() const override { return false; } | |||
bool supportsAAX() const override { return false; } | |||
bool supportsRTAS() const override { return false; } | |||
bool supportsAU() const override { return false; } | |||
bool supportsAUv3() const override { return false; } | |||
bool supportsStandalone() const override { return false; } | |||
bool supportsTargetType (ProjectType::Target::Type type) const override | |||
{ | |||
switch (type) | |||
{ | |||
case ProjectType::Target::StandalonePlugIn: | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::ConsoleApp: | |||
case ProjectType::Target::StaticLibrary: | |||
case ProjectType::Target::SharedCodeTarget: | |||
case ProjectType::Target::AggregateTarget: | |||
case ProjectType::Target::VSTPlugIn: | |||
case ProjectType::Target::DynamicLibrary: | |||
return true; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
void createExporterProperties (PropertyListBuilder&) override | |||
{ | |||
@@ -138,9 +150,30 @@ public: | |||
} | |||
//============================================================================== | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType& type) override | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType&) override | |||
{ | |||
createDynamicLibrary = type.isAudioPlugin() || type.isDynamicLibrary(); | |||
// add shared code target first as order matters for Codeblocks | |||
if (shouldBuildTargetType (ProjectType::Target::SharedCodeTarget)) | |||
targets.add (new CodeBlocksTarget (*this, ProjectType::Target::SharedCodeTarget)); | |||
//ProjectType::Target::SharedCodeTarget | |||
callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) | |||
{ | |||
if (targetType == ProjectType::Target::SharedCodeTarget) | |||
return; | |||
if (auto* target = new CodeBlocksTarget (*this, targetType)) | |||
{ | |||
if (targetType == ProjectType::Target::AggregateTarget) | |||
targets.insert (0, target); | |||
else | |||
targets.add (target); | |||
} | |||
}); | |||
// If you hit this assert, you tried to generate a project for an exporter | |||
// that does not support any of your targets! | |||
jassert (targets.size() > 0); | |||
} | |||
private: | |||
@@ -151,14 +184,52 @@ private: | |||
CodeBlocksBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e) | |||
: BuildConfiguration (p, settings, e) | |||
{ | |||
if (getArchitectureType().toString().isEmpty()) | |||
getArchitectureType() = static_cast<const char* const> ("-m64"); | |||
} | |||
Value getArchitectureType() | |||
{ | |||
const auto archID = exporter.isWindows() ? Ids::windowsCodeBlocksArchitecture | |||
: Ids::linuxCodeBlocksArchitecture; | |||
return getValue (archID); | |||
} | |||
var getArchitectureTypeVar() const | |||
{ | |||
const auto archID = exporter.isWindows() ? Ids::windowsCodeBlocksArchitecture | |||
: Ids::linuxCodeBlocksArchitecture; | |||
return config [archID]; | |||
} | |||
var getDefaultOptimisationLevel() const override { return var ((int) (isDebug() ? gccO0 : gccO3)); } | |||
void createConfigProperties (PropertyListBuilder& props) override | |||
{ | |||
addGCCOptimisationProperty (props); | |||
static const char* const archNames[] = { "32-bit (-m32)", "64-bit (-m64)", "ARM v6", "ARM v7" }; | |||
const var archFlags[] = { "-m32", "-m64", "-march=armv6", "-march=armv7" }; | |||
props.add (new ChoicePropertyComponent (getArchitectureType(), "Architecture", | |||
StringArray (archNames, numElementsInArray (archNames)), | |||
Array<var> (archFlags, numElementsInArray (archFlags)))); | |||
} | |||
var getDefaultOptimisationLevel() const override { return var ((int) (isDebug() ? gccO0 : gccO3)); } | |||
String getLibrarySubdirPath () const override | |||
{ | |||
const String archFlag = getArchitectureTypeVar(); | |||
const auto prefix = String ("-march="); | |||
if (archFlag.startsWith (prefix)) | |||
return String ("/") + archFlag.substring (prefix.length()); | |||
else if (archFlag == "-m64") | |||
return "/x86_64"; | |||
else if (archFlag == "-m32") | |||
return "/i386"; | |||
jassertfalse; | |||
return String(); | |||
} | |||
}; | |||
BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override | |||
@@ -166,6 +237,59 @@ private: | |||
return new CodeBlocksBuildConfiguration (project, tree, *this); | |||
} | |||
//============================================================================== | |||
class CodeBlocksTarget : public ProjectType::Target | |||
{ | |||
public: | |||
CodeBlocksTarget (CodeBlocksProjectExporter&, ProjectType::Target::Type typeToUse) | |||
: ProjectType::Target (typeToUse) | |||
{} | |||
String getTargetNameForConfiguration (const BuildConfiguration& config) const | |||
{ | |||
if (type == ProjectType::Target::AggregateTarget) | |||
return config.getName(); | |||
return getName() + String (" | ") + config.getName(); | |||
} | |||
String getTargetSuffix() const | |||
{ | |||
const ProjectType::Target::TargetFileType fileType = getTargetFileType(); | |||
switch (fileType) | |||
{ | |||
case executable: | |||
return ""; | |||
case staticLibrary: | |||
return ".a"; | |||
case sharedLibraryOrDLL: | |||
return ".so"; | |||
case pluginBundle: | |||
switch (type) | |||
{ | |||
case VST3PlugIn: | |||
return ".vst3"; | |||
case VSTPlugIn: | |||
return ".so"; | |||
default: | |||
break; | |||
} | |||
return ".so"; | |||
default: | |||
break; | |||
} | |||
return String(); | |||
} | |||
bool isDynamicLibrary() const | |||
{ | |||
return (type == DynamicLibrary || type == VST3PlugIn || type == VSTPlugIn || type == AAXPlugIn); | |||
} | |||
}; | |||
//============================================================================== | |||
void addVersion (XmlElement& xml) const | |||
{ | |||
@@ -181,7 +305,7 @@ private: | |||
xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc"); | |||
} | |||
StringArray getDefines (const BuildConfiguration& config) const | |||
StringArray getDefines (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||
{ | |||
StringPairArray defines; | |||
@@ -205,7 +329,7 @@ private: | |||
defines.set ("NDEBUG", "1"); | |||
} | |||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config, target.type)); | |||
StringArray defs; | |||
for (int i = 0; i < defines.size(); ++i) | |||
@@ -214,9 +338,12 @@ private: | |||
return getCleanedStringArray (defs); | |||
} | |||
StringArray getCompilerFlags (const BuildConfiguration& config) const | |||
StringArray getCompilerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||
{ | |||
StringArray flags; | |||
if (const auto codeBlocksConfig = dynamic_cast<const CodeBlocksBuildConfiguration*> (&config)) | |||
flags.add (codeBlocksConfig->getArchitectureTypeVar()); | |||
flags.add ("-O" + config.getGCCOptimisationFlag()); | |||
flags.add ("-std=c++11"); | |||
flags.add ("-mstackrealign"); | |||
@@ -228,7 +355,7 @@ private: | |||
" \n", "\"'"); | |||
{ | |||
const StringArray defines (getDefines (config)); | |||
const StringArray defines (getDefines (config, target)); | |||
for (int i = 0; i < defines.size(); ++i) | |||
{ | |||
@@ -243,7 +370,7 @@ private: | |||
if (config.exporter.isLinux()) | |||
{ | |||
if (createDynamicLibrary) | |||
if (target.isDynamicLibrary() || getProject().getProjectType().isAudioPlugin()) | |||
flags.add ("-fPIC"); | |||
if (linuxPackages.size() > 0) | |||
@@ -263,19 +390,25 @@ private: | |||
return getCleanedStringArray (flags); | |||
} | |||
StringArray getLinkerFlags (const BuildConfiguration& config) const | |||
StringArray getLinkerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||
{ | |||
StringArray flags (makefileExtraLinkerFlags); | |||
if (const auto codeBlocksConfig = dynamic_cast<const CodeBlocksBuildConfiguration*> (&config)) | |||
flags.add (codeBlocksConfig->getArchitectureTypeVar()); | |||
if (! config.isDebug()) | |||
flags.add ("-s"); | |||
flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(), | |||
" \n", "\"'"); | |||
if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget) | |||
flags.add ("-l" + config.getTargetBinaryNameString()); | |||
if (config.exporter.isLinux() && linuxPackages.size() > 0) | |||
{ | |||
if (createDynamicLibrary) | |||
if (target.isDynamicLibrary()) | |||
flags.add ("-shared"); | |||
auto pkgconfigLibs = String ("`pkg-config --libs"); | |||
@@ -303,80 +436,119 @@ private: | |||
return getCleanedStringArray (paths); | |||
} | |||
static int getTypeIndex (const ProjectType& type) | |||
static int getTypeIndex (const ProjectType::Target::Type& type) | |||
{ | |||
if (type.isGUIApplication()) return 0; | |||
if (type.isCommandLineApp()) return 1; | |||
if (type.isStaticLibrary()) return 2; | |||
if (type.isDynamicLibrary()) return 3; | |||
if (type.isAudioPlugin()) return 3; | |||
switch (type) | |||
{ | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::StandalonePlugIn: | |||
return 0; | |||
case ProjectType::Target::ConsoleApp: | |||
return 1; | |||
case ProjectType::Target::StaticLibrary: | |||
case ProjectType::Target::SharedCodeTarget: | |||
return 2; | |||
case ProjectType::Target::DynamicLibrary: | |||
case ProjectType::Target::VSTPlugIn: | |||
case ProjectType::Target::VST3PlugIn: | |||
return 3; | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} | |||
void createBuildTarget (XmlElement& xml, const BuildConfiguration& config) const | |||
String getOutputPathForTarget (CodeBlocksTarget& target, const BuildConfiguration& config) const | |||
{ | |||
String outputPath; | |||
if (config.getTargetBinaryRelativePathString().isNotEmpty()) | |||
{ | |||
RelativePath binaryPath (config.getTargetBinaryRelativePathString(), RelativePath::projectFolder); | |||
binaryPath = binaryPath.rebased (projectFolder, getTargetFolder(), RelativePath::buildTargetFolder); | |||
outputPath = config.getTargetBinaryRelativePathString(); | |||
} | |||
else | |||
{ | |||
outputPath ="bin/" + File::createLegalFileName (config.getName().trim()); | |||
} | |||
return outputPath + "/" + replacePreprocessorTokens (config, config.getTargetBinaryNameString() + target.getTargetSuffix()); | |||
} | |||
String getSharedCodePath (const BuildConfiguration& config) const | |||
{ | |||
const String outputPath = getOutputPathForTarget (getTargetWithType (ProjectType::Target::SharedCodeTarget), config); | |||
RelativePath path (outputPath, RelativePath::buildTargetFolder); | |||
const String autoPrefixedFilename = "lib" + path.getFileName(); | |||
return path.getParentDirectory().getChildFile (autoPrefixedFilename).toUnixStyle(); | |||
} | |||
void createBuildTarget (XmlElement& xml, CodeBlocksTarget& target, const BuildConfiguration& config) const | |||
{ | |||
xml.setAttribute ("title", config.getName()); | |||
xml.setAttribute ("title", target.getTargetNameForConfiguration (config)); | |||
{ | |||
XmlElement* output = xml.createNewChildElement ("Option"); | |||
String outputPath; | |||
if (config.getTargetBinaryRelativePathString().isNotEmpty()) | |||
{ | |||
RelativePath binaryPath (config.getTargetBinaryRelativePathString(), RelativePath::projectFolder); | |||
binaryPath = binaryPath.rebased (projectFolder, getTargetFolder(), RelativePath::buildTargetFolder); | |||
outputPath = config.getTargetBinaryRelativePathString(); | |||
} | |||
else | |||
{ | |||
outputPath ="bin/" + File::createLegalFileName (config.getName().trim()); | |||
} | |||
output->setAttribute ("output", getOutputPathForTarget (target, config)); | |||
output->setAttribute ("output", outputPath + "/" + replacePreprocessorTokens (config, config.getTargetBinaryNameString())); | |||
const bool keepPrefix = (target.type == ProjectType::Target::VSTPlugIn || target.type == ProjectType::Target::VST3PlugIn | |||
|| target.type == ProjectType::Target::AAXPlugIn || target.type == ProjectType::Target::RTASPlugIn); | |||
output->setAttribute ("prefix_auto", 1); | |||
output->setAttribute ("extension_auto", 1); | |||
output->setAttribute ("prefix_auto", keepPrefix ? 0 : 1); | |||
output->setAttribute ("extension_auto", 0); | |||
} | |||
xml.createNewChildElement ("Option") | |||
->setAttribute ("object_output", "obj/" + File::createLegalFileName (config.getName().trim())); | |||
xml.createNewChildElement ("Option")->setAttribute ("type", getTypeIndex (project.getProjectType())); | |||
xml.createNewChildElement ("Option")->setAttribute ("type", getTypeIndex (target.type)); | |||
xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc"); | |||
if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget) | |||
xml.createNewChildElement ("Option")->setAttribute ("external_deps", getSharedCodePath (config)); | |||
{ | |||
XmlElement* const compiler = xml.createNewChildElement ("Compiler"); | |||
{ | |||
const StringArray compilerFlags (getCompilerFlags (config)); | |||
const StringArray compilerFlags (getCompilerFlags (config, target)); | |||
for (int i = 0; i < compilerFlags.size(); ++i) | |||
setAddOption (*compiler, "option", compilerFlags[i]); | |||
for (auto flag : compilerFlags) | |||
setAddOption (*compiler, "option", flag); | |||
} | |||
{ | |||
const StringArray includePaths (getIncludePaths (config)); | |||
for (int i = 0; i < includePaths.size(); ++i) | |||
setAddOption (*compiler, "directory", includePaths[i]); | |||
for (auto path : includePaths) | |||
setAddOption (*compiler, "directory", path); | |||
} | |||
} | |||
{ | |||
XmlElement* const linker = xml.createNewChildElement ("Linker"); | |||
const StringArray linkerFlags (getLinkerFlags (config)); | |||
for (int i = 0; i < linkerFlags.size(); ++i) | |||
setAddOption (*linker, "option", linkerFlags[i]); | |||
const StringArray linkerFlags (getLinkerFlags (config, target)); | |||
for (auto flag : linkerFlags) | |||
setAddOption (*linker, "option", flag); | |||
const StringArray& libs = isWindows() ? mingwLibs : linuxLibs; | |||
for (int i = 0; i < libs.size(); ++i) | |||
setAddOption (*linker, "library", libs[i]); | |||
for (auto lib : libs) | |||
setAddOption (*linker, "library", lib); | |||
const StringArray librarySearchPaths (config.getLibrarySearchPaths()); | |||
for (int i = 0; i < librarySearchPaths.size(); ++i) | |||
setAddOption (*linker, "directory", replacePreprocessorDefs (getAllPreprocessorDefs(), librarySearchPaths[i])); | |||
StringArray librarySearchPaths (config.getLibrarySearchPaths()); | |||
if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget) | |||
librarySearchPaths.add (RelativePath (getSharedCodePath (config), RelativePath::buildTargetFolder).getParentDirectory().toUnixStyle()); | |||
for (auto path : librarySearchPaths) | |||
{ | |||
setAddOption (*linker, "directory", replacePreprocessorDefs (getAllPreprocessorDefs(), path)); | |||
} | |||
} | |||
} | |||
@@ -385,7 +557,36 @@ private: | |||
XmlElement* const build = xml.createNewChildElement ("Build"); | |||
for (ConstConfigIterator config (*this); config.next();) | |||
createBuildTarget (*build->createNewChildElement ("Target"), *config); | |||
{ | |||
for (auto target : targets) | |||
if (target->type != ProjectType::Target::AggregateTarget) | |||
createBuildTarget (*build->createNewChildElement ("Target"), *target, *config); | |||
} | |||
} | |||
void addVirtualTargets (XmlElement& xml) const | |||
{ | |||
XmlElement* const virtualTargets = xml.createNewChildElement ("VirtualTargets"); | |||
for (ConstConfigIterator config (*this); config.next();) | |||
{ | |||
StringArray allTargets; | |||
for (auto target : targets) | |||
if (target->type != ProjectType::Target::AggregateTarget) | |||
allTargets.add (target->getTargetNameForConfiguration (*config)); | |||
for (auto target : targets) | |||
{ | |||
if (target->type == ProjectType::Target::AggregateTarget) | |||
{ | |||
auto* configTarget = virtualTargets->createNewChildElement ("Add"); | |||
configTarget->setAttribute ("alias", config->getName()); | |||
configTarget->setAttribute ("targets", allTargets.joinIntoString (";")); | |||
} | |||
} | |||
} | |||
} | |||
void addProjectCompilerOptions (XmlElement& xml) const | |||
@@ -416,6 +617,54 @@ private: | |||
setAddOption (*linker, "library", replacePreprocessorDefs (getAllPreprocessorDefs(), libs[i])); | |||
} | |||
CodeBlocksTarget& getTargetWithType (ProjectType::Target::Type type) const | |||
{ | |||
CodeBlocksTarget* nonAggregrateTarget = nullptr; | |||
for (auto* target : targets) | |||
{ | |||
if (target->type == type) | |||
return *target; | |||
if (target->type != ProjectType::Target::AggregateTarget) | |||
nonAggregrateTarget = target; | |||
} | |||
// this project has no valid targets | |||
jassert (nonAggregrateTarget != nullptr); | |||
return *nonAggregrateTarget; | |||
} | |||
// Returns SharedCode target for multi-target projects, otherwise it returns | |||
// the single target | |||
CodeBlocksTarget& getMainTarget() const | |||
{ | |||
if (getProject().getProjectType().isAudioPlugin()) | |||
return getTargetWithType (ProjectType::Target::SharedCodeTarget); | |||
for (auto* target : targets) | |||
if (target->type != ProjectType::Target::AggregateTarget) | |||
return *target; | |||
jassertfalse; | |||
return *targets[0]; | |||
} | |||
CodeBlocksTarget& getTargetForProjectItem (const Project::Item& projectItem) const | |||
{ | |||
if (getProject().getProjectType().isAudioPlugin()) | |||
{ | |||
if (! projectItem.shouldBeCompiled()) | |||
return getTargetWithType (ProjectType::Target::SharedCodeTarget); | |||
return getTargetWithType (getProject().getTargetTypeFromFilePath (projectItem.getFile(), true)); | |||
} | |||
return getMainTarget(); | |||
} | |||
void addCompileUnits (const Project::Item& projectItem, XmlElement& xml) const | |||
{ | |||
if (projectItem.isGroup()) | |||
@@ -430,10 +679,16 @@ private: | |||
XmlElement* unit = xml.createNewChildElement ("Unit"); | |||
unit->setAttribute ("filename", file.toUnixStyle()); | |||
for (ConstConfigIterator config (*this); config.next();) | |||
{ | |||
const String& targetName = getTargetForProjectItem (projectItem).getTargetNameForConfiguration (*config); | |||
unit->createNewChildElement ("Option")->setAttribute ("target", targetName); | |||
} | |||
if (! projectItem.shouldBeCompiled()) | |||
{ | |||
unit->createNewChildElement("Option")->setAttribute ("compile", 0); | |||
unit->createNewChildElement("Option")->setAttribute ("link", 0); | |||
unit->createNewChildElement ("Option")->setAttribute ("compile", 0); | |||
unit->createNewChildElement ("Option")->setAttribute ("link", 0); | |||
} | |||
} | |||
} | |||
@@ -448,6 +703,7 @@ private: | |||
{ | |||
addOptions (xml); | |||
addBuild (xml); | |||
addVirtualTargets (xml); | |||
addProjectCompilerOptions (xml); | |||
addProjectLinkerOptions (xml); | |||
addCompileUnits (xml); | |||
@@ -473,7 +729,8 @@ private: | |||
} | |||
CodeBlocksOS os; | |||
bool createDynamicLibrary = false; | |||
OwnedArray<CodeBlocksTarget> targets; | |||
JUCE_DECLARE_NON_COPYABLE (CodeBlocksProjectExporter) | |||
}; |
@@ -24,7 +24,243 @@ | |||
class MakefileProjectExporter : public ProjectExporter | |||
{ | |||
protected: | |||
//============================================================================== | |||
class MakeBuildConfiguration : public BuildConfiguration | |||
{ | |||
public: | |||
MakeBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e) | |||
: BuildConfiguration (p, settings, e) | |||
{ | |||
} | |||
Value getArchitectureType() { return getValue (Ids::linuxArchitecture); } | |||
var getArchitectureTypeVar() const { return config [Ids::linuxArchitecture]; } | |||
var getDefaultOptimisationLevel() const override { return var ((int) (isDebug() ? gccO0 : gccO3)); } | |||
void createConfigProperties (PropertyListBuilder& props) override | |||
{ | |||
addGCCOptimisationProperty (props); | |||
static const char* const archNames[] = { "(Default)", "<None>", "32-bit (-m32)", "64-bit (-m64)", "ARM v6", "ARM v7" }; | |||
const var archFlags[] = { var(), var (String()), "-m32", "-m64", "-march=armv6", "-march=armv7" }; | |||
props.add (new ChoicePropertyComponent (getArchitectureType(), "Architecture", | |||
StringArray (archNames, numElementsInArray (archNames)), | |||
Array<var> (archFlags, numElementsInArray (archFlags)))); | |||
} | |||
String getLibrarySubdirPath () const override | |||
{ | |||
const String archFlag = getArchitectureTypeVar(); | |||
const auto prefix = String ("-march="); | |||
if (archFlag.startsWith (prefix)) | |||
return archFlag.substring (prefix.length()); | |||
else if (archFlag == "-m64") | |||
return "x86_64"; | |||
else if (archFlag == "-m32") | |||
return "i386"; | |||
else | |||
return "$(shell uname -m)"; | |||
} | |||
}; | |||
BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override | |||
{ | |||
return new MakeBuildConfiguration (project, tree, *this); | |||
} | |||
public: | |||
//============================================================================== | |||
class MakefileTarget : public ProjectType::Target | |||
{ | |||
public: | |||
MakefileTarget (ProjectType::Target::Type targetType, const MakefileProjectExporter& exporter) | |||
: ProjectType::Target (targetType), owner (exporter) | |||
{} | |||
StringArray getTargetSettings (const BuildConfiguration& config) const | |||
{ | |||
if (type == AggregateTarget) | |||
// the aggregate target should not specify any settings at all! | |||
// it just defines dependencies on the other targets. | |||
return StringArray(); | |||
StringPairArray commonOptions = owner.getAllPreprocessorDefs (config, ProjectType::Target::unspecified); | |||
StringPairArray targetSpecific = owner.getAllPreprocessorDefs (config, type); | |||
StringArray defs; | |||
// remove any defines that have already been added by the configuration | |||
const int n = targetSpecific.size(); | |||
for (int i = 0 ; i < n; ++i) | |||
{ | |||
const String& key = targetSpecific.getAllKeys()[i]; | |||
if (! commonOptions.getAllKeys().contains (key)) | |||
defs.add (String ("-D") + key + String ("=") + targetSpecific.getAllValues()[i]); | |||
} | |||
StringArray s; | |||
const String cppflagsVarName = String ("JUCE_CPPFLAGS_") + getTargetVarName(); | |||
s.add (cppflagsVarName + String (" := ") + defs.joinIntoString (" ")); | |||
if (getTargetFileType() == sharedLibraryOrDLL || getTargetFileType() == pluginBundle) | |||
{ | |||
s.add (String ("JUCE_CFLAGS_") + getTargetVarName() + String (" := -fPIC")); | |||
const String ldflagsVarName = String ("JUCE_LDFLAGS_") + getTargetVarName(); | |||
String targetLinkOptions = ldflagsVarName + String (" := -shared"); | |||
if (getTargetFileType() == pluginBundle) | |||
targetLinkOptions += " -Wl,--no-undefined"; | |||
s.add (targetLinkOptions); | |||
} | |||
String targetName (owner.replacePreprocessorTokens (config, config.getTargetBinaryNameString())); | |||
if (owner.projectType.isStaticLibrary() || owner.projectType.isDynamicLibrary()) | |||
targetName = getLibbedFilename (targetName); | |||
else | |||
targetName = targetName.upToLastOccurrenceOf (".", false, false) + getTargetFileSuffix(); | |||
s.add (String ("JUCE_TARGET_") + getTargetVarName() + String (" := ") + escapeSpaces (targetName)); | |||
return s; | |||
} | |||
String getTargetFileSuffix() const | |||
{ | |||
switch (type) | |||
{ | |||
case VSTPlugIn: | |||
return ".so"; | |||
case VST3PlugIn: | |||
return ".vst3"; | |||
case SharedCodeTarget: | |||
return ".a"; | |||
default: | |||
break; | |||
} | |||
return String(); | |||
} | |||
String getTargetVarName() const | |||
{ | |||
return String (getName()).toUpperCase().replaceCharacter (L' ', L'_'); | |||
} | |||
void writeObjects (OutputStream& out) const | |||
{ | |||
Array<RelativePath> targetFiles; | |||
for (int i = 0; i < owner.getAllGroups().size(); ++i) | |||
findAllFilesToCompile (owner.getAllGroups().getReference(i), targetFiles); | |||
out << "OBJECTS_" + getTargetVarName() + String (" := \\") << newLine; | |||
for (int i = 0; i < targetFiles.size(); ++i) | |||
out << " $(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor (targetFiles.getReference(i))) << " \\" << newLine; | |||
out << newLine; | |||
} | |||
void findAllFilesToCompile (const Project::Item& projectItem, Array<RelativePath>& results) const | |||
{ | |||
if (projectItem.isGroup()) | |||
{ | |||
for (int i = 0; i < projectItem.getNumChildren(); ++i) | |||
findAllFilesToCompile (projectItem.getChild(i), results); | |||
} | |||
else | |||
{ | |||
if (projectItem.shouldBeCompiled()) | |||
{ | |||
const Type targetType = (owner.getProject().getProjectType().isAudioPlugin() ? type : SharedCodeTarget); | |||
const File f = projectItem.getFile(); | |||
RelativePath relativePath (f, owner.getTargetFolder(), RelativePath::buildTargetFolder); | |||
if (owner.shouldFileBeCompiledByDefault (relativePath) | |||
&& owner.getProject().getTargetTypeFromFilePath (f, true) == targetType) | |||
results.add (relativePath); | |||
} | |||
} | |||
} | |||
void addFiles (OutputStream& out) | |||
{ | |||
Array<RelativePath> targetFiles; | |||
for (int i = 0; i < owner.getAllGroups().size(); ++i) | |||
findAllFilesToCompile (owner.getAllGroups().getReference(i), targetFiles); | |||
const String cppflagsVarName = String ("JUCE_CPPFLAGS_") + getTargetVarName(); | |||
const String cflagsVarName = String ("JUCE_CFLAGS_") + getTargetVarName(); | |||
for (int i = 0; i < targetFiles.size(); ++i) | |||
{ | |||
jassert (targetFiles.getReference(i).getRoot() == RelativePath::buildTargetFolder); | |||
out << "$(JUCE_OBJDIR)/" << escapeSpaces (owner.getObjectFileFor (targetFiles.getReference(i))) | |||
<< ": " << escapeSpaces (targetFiles.getReference(i).toUnixStyle()) << newLine | |||
<< "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)" << newLine | |||
<< "\t@echo \"Compiling " << targetFiles.getReference(i).getFileName() << "\"" << newLine | |||
<< (targetFiles.getReference(i).hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS)" : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ") | |||
<< "$(" << cppflagsVarName << ") $(" << cflagsVarName << ") -o \"$@\" -c \"$<\"" | |||
<< newLine << newLine; | |||
} | |||
} | |||
String getBuildProduct() const | |||
{ | |||
return String ("$(JUCE_OUTDIR)/$(JUCE_TARGET_") + getTargetVarName() + String (")"); | |||
} | |||
void writeTargetLine (OutputStream& out, const bool useLinuxPackages) | |||
{ | |||
jassert (type != AggregateTarget); | |||
out << getBuildProduct() << " : " | |||
<< ((useLinuxPackages) ? "check-pkg-config " : "") | |||
<< "$(OBJECTS_" << getTargetVarName() << ") $(RESOURCES)"; | |||
if (type != SharedCodeTarget && owner.shouldBuildTargetType (SharedCodeTarget)) | |||
out << " $(JUCE_OUTDIR)/$(JUCE_TARGET_SHARED_CODE)"; | |||
out << newLine << "\t@echo Linking \"" << owner.projectName << " (" << getName() << ")\"" << newLine | |||
<< "\t-$(V_AT)mkdir -p $(JUCE_BINDIR)" << newLine | |||
<< "\t-$(V_AT)mkdir -p $(JUCE_LIBDIR)" << newLine | |||
<< "\t-$(V_AT)mkdir -p $(JUCE_OUTDIR)" << newLine; | |||
if (owner.projectType.isStaticLibrary() || type == SharedCodeTarget) | |||
out << "\t$(V_AT)$(AR) -rcs " << getBuildProduct() | |||
<< " $(OBJECTS_" << getTargetVarName() << ")" << newLine; | |||
else | |||
{ | |||
out << "\t$(V_AT)$(CXX) -o " << getBuildProduct() | |||
<< " $(OBJECTS_" << getTargetVarName() << ") "; | |||
if (owner.shouldBuildTargetType (SharedCodeTarget)) | |||
out << "$(JUCE_OUTDIR)/$(JUCE_TARGET_SHARED_CODE) "; | |||
out << "$(JUCE_LDFLAGS) "; | |||
if (getTargetFileType() == sharedLibraryOrDLL || getTargetFileType() == pluginBundle) | |||
out << "$(JUCE_LDFLAGS_" << getTargetVarName() << ") "; | |||
out << "$(RESOURCES) $(TARGET_ARCH)" << newLine; | |||
} | |||
out << newLine; | |||
} | |||
const MakefileProjectExporter& owner; | |||
}; | |||
//============================================================================== | |||
static const char* getNameLinux() { return "Linux Makefile"; } | |||
static const char* getValueTreeTypeName() { return "LINUX_MAKE"; } | |||
@@ -72,13 +308,25 @@ public: | |||
bool isOSX() const override { return false; } | |||
bool isiOS() const override { return false; } | |||
bool supportsVST() const override { return true; } | |||
bool supportsVST3() const override { return false; } | |||
bool supportsAAX() const override { return false; } | |||
bool supportsRTAS() const override { return false; } | |||
bool supportsAU() const override { return false; } | |||
bool supportsAUv3() const override { return false; } | |||
bool supportsStandalone() const override { return false; } | |||
bool supportsTargetType (ProjectType::Target::Type type) const override | |||
{ | |||
switch (type) | |||
{ | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::ConsoleApp: | |||
case ProjectType::Target::StaticLibrary: | |||
case ProjectType::Target::SharedCodeTarget: | |||
case ProjectType::Target::AggregateTarget: | |||
case ProjectType::Target::VSTPlugIn: | |||
case ProjectType::Target::StandalonePlugIn: | |||
case ProjectType::Target::DynamicLibrary: | |||
return true; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
Value getCppStandardValue() { return getSetting (Ids::cppLanguageStandard); } | |||
String getCppStandardString() const { return settings[Ids::cppLanguageStandard]; } | |||
@@ -99,81 +347,49 @@ public: | |||
} | |||
//============================================================================== | |||
void create (const OwnedArray<LibraryModule>&) const override | |||
bool anyTargetIsSharedLibrary() const | |||
{ | |||
Array<RelativePath> files; | |||
for (int i = 0; i < getAllGroups().size(); ++i) | |||
findAllFilesToCompile (getAllGroups().getReference(i), files); | |||
MemoryOutputStream mo; | |||
writeMakefile (mo, files); | |||
const int n = targets.size(); | |||
for (int i = 0; i < n; ++i) | |||
{ | |||
const ProjectType::Target::TargetFileType fileType = targets.getUnchecked (i)->getTargetFileType(); | |||
if (fileType == ProjectType::Target::sharedLibraryOrDLL || fileType == ProjectType::Target::pluginBundle) | |||
return true; | |||
} | |||
overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("Makefile"), mo); | |||
return false; | |||
} | |||
//============================================================================== | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType& type) override | |||
void create (const OwnedArray<LibraryModule>&) const override | |||
{ | |||
if (type.isStaticLibrary()) | |||
makefileTargetSuffix = ".a"; | |||
MemoryOutputStream mo; | |||
writeMakefile (mo); | |||
else if (type.isAudioPlugin() || type.isDynamicLibrary()) | |||
{ | |||
makefileIsDLL = true; | |||
if (type.isDynamicLibrary()) | |||
makefileTargetSuffix = ".so"; | |||
} | |||
overwriteFileIfDifferentOrThrow (getTargetFolder().getChildFile ("Makefile"), mo); | |||
} | |||
protected: | |||
//============================================================================== | |||
class MakeBuildConfiguration : public BuildConfiguration | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType&) override | |||
{ | |||
public: | |||
MakeBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e) | |||
: BuildConfiguration (p, settings, e) | |||
{ | |||
} | |||
Value getArchitectureType() { return getValue (Ids::linuxArchitecture); } | |||
var getArchitectureTypeVar() const { return config [Ids::linuxArchitecture]; } | |||
var getDefaultOptimisationLevel() const override { return var ((int) (isDebug() ? gccO0 : gccO3)); } | |||
void createConfigProperties (PropertyListBuilder& props) override | |||
{ | |||
addGCCOptimisationProperty (props); | |||
static const char* const archNames[] = { "(Default)", "<None>", "32-bit (-m32)", "64-bit (-m64)", "ARM v6", "ARM v7" }; | |||
const var archFlags[] = { var(), var (String()), "-m32", "-m64", "-march=armv6", "-march=armv7" }; | |||
props.add (new ChoicePropertyComponent (getArchitectureType(), "Architecture", | |||
StringArray (archNames, numElementsInArray (archNames)), | |||
Array<var> (archFlags, numElementsInArray (archFlags)))); | |||
} | |||
}; | |||
BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override | |||
{ | |||
return new MakeBuildConfiguration (project, tree, *this); | |||
callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) | |||
{ | |||
if (MakefileTarget* target = new MakefileTarget (targetType, *this)) | |||
{ | |||
if (targetType == ProjectType::Target::AggregateTarget) | |||
targets.insert (0, target); | |||
else | |||
targets.add (target); | |||
} | |||
}); | |||
// If you hit this assert, you tried to generate a project for an exporter | |||
// that does not support any of your targets! | |||
jassert (targets.size() > 0); | |||
} | |||
private: | |||
//============================================================================== | |||
void findAllFilesToCompile (const Project::Item& projectItem, Array<RelativePath>& results) const | |||
{ | |||
if (projectItem.isGroup()) | |||
{ | |||
for (int i = 0; i < projectItem.getNumChildren(); ++i) | |||
findAllFilesToCompile (projectItem.getChild(i), results); | |||
} | |||
else | |||
{ | |||
if (projectItem.shouldBeCompiled()) | |||
results.add (RelativePath (projectItem.getFile(), getTargetFolder(), RelativePath::buildTargetFolder)); | |||
} | |||
} | |||
void writeDefineFlags (OutputStream& out, const BuildConfiguration& config) const | |||
{ | |||
StringPairArray defines; | |||
@@ -189,7 +405,7 @@ private: | |||
defines.set ("NDEBUG", "1"); | |||
} | |||
out << createGCCPreprocessorFlags (mergePreprocessorDefs (defines, getAllPreprocessorDefs (config))); | |||
out << createGCCPreprocessorFlags (mergePreprocessorDefs (defines, getAllPreprocessorDefs (config, ProjectType::Target::unspecified))); | |||
} | |||
void writeHeaderPathFlags (OutputStream& out, const BuildConfiguration& config) const | |||
@@ -239,9 +455,6 @@ private: | |||
{ | |||
StringArray flags (makefileExtraLinkerFlags); | |||
if (makefileIsDLL) | |||
flags.add ("-shared"); | |||
if (! config.isDebug()) | |||
flags.add ("-fvisibility=hidden"); | |||
@@ -282,6 +495,36 @@ private: | |||
<< " $(LDFLAGS)" << newLine; | |||
} | |||
void writeTargetLines (OutputStream& out, const bool useLinuxPackages) const | |||
{ | |||
const int n = targets.size(); | |||
for (int i = 0; i < n; ++i) | |||
{ | |||
if (MakefileTarget* target = targets.getUnchecked (i)) | |||
{ | |||
if (target->type == ProjectType::Target::AggregateTarget) | |||
{ | |||
StringArray dependencies; | |||
for (int j = 0; j < n; ++j) | |||
{ | |||
if (i == j) continue; | |||
if (MakefileTarget* dependency = targets.getUnchecked (j)) | |||
{ | |||
if (dependency->type != ProjectType::Target::SharedCodeTarget) | |||
dependencies.add (dependency->getBuildProduct()); | |||
} | |||
} | |||
out << "all : " << dependencies.joinIntoString (" ") << newLine << newLine; | |||
} | |||
else | |||
target->writeTargetLine (out, useLinuxPackages); | |||
} | |||
} | |||
} | |||
void writeConfig (OutputStream& out, const BuildConfiguration& config) const | |||
{ | |||
const String buildDirName ("build"); | |||
@@ -307,14 +550,24 @@ private: | |||
writeCppFlags (out, config); | |||
for (auto target : targets) | |||
{ | |||
StringArray lines = target->getTargetSettings (config); | |||
if (lines.size() > 0) | |||
out << " " << lines.joinIntoString ("\n ") << newLine; | |||
out << newLine; | |||
} | |||
out << " JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH)"; | |||
if (anyTargetIsSharedLibrary()) | |||
out << " -fPIC"; | |||
if (config.isDebug()) | |||
out << " -g -ggdb"; | |||
if (makefileIsDLL) | |||
out << " -fPIC"; | |||
out << " -O" << config.getGCCOptimisationFlag() | |||
<< (" " + replacePreprocessorTokens (config, getExtraCompilerFlagsString())).trimEnd() | |||
<< " $(CFLAGS)" << newLine; | |||
@@ -324,44 +577,19 @@ private: | |||
if (cppStandardToUse.isEmpty()) | |||
cppStandardToUse = "-std=c++11"; | |||
out << " JUCE_CXXFLAGS += $(JUCE_CFLAGS) " | |||
out << " JUCE_CXXFLAGS += $(CXXFLAGS) $(JUCE_CFLAGS) " | |||
<< cppStandardToUse << " $(CXXFLAGS)" << newLine; | |||
writeLinkerFlags (out, config); | |||
out << newLine; | |||
String targetName (replacePreprocessorTokens (config, config.getTargetBinaryNameString())); | |||
if (projectType.isStaticLibrary() || projectType.isDynamicLibrary()) | |||
targetName = getLibbedFilename (targetName); | |||
else | |||
targetName = targetName.upToLastOccurrenceOf (".", false, false) + makefileTargetSuffix; | |||
out << " TARGET := " << escapeSpaces (targetName) << newLine; | |||
if (projectType.isStaticLibrary()) | |||
out << " BLDCMD = $(AR) -rcs $(JUCE_OUTDIR)/$(TARGET) $(OBJECTS)" << newLine; | |||
else | |||
out << " BLDCMD = $(CXX) -o $(JUCE_OUTDIR)/$(TARGET) $(OBJECTS) $(JUCE_LDFLAGS) $(RESOURCES) $(TARGET_ARCH)" << newLine; | |||
out << " CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)" << newLine | |||
<< "endif" << newLine | |||
<< newLine; | |||
} | |||
void writeObjects (OutputStream& out, const Array<RelativePath>& files) const | |||
{ | |||
out << "OBJECTS := \\" << newLine; | |||
for (int i = 0; i < files.size(); ++i) | |||
if (shouldFileBeCompiledByDefault (files.getReference(i))) | |||
out << " $(JUCE_OBJDIR)/" << escapeSpaces (getObjectFileFor (files.getReference(i))) << " \\" << newLine; | |||
out << newLine; | |||
} | |||
void writeMakefile (OutputStream& out, const Array<RelativePath>& files) const | |||
void writeMakefile (OutputStream& out) const | |||
{ | |||
out << "# Automatically generated makefile, created by the Projucer" << newLine | |||
<< "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine | |||
@@ -397,26 +625,22 @@ private: | |||
for (ConstConfigIterator config (*this); config.next();) | |||
writeConfig (out, *config); | |||
writeObjects (out, files); | |||
for (auto target : targets) | |||
target->writeObjects (out); | |||
out << ".PHONY: clean" << newLine | |||
out << ".PHONY: clean all" << newLine | |||
<< newLine; | |||
StringArray packages; | |||
packages.addTokens (getExtraPkgConfigString(), " ", "\"'"); | |||
packages.removeEmptyStrings(); | |||
bool useLinuxPackages = (linuxPackages.size() > 0 || packages.size() > 0); | |||
const bool useLinuxPackages = (linuxPackages.size() > 0 || packages.size() > 0); | |||
out << "$(JUCE_OUTDIR)/$(TARGET): " | |||
<< ((useLinuxPackages) ? "check-pkg-config " : "") | |||
<< "$(OBJECTS) $(RESOURCES)" << newLine | |||
<< "\t@echo Linking " << projectName << newLine | |||
<< "\t-@mkdir -p $(JUCE_BINDIR)" << newLine | |||
<< "\t-@mkdir -p $(JUCE_LIBDIR)" << newLine | |||
<< "\t-@mkdir -p $(JUCE_OUTDIR)" << newLine | |||
<< "\t$(V_AT)$(BLDCMD)" << newLine | |||
<< newLine; | |||
writeTargetLines (out, useLinuxPackages); | |||
for (auto target : targets) | |||
target->addFiles (out); | |||
if (useLinuxPackages) | |||
{ | |||
@@ -442,25 +666,9 @@ private: | |||
out << "strip:" << newLine | |||
<< "\t@echo Stripping " << projectName << newLine | |||
<< "\t-@$(STRIP) --strip-unneeded $(JUCE_OUTDIR)/$(TARGET)" << newLine | |||
<< "\t-$(V_AT)$(STRIP) --strip-unneeded $(JUCE_OUTDIR)/$(TARGET)" << newLine | |||
<< newLine; | |||
for (int i = 0; i < files.size(); ++i) | |||
{ | |||
if (shouldFileBeCompiledByDefault (files.getReference(i))) | |||
{ | |||
jassert (files.getReference(i).getRoot() == RelativePath::buildTargetFolder); | |||
out << "$(JUCE_OBJDIR)/" << escapeSpaces (getObjectFileFor (files.getReference(i))) | |||
<< ": " << escapeSpaces (files.getReference(i).toUnixStyle()) << newLine | |||
<< "\t-@mkdir -p $(JUCE_OBJDIR)" << newLine | |||
<< "\t@echo \"Compiling " << files.getReference(i).getFileName() << "\"" << newLine | |||
<< (files.getReference(i).hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) -o \"$@\" -c \"$<\"" | |||
: "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) -o \"$@\" -c \"$<\"") | |||
<< newLine << newLine; | |||
} | |||
} | |||
out << "-include $(OBJECTS:%.o=%.d)" << newLine; | |||
} | |||
@@ -486,5 +694,7 @@ private: | |||
TargetOS::linux))); | |||
} | |||
OwnedArray<MakefileTarget> targets; | |||
JUCE_DECLARE_NON_COPYABLE (MakefileProjectExporter) | |||
}; |
@@ -127,13 +127,31 @@ public: | |||
bool isOSX() const override { return ! iOS; } | |||
bool isiOS() const override { return iOS; } | |||
bool supportsVST() const override { return ! iOS; } | |||
bool supportsVST3() const override { return ! iOS; } | |||
bool supportsAAX() const override { return ! iOS; } | |||
bool supportsRTAS() const override { return ! iOS; } | |||
bool supportsAU() const override { return ! iOS; } | |||
bool supportsAUv3() const override { return true; } | |||
bool supportsStandalone() const override { return true; } | |||
bool supportsTargetType (ProjectType::Target::Type type) const override | |||
{ | |||
switch (type) | |||
{ | |||
case ProjectType::Target::AudioUnitv3PlugIn: | |||
case ProjectType::Target::StandalonePlugIn: | |||
case ProjectType::Target::GUIApp: | |||
case ProjectType::Target::StaticLibrary: | |||
case ProjectType::Target::SharedCodeTarget: | |||
case ProjectType::Target::AggregateTarget: | |||
return true; | |||
case ProjectType::Target::ConsoleApp: | |||
case ProjectType::Target::VSTPlugIn: | |||
case ProjectType::Target::VST3PlugIn: | |||
case ProjectType::Target::AAXPlugIn: | |||
case ProjectType::Target::RTASPlugIn: | |||
case ProjectType::Target::AudioUnitPlugIn: | |||
case ProjectType::Target::DynamicLibrary: | |||
return ! iOS; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
void createExporterProperties (PropertyListBuilder& props) override | |||
{ | |||
@@ -206,7 +224,8 @@ public: | |||
"You can find this string in the OS X app Keychain Access under \"Certificates\"."); | |||
props.add (new BooleanPropertyComponent (getSetting ("keepCustomXcodeSchemes"), "Keep custom Xcode schemes", "Enabled"), | |||
"Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in various hosts. If disabled, all schemes are replaced by a default set."); | |||
"Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in" | |||
"various hosts. If disabled, all schemes are replaced by a default set."); | |||
} | |||
bool launchProject() override | |||
@@ -231,7 +250,7 @@ public: | |||
void create (const OwnedArray<LibraryModule>&) const override | |||
{ | |||
for (auto& target : targets) | |||
if (target->xcodeCreatePList) | |||
if (target->shouldCreatePList()) | |||
target->infoPlistFile = getTargetFolder().getChildFile (target->getInfoPlistName()); | |||
menuNibFile = getTargetFolder().getChildFile ("RecentFilesMenuTemplate.nib"); | |||
@@ -265,52 +284,18 @@ public: | |||
} | |||
//============================================================================== | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType& type) override | |||
{ | |||
if (type.isGUIApplication()) | |||
targets.add (new Target (Target::GUIApp, *this)); | |||
else if (type.isCommandLineApp()) | |||
targets.add (new Target (Target::ConsoleApp, *this)); | |||
else if (type.isStaticLibrary()) | |||
targets.add (new Target (Target::StaticLibrary, *this)); | |||
else if (type.isDynamicLibrary()) | |||
targets.add (new Target (Target::DynamicLibrary, *this)); | |||
else if (type.isAudioPlugin()) | |||
{ | |||
if (project.shouldBuildVST().getValue() && supportsVST()) | |||
targets.add (new Target (Target::VSTPlugIn, *this)); | |||
if (project.shouldBuildVST3().getValue() && supportsVST3()) | |||
targets.add (new Target (Target::VST3PlugIn, *this)); | |||
if (project.shouldBuildAU().getValue() && supportsAU()) | |||
targets.add (new Target (Target::AudioUnitPlugIn, *this)); | |||
if (project.shouldBuildAUv3().getValue()) | |||
targets.add (new Target (Target::AudioUnitv3PlugIn, *this)); | |||
if (project.shouldBuildAAX().getValue() && supportsAAX()) | |||
targets.add (new Target (Target::AAXPlugIn, *this)); | |||
if (project.shouldBuildStandalone().getValue()) | |||
targets.add (new Target (Target::StandalonePlugIn, *this)); | |||
if (project.shouldBuildRTAS().getValue() && supportsRTAS()) | |||
{ | |||
targets.add (new Target (Target::RTASPlugIn, *this)); | |||
addRTASPluginSettings(); | |||
} | |||
if (targets.size() > 0) | |||
targets.add (new Target (Target::SharedCodeTarget, *this)); | |||
} | |||
if (targets.size() > 1) | |||
targets.insert (0, new Target (Target::AggregateTarget, *this)); | |||
void addPlatformSpecificSettingsForProjectType (const ProjectType&) override | |||
{ | |||
callForAllSupportedTargets ([this] (ProjectType::Target::Type targetType) | |||
{ | |||
if (XCodeTarget* target = new XCodeTarget (targetType, *this)) | |||
{ | |||
if (targetType == ProjectType::Target::AggregateTarget) | |||
targets.insert (0, target); | |||
else | |||
targets.add (target); | |||
} | |||
}); | |||
// If you hit this assert, you tried to generate a project for an exporter | |||
// that does not support any of your targets! | |||
@@ -400,7 +385,9 @@ protected: | |||
osxVersionNames.add ("Use Default"); | |||
versionValues.add (osxVersionDefault); | |||
for (int ver = oldestSDKVersion; ver <= currentSDKVersion; ++ver) | |||
int oldestAllowedSDKVersion = project.shouldBuildAUv3() ? minimumAUv3SDKVersion : oldestSDKVersion; | |||
for (int ver = oldestAllowedSDKVersion; ver <= currentSDKVersion; ++ver) | |||
{ | |||
sdkVersionNames.add (getSDKName (ver)); | |||
osxVersionNames.add (getOSXVersionName (ver)); | |||
@@ -463,27 +450,32 @@ protected: | |||
"Enable this to strip any locally defined symbols resulting in a smaller binary size. Enabling this will also remove any function names from crash logs. Must be disabled for static library projects."); | |||
} | |||
String getLibrarySubdirPath () const override | |||
{ | |||
return "${CURRENT_ARCH}"; | |||
} | |||
private: | |||
//========================================================================== | |||
void addXcodePluginInstallPathProperties (PropertyListBuilder& props) | |||
{ | |||
if (project.shouldBuildVST().getValue()) | |||
if (project.shouldBuildVST()) | |||
props.add (new TextWithDefaultPropertyComponent<String> (vstBinaryLocation, "VST Binary location", 1024), | |||
"The folder in which the compiled VST binary should be placed."); | |||
if (project.shouldBuildVST3().getValue()) | |||
if (project.shouldBuildVST3()) | |||
props.add (new TextWithDefaultPropertyComponent<String> (vst3BinaryLocation, "VST3 Binary location", 1024), | |||
"The folder in which the compiled VST3 binary should be placed."); | |||
if (project.shouldBuildAU().getValue()) | |||
if (project.shouldBuildAU()) | |||
props.add (new TextWithDefaultPropertyComponent<String> (auBinaryLocation, "AU Binary location", 1024), | |||
"The folder in which the compiled AU binary should be placed."); | |||
if (project.shouldBuildRTAS().getValue()) | |||
if (project.shouldBuildRTAS()) | |||
props.add (new TextWithDefaultPropertyComponent<String> (rtasBinaryLocation, "RTAS Binary location", 1024), | |||
"The folder in which the compiled RTAS binary should be placed."); | |||
if (project.shouldBuildAAX().getValue()) | |||
if (project.shouldBuildAAX()) | |||
props.add (new TextWithDefaultPropertyComponent<String> (aaxBinaryLocation, "AAX Binary location", 1024), | |||
"The folder in which the compiled AAX binary should be placed."); | |||
} | |||
@@ -513,40 +505,16 @@ public: | |||
}; | |||
//============================================================================== | |||
struct Target | |||
struct XCodeTarget : ProjectType::Target | |||
{ | |||
enum Type | |||
{ | |||
GUIApp = 0, | |||
ConsoleApp = 1, | |||
StaticLibrary = 2, | |||
DynamicLibrary = 3, | |||
VSTPlugIn = 10, | |||
VST3PlugIn = 11, | |||
AAXPlugIn = 12, | |||
RTASPlugIn = 13, | |||
AudioUnitPlugIn = 14, | |||
AudioUnitv3PlugIn = 15, | |||
StandalonePlugIn = 16, | |||
SharedCodeTarget = 20, // internal | |||
AggregateTarget = 21, | |||
unspecified = 30 | |||
}; | |||
//============================================================================== | |||
Target (Type targetType, const XCodeProjectExporter& exporter) | |||
: type (targetType), | |||
XCodeTarget (ProjectType::Target::Type targetType, const XCodeProjectExporter& exporter) | |||
: ProjectType::Target (targetType), | |||
owner (exporter) | |||
{ | |||
switch (type) | |||
{ | |||
case GUIApp: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = true; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "APPL"; | |||
xcodeBundleSignature = "????"; | |||
xcodeFileType = "wrapper.application"; | |||
@@ -556,9 +524,6 @@ public: | |||
break; | |||
case ConsoleApp: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = true; | |||
xcodeCreatePList = false; | |||
xcodeFileType = "compiled.mach-o.executable"; | |||
xcodeBundleExtension = String(); | |||
xcodeProductType = "com.apple.product-type.tool"; | |||
@@ -566,55 +531,37 @@ public: | |||
break; | |||
case StaticLibrary: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = false; | |||
xcodeFileType = "archive.ar"; | |||
xcodeProductType = "com.apple.product-type.library.static"; | |||
xcodeCopyToProductInstallPathAfterBuild = false; | |||
break; | |||
case DynamicLibrary: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = false; | |||
xcodeFileType = "compiled.mach-o.dylib"; | |||
xcodeProductType = "com.apple.product-type.library.dynamic"; | |||
xcodeBundleExtension = ".dylib"; | |||
xcodeCopyToProductInstallPathAfterBuild = false; | |||
break; | |||
case VSTPlugIn: | |||
xcodeIsBundle = true; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "BNDL"; | |||
xcodeBundleSignature = "????"; | |||
xcodeFileType = "wrapper.cfbundle"; | |||
xcodeBundleExtension = ".vst"; | |||
xcodeProductType = "com.apple.product-type.bundle"; | |||
xcodeCopyToProductInstallPathAfterBuild = true; | |||
break; | |||
case VST3PlugIn: | |||
xcodeIsBundle = true; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "BNDL"; | |||
xcodeBundleSignature = "????"; | |||
xcodeFileType = "wrapper.cfbundle"; | |||
xcodeBundleExtension = ".vst3"; | |||
xcodeProductType = "com.apple.product-type.bundle"; | |||
xcodeCopyToProductInstallPathAfterBuild = true; | |||
break; | |||
case AudioUnitPlugIn: | |||
xcodeIsBundle = true; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "BNDL"; | |||
xcodeBundleSignature = "????"; | |||
xcodeFileType = "wrapper.cfbundle"; | |||
@@ -626,12 +573,8 @@ public: | |||
break; | |||
case StandalonePlugIn: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = true; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "APPL"; | |||
xcodeBundleSignature = "????"; | |||
xcodeCreatePList = true; | |||
xcodeFileType = "wrapper.application"; | |||
xcodeBundleExtension = ".app"; | |||
xcodeProductType = "com.apple.product-type.application"; | |||
@@ -639,9 +582,6 @@ public: | |||
break; | |||
case AudioUnitv3PlugIn: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "XPC!"; | |||
xcodeBundleSignature = "????"; | |||
xcodeFileType = "wrapper.app-extension"; | |||
@@ -654,9 +594,6 @@ public: | |||
break; | |||
case AAXPlugIn: | |||
xcodeIsBundle = true; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "TDMw"; | |||
xcodeBundleSignature = "PTul"; | |||
xcodeFileType = "wrapper.cfbundle"; | |||
@@ -668,9 +605,6 @@ public: | |||
break; | |||
case RTASPlugIn: | |||
xcodeIsBundle = true; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = true; | |||
xcodePackageType = "TDMw"; | |||
xcodeBundleSignature = "PTul"; | |||
xcodeFileType = "wrapper.cfbundle"; | |||
@@ -682,18 +616,12 @@ public: | |||
break; | |||
case SharedCodeTarget: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = false; | |||
xcodeFileType = "archive.ar"; | |||
xcodeProductType = "com.apple.product-type.library.static"; | |||
xcodeCopyToProductInstallPathAfterBuild = false; | |||
break; | |||
case AggregateTarget: | |||
xcodeIsBundle = false; | |||
xcodeIsExecutable = false; | |||
xcodeCreatePList = false; | |||
xcodeCopyToProductInstallPathAfterBuild = false; | |||
break; | |||
@@ -704,40 +632,11 @@ public: | |||
} | |||
} | |||
const char* getName() const noexcept | |||
{ | |||
switch (type) | |||
{ | |||
case GUIApp: return "App"; | |||
case ConsoleApp: return "ConsoleApp"; | |||
case StaticLibrary: return "Static Library"; | |||
case DynamicLibrary: return "Dynamic Library"; | |||
case VSTPlugIn: return "VST"; | |||
case VST3PlugIn: return "VST3"; | |||
case AudioUnitPlugIn: return "AU"; | |||
case StandalonePlugIn: return "AUv3 Standalone"; | |||
case AudioUnitv3PlugIn: return "AUv3 AppExtension"; | |||
case AAXPlugIn: return "AAX"; | |||
case RTASPlugIn: return "RTAS"; | |||
case SharedCodeTarget: return "Shared Code"; | |||
case AggregateTarget: return "All"; | |||
default: return "undefined"; | |||
} | |||
} | |||
String getXCodeSchemeName() const | |||
{ | |||
return owner.projectName + " (" + getName() + ")"; | |||
} | |||
bool shouldBuildVST() const { return owner.supportsVST() && owner.project.shouldBuildVST().getValue() && (type == SharedCodeTarget || type == VSTPlugIn); } | |||
bool shouldBuildVST3() const { return owner.supportsVST3() && owner.project.shouldBuildVST3().getValue() && (type == SharedCodeTarget || type == VST3PlugIn); } | |||
bool shouldBuildAAX() const { return owner.supportsAAX() && owner.project.shouldBuildAAX().getValue() && (type == SharedCodeTarget || type == AAXPlugIn); } | |||
bool shouldBuildRTAS() const { return owner.supportsRTAS() && owner.project.shouldBuildRTAS().getValue() && (type == SharedCodeTarget || type == RTASPlugIn); } | |||
bool shouldBuildAU() const { return owner.supportsAU() && owner.project.shouldBuildAU().getValue() && (type == SharedCodeTarget || type == AudioUnitPlugIn); } | |||
bool shouldBuildAUv3() const { return owner.supportsAUv3() && owner.project.shouldBuildAUv3().getValue() && (type == SharedCodeTarget || type == AudioUnitv3PlugIn); } | |||
bool shouldBuildStandalone() const { return owner.project.shouldBuildStandalone().getValue() && (type == SharedCodeTarget || type == StandalonePlugIn); } | |||
String getID() const | |||
{ | |||
return owner.createID (String ("__target") + getName()); | |||
@@ -751,9 +650,8 @@ public: | |||
String xcodePackageType, xcodeBundleSignature, xcodeBundleExtension; | |||
String xcodeProductType, xcodeFileType; | |||
String xcodeOtherRezFlags, xcodeExcludedFiles64Bit, xcodeBundleIDSubPath; | |||
bool xcodeIsBundle, xcodeCreatePList, xcodeIsExecutable, xcodeCopyToProductInstallPathAfterBuild; | |||
bool xcodeCopyToProductInstallPathAfterBuild; | |||
StringArray xcodeFrameworks, xcodeLibs; | |||
Type type; | |||
Array<XmlElement> xcodeExtraPListEntries; | |||
Array<RelativePath> xcodeExtraLibrariesDebug, xcodeExtraLibrariesRelease; | |||
@@ -874,6 +772,12 @@ public: | |||
return *v; | |||
} | |||
bool shouldCreatePList() const | |||
{ | |||
const ProjectType::Target::TargetFileType fileType = getTargetFileType(); | |||
return (fileType == executable && type != ConsoleApp) || fileType == pluginBundle || fileType == macOSAppex; | |||
} | |||
//============================================================================== | |||
StringArray getTargetSettings (const XcodeBuildConfiguration& config) const | |||
{ | |||
@@ -904,7 +808,7 @@ public: | |||
s.add ("HEADER_SEARCH_PATHS = " + owner.getHeaderSearchPaths (config)); | |||
s.add ("GCC_OPTIMIZATION_LEVEL = " + config.getGCCOptimisationFlag()); | |||
if (xcodeCreatePList) | |||
if (shouldCreatePList()) | |||
s.add ("INFOPLIST_FILE = " + infoPlistFile.getFileName()); | |||
if (config.linkTimeOptimisationEnabled.get()) | |||
@@ -930,7 +834,7 @@ public: | |||
} | |||
} | |||
if (xcodeIsBundle) | |||
if (getTargetFileType() == pluginBundle) | |||
{ | |||
s.add ("LIBRARY_STYLE = Bundle"); | |||
s.add ("WRAPPER_EXTENSION = " + xcodeBundleExtension.substring (1)); | |||
@@ -970,9 +874,7 @@ public: | |||
// if the user doesn't set it, then use the last known version that works well with JUCE | |||
String deploymentTarget = "10.11"; | |||
int oldestAllowedSDKVersion = (type == AudioUnitv3PlugIn || type == StandalonePlugIn) ? minimumAUv3SDKVersion : oldestSDKVersion; | |||
for (int ver = oldestAllowedSDKVersion; ver <= currentSDKVersion; ++ver) | |||
for (int ver = oldestSDKVersion; ver <= currentSDKVersion; ++ver) | |||
{ | |||
if (sdk == getSDKName (ver)) s.add ("SDKROOT = macosx10." + String (ver)); | |||
if (sdkCompat == getSDKName (ver)) deploymentTarget = "10." + String (ver); | |||
@@ -1052,24 +954,10 @@ public: | |||
s.add ("SEPARATE_STRIP = YES"); | |||
} | |||
if (type == Target::SharedCodeTarget) | |||
defines.set ("JUCE_SHARED_CODE", "1"); | |||
if (owner.project.getProjectType().isAudioPlugin() && type == Target::AudioUnitv3PlugIn && owner.isOSX()) | |||
s.add (String ("CODE_SIGN_ENTITLEMENTS = \"") + owner.getEntitlementsFileName() + String ("\"")); | |||
if (owner.project.getProjectType().isAudioPlugin()) | |||
{ | |||
defines.set ("JucePlugin_Build_VST", (shouldBuildVST() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_VST3", (shouldBuildVST3() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_AU", (shouldBuildAU() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_AUv3", (shouldBuildAUv3() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_RTAS", (shouldBuildRTAS() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_AAX", (shouldBuildAAX() ? "1" : "0")); | |||
defines.set ("JucePlugin_Build_Standalone", (shouldBuildStandalone() ? "1" : "0")); | |||
} | |||
defines = mergePreprocessorDefs (defines, owner.getAllPreprocessorDefs (config)); | |||
defines = mergePreprocessorDefs (defines, owner.getAllPreprocessorDefs (config, type)); | |||
StringArray defsList; | |||
@@ -1109,7 +997,7 @@ public: | |||
//============================================================================== | |||
void getLinkerSettings (const BuildConfiguration& config, StringArray& flags, StringArray& librarySearchPaths) const | |||
{ | |||
if (xcodeIsBundle) | |||
if (getTargetFileType() == pluginBundle) | |||
flags.add (owner.isiOS() ? "-bitcode_bundle" : "-bundle"); | |||
const Array<RelativePath>& extraLibs = config.isDebug() ? xcodeExtraLibrariesDebug | |||
@@ -1147,7 +1035,7 @@ public: | |||
//========================================================================== c | |||
void writeInfoPlistFile() const | |||
{ | |||
if (! xcodeCreatePList) | |||
if (! shouldCreatePList()) | |||
return; | |||
ScopedPointer<XmlElement> plist (XmlDocument::parse (owner.getPListToMergeString())); | |||
@@ -1409,7 +1297,7 @@ public: | |||
private: | |||
//============================================================================== | |||
bool xcodeCanUseDwarf; | |||
OwnedArray<Target> targets; | |||
OwnedArray<XCodeTarget> targets; | |||
mutable OwnedArray<ValueTree> pbxBuildFiles, pbxFileReferences, pbxGroups, misc, projectConfigs, targetConfigs; | |||
mutable StringArray resourceIDs, sourceIDs, targetIDs; | |||
@@ -1471,7 +1359,7 @@ private: | |||
{ | |||
for (auto* target : targets) | |||
{ | |||
if (target->type == Target::AggregateTarget) | |||
if (target->type == XCodeTarget::AggregateTarget) | |||
continue; | |||
target->addMainBuildProduct(); | |||
@@ -1495,10 +1383,10 @@ private: | |||
{ | |||
for (auto* target : targets) | |||
{ | |||
if (target->type == Target::AggregateTarget) | |||
if (target->type == XCodeTarget::AggregateTarget) | |||
continue; | |||
if (target->xcodeCreatePList) | |||
if (target->shouldCreatePList()) | |||
{ | |||
RelativePath plistPath (target->infoPlistFile, getTargetFolder(), RelativePath::buildTargetFolder); | |||
addFileReference (plistPath.toUnixStyle()); | |||
@@ -1576,7 +1464,7 @@ private: | |||
// add build phases | |||
for (auto* target : targets) | |||
{ | |||
if (target->type != Target::AggregateTarget) | |||
if (target->type != XCodeTarget::AggregateTarget) | |||
buildProducts.add (createID (String ("__productFileID") + String (target->getName()))); | |||
for (ConstConfigIterator config (*this); config.next();) | |||
@@ -1589,11 +1477,11 @@ private: | |||
target->addShellScriptBuildPhase ("Pre-build script", getPreBuildScript()); | |||
if (target->type != Target::AggregateTarget) | |||
if (target->type != XCodeTarget::AggregateTarget) | |||
{ | |||
// TODO: ideally resources wouldn't be copied into the AUv3 bundle as well. | |||
// However, fixing this requires supporting App groups -> TODO: add app groups | |||
if (! projectType.isStaticLibrary() && target->type != Target::SharedCodeTarget) | |||
if (! projectType.isStaticLibrary() && target->type != XCodeTarget::SharedCodeTarget) | |||
target->addBuildPhase ("PBXResourcesBuildPhase", resourceIDs); | |||
StringArray rezFiles (rezFileIDs); | |||
@@ -1604,20 +1492,20 @@ private: | |||
StringArray sourceFiles (target->sourceIDs); | |||
if (target->type == Target::SharedCodeTarget | |||
if (target->type == XCodeTarget::SharedCodeTarget | |||
|| (! project.getProjectType().isAudioPlugin())) | |||
sourceFiles.addArray (sourceIDs); | |||
target->addBuildPhase ("PBXSourcesBuildPhase", sourceFiles); | |||
if (! projectType.isStaticLibrary() && target->type != Target::SharedCodeTarget) | |||
if (! projectType.isStaticLibrary() && target->type != XCodeTarget::SharedCodeTarget) | |||
target->addBuildPhase ("PBXFrameworksBuildPhase", target->frameworkIDs); | |||
} | |||
target->addShellScriptBuildPhase ("Post-build script", getPostBuildScript()); | |||
if (project.getProjectType().isAudioPlugin() && project.shouldBuildAUv3().getValue() | |||
&& project.shouldBuildStandalone().getValue() && target->type == Target::StandalonePlugIn) | |||
if (project.getProjectType().isAudioPlugin() && project.shouldBuildAUv3() | |||
&& project.shouldBuildStandalonePlugin() && target->type == XCodeTarget::StandalonePlugIn) | |||
embedAppExtension(); | |||
addTargetObject (*target); | |||
@@ -1626,9 +1514,9 @@ private: | |||
void embedAppExtension() const | |||
{ | |||
if (auto* standaloneTarget = getTargetOfType (Target::StandalonePlugIn)) | |||
if (auto* standaloneTarget = getTargetOfType (XCodeTarget::StandalonePlugIn)) | |||
{ | |||
if (auto* auv3Target = getTargetOfType (Target::AudioUnitv3PlugIn)) | |||
if (auto* auv3Target = getTargetOfType (XCodeTarget::AudioUnitv3PlugIn)) | |||
{ | |||
StringArray files; | |||
files.add (auv3Target->mainBuildProductID); | |||
@@ -1662,7 +1550,7 @@ private: | |||
} | |||
//============================================================================== | |||
Target* getTargetOfType (Target::Type type) const | |||
XCodeTarget* getTargetOfType (ProjectType::Target::Type type) const | |||
{ | |||
for (auto& target : targets) | |||
if (target->type == type) | |||
@@ -1671,13 +1559,13 @@ private: | |||
return nullptr; | |||
} | |||
void addTargetObject (Target& target) const | |||
void addTargetObject (XCodeTarget& target) const | |||
{ | |||
String targetName = target.getName(); | |||
String targetID = target.getID(); | |||
ValueTree* const v = new ValueTree (targetID); | |||
v->setProperty ("isa", target.type == Target::AggregateTarget ? "PBXAggregateTarget" : "PBXNativeTarget", nullptr); | |||
v->setProperty ("isa", target.type == XCodeTarget::AggregateTarget ? "PBXAggregateTarget" : "PBXNativeTarget", nullptr); | |||
v->setProperty ("buildConfigurationList", createID (String ("__configList") + targetName), nullptr); | |||
v->setProperty ("buildPhases", indentParenthesisedList (target.buildPhaseIDs), nullptr); | |||
@@ -1687,7 +1575,7 @@ private: | |||
v->setProperty (Ids::name, target.getXCodeSchemeName(), nullptr); | |||
v->setProperty ("productName", projectName, nullptr); | |||
if (target.type != Target::AggregateTarget) | |||
if (target.type != XCodeTarget::AggregateTarget) | |||
{ | |||
v->setProperty ("productReference", createID (String ("__productFileID") + targetName), nullptr); | |||
@@ -1699,28 +1587,28 @@ private: | |||
misc.add (v); | |||
} | |||
StringArray getTargetDependencies (const Target& target) const | |||
StringArray getTargetDependencies (const XCodeTarget& target) const | |||
{ | |||
StringArray dependencies; | |||
if (project.getProjectType().isAudioPlugin()) | |||
{ | |||
if (target.type == Target::StandalonePlugIn) // depends on AUv3 and shared code | |||
if (target.type == XCodeTarget::StandalonePlugIn) // depends on AUv3 and shared code | |||
{ | |||
if (Target* auv3Target = getTargetOfType (Target::AudioUnitv3PlugIn)) | |||
if (XCodeTarget* auv3Target = getTargetOfType (XCodeTarget::AudioUnitv3PlugIn)) | |||
dependencies.add (auv3Target->getDependencyID()); | |||
if (Target* sharedCodeTarget = getTargetOfType (Target::SharedCodeTarget)) | |||
if (XCodeTarget* sharedCodeTarget = getTargetOfType (XCodeTarget::SharedCodeTarget)) | |||
dependencies.add (sharedCodeTarget->getDependencyID()); | |||
} | |||
else if (target.type == Target::AggregateTarget) // depends on all other targets | |||
else if (target.type == XCodeTarget::AggregateTarget) // depends on all other targets | |||
{ | |||
for (int i = 1; i < targets.size(); ++i) | |||
dependencies.add (targets[i]->getDependencyID()); | |||
} | |||
else if (target.type != Target::SharedCodeTarget) // shared code doesn't depend on anything; all other targets depend only on the shared code | |||
else if (target.type != XCodeTarget::SharedCodeTarget) // shared code doesn't depend on anything; all other targets depend only on the shared code | |||
{ | |||
if (Target* sharedCodeTarget = getTargetOfType (Target::SharedCodeTarget)) | |||
if (XCodeTarget* sharedCodeTarget = getTargetOfType (XCodeTarget::SharedCodeTarget)) | |||
dependencies.add (sharedCodeTarget->getDependencyID()); | |||
} | |||
} | |||
@@ -2099,7 +1987,7 @@ private: | |||
output << "\t};\n\trootObject = " << createID ("__root") << ";\n}\n"; | |||
} | |||
String addBuildFile (const String& path, const String& fileRefID, bool addToSourceBuildPhase, bool inhibitWarnings, Target* xcodeTarget = nullptr) const | |||
String addBuildFile (const String& path, const String& fileRefID, bool addToSourceBuildPhase, bool inhibitWarnings, XCodeTarget* xcodeTarget = nullptr) const | |||
{ | |||
String fileID (createID (path + "buildref")); | |||
@@ -2120,7 +2008,7 @@ private: | |||
return fileID; | |||
} | |||
String addBuildFile (const RelativePath& path, bool addToSourceBuildPhase, bool inhibitWarnings, Target* xcodeTarget = nullptr) const | |||
String addBuildFile (const RelativePath& path, bool addToSourceBuildPhase, bool inhibitWarnings, XCodeTarget* xcodeTarget = nullptr) const | |||
{ | |||
return addBuildFile (path.toUnixStyle(), createFileRefID (path), addToSourceBuildPhase, inhibitWarnings, xcodeTarget); | |||
} | |||
@@ -2204,7 +2092,7 @@ private: | |||
} | |||
String addFile (const RelativePath& path, bool shouldBeCompiled, bool shouldBeAddedToBinaryResources, | |||
bool shouldBeAddedToXcodeResources, bool inhibitWarnings, Target* xcodeTarget) const | |||
bool shouldBeAddedToXcodeResources, bool inhibitWarnings, XCodeTarget* xcodeTarget) const | |||
{ | |||
const String pathAsString (path.toUnixStyle()); | |||
const String refID (addFileReference (path.toUnixStyle())); | |||
@@ -2234,7 +2122,7 @@ private: | |||
if (projectItem.isModuleCode()) | |||
{ | |||
if (Target* xcodeTarget = getTargetOfType (getTargetTypeFromFilePath (projectItem.getFile(), false))) | |||
if (XCodeTarget* xcodeTarget = getTargetOfType (getProject().getTargetTypeFromFilePath (projectItem.getFile(), false))) | |||
{ | |||
String rezFileID = addBuildFile (pathAsString, refID, false, false, xcodeTarget); | |||
xcodeTarget->rezFileIDs.add (rezFileID); | |||
@@ -2299,9 +2187,9 @@ private: | |||
if (path.hasFileExtension (".r")) | |||
return addRezFile (projectItem, path); | |||
Target* xcodeTarget = nullptr; | |||
XCodeTarget* xcodeTarget = nullptr; | |||
if (projectItem.isModuleCode() && projectItem.shouldBeCompiled()) | |||
xcodeTarget = getTargetOfType (getTargetTypeFromFilePath (projectItem.getFile(), false)); | |||
xcodeTarget = getTargetOfType (project.getTargetTypeFromFilePath (projectItem.getFile(), false)); | |||
return addFile (path, projectItem.shouldBeCompiled(), | |||
projectItem.shouldBeAddedToBinaryResources(), | |||
@@ -2357,7 +2245,7 @@ private: | |||
projectConfigs.add (v); | |||
} | |||
void addConfigList (Target& target, const OwnedArray<ValueTree>& configsToUse, const String& listID) const | |||
void addConfigList (XCodeTarget& target, const OwnedArray <ValueTree>& configsToUse, const String& listID) const | |||
{ | |||
ValueTree* v = new ValueTree (listID); | |||
v->setProperty ("isa", "XCConfigurationList", nullptr); | |||
@@ -2370,7 +2258,7 @@ private: | |||
misc.add (v); | |||
} | |||
void addProjectConfigList (const OwnedArray<ValueTree>& configsToUse, const String& listID) const | |||
void addProjectConfigList (const OwnedArray <ValueTree>& configsToUse, const String& listID) const | |||
{ | |||
StringArray configIDs; | |||
@@ -2405,19 +2293,6 @@ private: | |||
misc.add (v); | |||
} | |||
static Target::Type getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffic) | |||
{ | |||
if (LibraryModule::CompileUnit::hasSuffix (file, "_AU")) return Target::AudioUnitPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_AUv3")) return Target::AudioUnitv3PlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_AAX")) return Target::AAXPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_RTAS")) return Target::RTASPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST2")) return Target::VSTPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST3")) return Target::VST3PlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_Standalone")) return Target::StandalonePlugIn; | |||
return (returnSharedTargetIfNoValidSuffic ? Target::SharedCodeTarget : Target::unspecified); | |||
} | |||
//============================================================================== | |||
void removeMismatchedXcuserdata() const | |||
{ | |||
@@ -173,15 +173,11 @@ bool ProjectExporter::canProjectBeLaunched (Project* project) | |||
//============================================================================== | |||
ProjectExporter::ProjectExporter (Project& p, const ValueTree& state) | |||
: makefileIsDLL (false), | |||
msvcIsDLL (false), | |||
msvcIsWindowsSubsystem (true), | |||
settings (state), | |||
: settings (state), | |||
project (p), | |||
projectType (p.getProjectType()), | |||
projectName (p.getTitle()), | |||
projectFolder (p.getProjectFolder()), | |||
modulesGroup (nullptr) | |||
projectFolder (p.getProjectFolder()) | |||
{ | |||
} | |||
@@ -242,19 +238,19 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props) | |||
void ProjectExporter::createDependencyPathProperties (PropertyListBuilder& props) | |||
{ | |||
if (supportsVST3() && (project.shouldBuildVST3().getValue() || project.isVST3PluginHost())) | |||
if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) || project.isVST3PluginHost()) | |||
{ | |||
props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getVST3PathValue(), "VST3 SDK Folder"), | |||
"If you're building a VST3 plugin or host, this must be the folder containing the VST3 SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
} | |||
if (supportsAAX() && project.shouldBuildAAX().getValue()) | |||
if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn) && project.shouldBuildAAX()) | |||
{ | |||
props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getAAXPathValue(), "AAX SDK Folder"), | |||
"If you're building an AAX plugin, this must be the folder containing the AAX SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
} | |||
if (supportsRTAS() && project.shouldBuildRTAS().getValue()) | |||
if (shouldBuildTargetType (ProjectType::Target::RTASPlugIn) && project.shouldBuildRTAS()) | |||
{ | |||
props.add (new DependencyPathPropertyComponent (project.getFile().getParentDirectory(), getRTASPathValue(), "RTAS SDK Folder"), | |||
"If you're building an RTAS, this must be the folder containing the RTAS SDK. This can be an absolute path, or a path relative to the Projucer project file."); | |||
@@ -300,25 +296,17 @@ void ProjectExporter::addSettingsForProjectType (const ProjectType& type) | |||
void ProjectExporter::addVSTPathsIfPluginOrHost() | |||
{ | |||
if (supportsVST() && project.shouldBuildVST().getValue()) | |||
makefileTargetSuffix = ".so"; | |||
if (supportsVST3()) | |||
{ | |||
if (project.shouldBuildVST3().getValue()) | |||
makefileTargetSuffix = ".so"; | |||
if (project.shouldBuildVST3().getValue() || project.isVST3PluginHost()) | |||
addVST3FolderToPath(); | |||
} | |||
if (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) || project.isVST3PluginHost()) | |||
addVST3FolderToPath(); | |||
} | |||
void ProjectExporter::addCommonAudioPluginSettings() | |||
{ | |||
if (isLinux() && (getProject().shouldBuildVST().getValue() || getProject().shouldBuildVST3().getValue())) | |||
if (isLinux() | |||
&& (shouldBuildTargetType (ProjectType::Target::VSTPlugIn) || shouldBuildTargetType (ProjectType::Target::VST3PlugIn))) | |||
makefileExtraLinkerFlags.add ("-Wl,--no-undefined"); | |||
if (supportsAAX() && getProject().shouldBuildAAX().getValue()) | |||
if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn)) | |||
addAAXFoldersToPath(); | |||
// Note: RTAS paths are platform-dependent, impl -> addPlatformSpecificSettingsForProjectType | |||
@@ -347,11 +335,13 @@ void ProjectExporter::addAAXFoldersToPath() | |||
} | |||
//============================================================================== | |||
StringPairArray ProjectExporter::getAllPreprocessorDefs (const ProjectExporter::BuildConfiguration& config) const | |||
StringPairArray ProjectExporter::getAllPreprocessorDefs (const BuildConfiguration& config, const ProjectType::Target::Type targetType) const | |||
{ | |||
StringPairArray defs (mergePreprocessorDefs (config.getAllPreprocessorDefs(), | |||
parsePreprocessorDefs (getExporterPreprocessorDefsString()))); | |||
addDefaultPreprocessorDefs (defs); | |||
addTargetSpecificPreprocessorDefs (defs, targetType); | |||
return defs; | |||
} | |||
@@ -363,6 +353,31 @@ StringPairArray ProjectExporter::getAllPreprocessorDefs() const | |||
return defs; | |||
} | |||
void ProjectExporter::addTargetSpecificPreprocessorDefs (StringPairArray& defs, const ProjectType::Target::Type targetType) const | |||
{ | |||
if (targetType == ProjectType::Target::SharedCodeTarget) | |||
{ | |||
defs.set ("JucePlugin_Build_VST", (shouldBuildTargetType (ProjectType::Target::VSTPlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_VST3", (shouldBuildTargetType (ProjectType::Target::VST3PlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AU", (shouldBuildTargetType (ProjectType::Target::AudioUnitPlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AUv3", (shouldBuildTargetType (ProjectType::Target::AudioUnitv3PlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_RTAS", (shouldBuildTargetType (ProjectType::Target::RTASPlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AAX", (shouldBuildTargetType (ProjectType::Target::AAXPlugIn) ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_Standalone", (shouldBuildTargetType (ProjectType::Target::StandalonePlugIn) ? "1" : "0")); | |||
defs.set ("JUCE_SHARED_CODE", "1"); | |||
} | |||
else if (targetType != ProjectType::Target::unspecified) | |||
{ | |||
defs.set ("JucePlugin_Build_VST", (targetType == ProjectType::Target::VSTPlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_VST3", (targetType == ProjectType::Target::VST3PlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AU", (targetType == ProjectType::Target::AudioUnitPlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AUv3", (targetType == ProjectType::Target::AudioUnitv3PlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_RTAS", (targetType == ProjectType::Target::RTASPlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_AAX", (targetType == ProjectType::Target::AAXPlugIn ? "1" : "0")); | |||
defs.set ("JucePlugin_Build_Standalone", (targetType == ProjectType::Target::StandalonePlugIn ? "1" : "0")); | |||
} | |||
} | |||
void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const | |||
{ | |||
defs.set (getExporterIdentifierMacro(), "1"); | |||
@@ -370,9 +385,10 @@ void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const | |||
defs.set ("JUCE_APP_VERSION_HEX", project.getVersionAsHex()); | |||
} | |||
String ProjectExporter::replacePreprocessorTokens (const ProjectExporter::BuildConfiguration& config, const String& sourceString) const | |||
String ProjectExporter::replacePreprocessorTokens (const ProjectExporter::BuildConfiguration& config, | |||
const String& sourceString) const | |||
{ | |||
return replacePreprocessorDefs (getAllPreprocessorDefs (config), sourceString); | |||
return replacePreprocessorDefs (getAllPreprocessorDefs (config, ProjectType::Target::unspecified), sourceString); | |||
} | |||
void ProjectExporter::copyMainGroupFromProject() | |||
@@ -393,14 +409,24 @@ Project::Item& ProjectExporter::getModulesGroup() | |||
return *modulesGroup; | |||
} | |||
void ProjectExporter::addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index) | |||
void ProjectExporter::addProjectPathToBuildPathList (StringArray& pathList, const RelativePath& pathFromProjectFolder, int index) | |||
{ | |||
RelativePath localPath (rebaseFromProjectFolderToBuildTarget (pathFromProjectFolder)); | |||
const auto localPath = RelativePath (rebaseFromProjectFolderToBuildTarget (pathFromProjectFolder)); | |||
const auto path = isVisualStudio() ? localPath.toWindowsStyle() : localPath.toUnixStyle(); | |||
const String path (isVisualStudio() ? localPath.toWindowsStyle() : localPath.toUnixStyle()); | |||
if (! pathList.contains (path)) | |||
pathList.insert (index, path); | |||
} | |||
if (! extraSearchPaths.contains (path)) | |||
extraSearchPaths.insert (index, path); | |||
void ProjectExporter::addToModuleLibPaths (const RelativePath& pathFromProjectFolder) | |||
{ | |||
addProjectPathToBuildPathList (moduleLibSearchPaths, pathFromProjectFolder); | |||
} | |||
void ProjectExporter::addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index) | |||
{ | |||
addProjectPathToBuildPathList (extraSearchPaths, pathFromProjectFolder, index); | |||
} | |||
Value ProjectExporter::getPathForModuleValue (const String& moduleID) | |||
@@ -810,16 +836,24 @@ StringArray ProjectExporter::BuildConfiguration::getHeaderSearchPaths() const | |||
StringArray ProjectExporter::BuildConfiguration::getLibrarySearchPaths() const | |||
{ | |||
return getSearchPathsFromString (getLibrarySearchPathString()); | |||
auto separator = exporter.isVisualStudio() ? "\\" : "/"; | |||
auto s = getSearchPathsFromString (getLibrarySearchPathString()); | |||
for (auto path : exporter.moduleLibSearchPaths) | |||
s.add (path + separator + getLibrarySubdirPath()); | |||
return s; | |||
} | |||
String ProjectExporter::BuildConfiguration::getGCCLibraryPathFlags() const | |||
{ | |||
String s; | |||
const StringArray libraryPaths (getLibrarySearchPaths()); | |||
const auto libraryPaths = getSearchPathsFromString (getLibrarySearchPathString()); | |||
for (auto path : libraryPaths) | |||
s << " -L" << escapeSpaces (path).replace ("~", "$(HOME)"); | |||
for (int i = 0; i < libraryPaths.size(); ++i) | |||
s << " -L" << escapeSpaces (libraryPaths[i]).replace ("~", "$(HOME)"); | |||
for (auto path : exporter.moduleLibSearchPaths) | |||
s << " -L" << escapeSpaces (path).replace ("~", "$(HOME)") << "/" << getLibrarySubdirPath(); | |||
return s; | |||
} | |||
@@ -84,14 +84,21 @@ public: | |||
virtual bool isOSX() const = 0; | |||
virtual bool isiOS() const = 0; | |||
//============================================================================== | |||
// cross-platform audio plug-ins supported by exporter | |||
virtual bool supportsVST() const = 0; | |||
virtual bool supportsVST3() const = 0; | |||
virtual bool supportsAAX() const = 0; | |||
virtual bool supportsRTAS() const = 0; | |||
virtual bool supportsAU() const = 0; | |||
virtual bool supportsAUv3() const = 0; | |||
virtual bool supportsStandalone() const = 0; // as in Standalong plug-in type, not GUIApp or ConsoleApp | |||
virtual bool supportsTargetType (ProjectType::Target::Type type) const = 0; | |||
inline bool shouldBuildTargetType (ProjectType::Target::Type type) const | |||
{ | |||
return project.shouldBuildTargetType (type) && supportsTargetType (type); | |||
} | |||
inline void callForAllSupportedTargets (std::function<void (ProjectType::Target::Type)> callback) | |||
{ | |||
for (int i = 0; i < ProjectType::Target::unspecified; ++i) | |||
if (shouldBuildTargetType (static_cast<ProjectType::Target::Type> (i))) | |||
callback (static_cast<ProjectType::Target::Type> (i)); | |||
} | |||
//============================================================================== | |||
bool mayCompileOnCurrentOS() const | |||
@@ -150,6 +157,7 @@ public: | |||
RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const; | |||
void addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index = -1); | |||
void addToModuleLibPaths (const RelativePath& pathFromProjectFolder); | |||
Value getBigIconImageItemID() { return getSetting (Ids::bigIcon); } | |||
Value getSmallIconImageItemID() { return getSetting (Ids::smallIcon); } | |||
@@ -187,19 +195,16 @@ public: | |||
Project::Item& getModulesGroup(); | |||
//============================================================================== | |||
String makefileTargetSuffix; | |||
bool makefileIsDLL; | |||
StringArray linuxLibs, linuxPackages, makefileExtraLinkerFlags; | |||
//============================================================================== | |||
String msvcTargetSuffix; | |||
StringPairArray msvcExtraPreprocessorDefs; | |||
bool msvcIsDLL, msvcIsWindowsSubsystem; | |||
String msvcDelayLoadedDLLs; | |||
StringArray mingwLibs; | |||
StringArray mingwLibs, windowsLibs; | |||
//============================================================================== | |||
StringArray extraSearchPaths; | |||
StringArray moduleLibSearchPaths; | |||
//============================================================================== | |||
class BuildConfiguration : public ReferenceCountedObject | |||
@@ -213,6 +218,8 @@ public: | |||
//============================================================================== | |||
virtual void createConfigProperties (PropertyListBuilder&) = 0; | |||
virtual var getDefaultOptimisationLevel() const = 0; | |||
virtual String getLibrarySubdirPath() const { return String(); } | |||
//============================================================================== | |||
Value getNameValue() { return getValue (Ids::name); } | |||
@@ -316,10 +323,12 @@ public: | |||
String getExporterPreprocessorDefsString() const { return getSettingString (Ids::extraDefs); } | |||
// includes exporter, project + config defs | |||
StringPairArray getAllPreprocessorDefs (const BuildConfiguration& config) const; | |||
StringPairArray getAllPreprocessorDefs (const BuildConfiguration& config, const ProjectType::Target::Type targetType) const; | |||
// includes exporter + project defs.. | |||
StringPairArray getAllPreprocessorDefs() const; | |||
void addTargetSpecificPreprocessorDefs (StringPairArray& defs, const ProjectType::Target::Type targetType) const; | |||
String replacePreprocessorTokens (const BuildConfiguration&, const String& sourceString) const; | |||
ValueTree settings; | |||
@@ -345,7 +354,7 @@ protected: | |||
mutable Array<Project::Item> itemGroups; | |||
void initItemGroups() const; | |||
Project::Item* modulesGroup; | |||
Project::Item* modulesGroup = nullptr; | |||
virtual BuildConfiguration::Ptr createBuildConfig (const ValueTree&) const = 0; | |||
@@ -408,6 +417,7 @@ private: | |||
void addCommonAudioPluginSettings(); | |||
void addVST3FolderToPath(); | |||
void addAAXFoldersToPath(); | |||
void addProjectPathToBuildPathList (StringArray&, const RelativePath&, int index = -1); | |||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter) | |||
}; | |||
@@ -73,13 +73,13 @@ namespace | |||
void ProjectSaver::writePluginCharacteristicsFile() | |||
{ | |||
StringPairArray flags; | |||
flags.set ("JucePlugin_Build_VST", valueToBool (project.shouldBuildVST())); | |||
flags.set ("JucePlugin_Build_VST3", valueToBool (project.shouldBuildVST3())); | |||
flags.set ("JucePlugin_Build_AU", valueToBool (project.shouldBuildAU())); | |||
flags.set ("JucePlugin_Build_AUv3", valueToBool (project.shouldBuildAUv3())); | |||
flags.set ("JucePlugin_Build_RTAS", valueToBool (project.shouldBuildRTAS())); | |||
flags.set ("JucePlugin_Build_AAX", valueToBool (project.shouldBuildAAX())); | |||
flags.set ("JucePlugin_Build_STANDALONE", valueToBool (project.shouldBuildStandalone())); | |||
flags.set ("JucePlugin_Build_VST", valueToBool (project.getShouldBuildVSTAsValue())); | |||
flags.set ("JucePlugin_Build_VST3", valueToBool (project.getShouldBuildVST3AsValue())); | |||
flags.set ("JucePlugin_Build_AU", valueToBool (project.getShouldBuildAUAsValue())); | |||
flags.set ("JucePlugin_Build_AUv3", valueToBool (project.getShouldBuildAUv3AsValue())); | |||
flags.set ("JucePlugin_Build_RTAS", valueToBool (project.getShouldBuildRTASAsValue())); | |||
flags.set ("JucePlugin_Build_AAX", valueToBool (project.getShouldBuildAAXAsValue())); | |||
flags.set ("JucePlugin_Build_STANDALONE", valueToBool (project.getShouldBuildStandalonePluginAsValue())); | |||
flags.set ("JucePlugin_Name", valueToStringLiteral (project.getPluginName())); | |||
flags.set ("JucePlugin_Desc", valueToStringLiteral (project.getPluginDesc())); | |||
flags.set ("JucePlugin_Manufacturer", valueToStringLiteral (project.getPluginManufacturer())); | |||
@@ -303,21 +303,34 @@ static void parseAndAddLibs (StringArray& libList, const String& libs) | |||
void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, ProjectSaver& projectSaver) const | |||
{ | |||
Project& project = exporter.getProject(); | |||
auto& project = exporter.getProject(); | |||
RelativePath modulePath = exporter.getModuleFolderRelativeToProject (getID()); | |||
const auto moduleRelativePath = exporter.getModuleFolderRelativeToProject (getID()); | |||
exporter.addToExtraSearchPaths (modulePath.getParentDirectory()); | |||
exporter.addToExtraSearchPaths (moduleRelativePath.getParentDirectory()); | |||
const String extraInternalSearchPaths (moduleInfo.getExtraSearchPaths().trim()); | |||
String libDirPlatform; | |||
if (exporter.isLinux()) | |||
libDirPlatform = "Linux"; | |||
else if (exporter.isCodeBlocks() && exporter.isWindows()) | |||
libDirPlatform = "MinGW"; | |||
else | |||
libDirPlatform = exporter.getTargetFolder().getFileName(); | |||
const auto libSubdirPath = String (moduleRelativePath.toUnixStyle() + "/libs/") + libDirPlatform; | |||
const auto moduleLibDir = File (project.getProjectFolder().getFullPathName() + "/" + libSubdirPath); | |||
if (moduleLibDir.exists()) | |||
exporter.addToModuleLibPaths (RelativePath (libSubdirPath, moduleRelativePath.getRoot())); | |||
const auto extraInternalSearchPaths = moduleInfo.getExtraSearchPaths().trim(); | |||
if (extraInternalSearchPaths.isNotEmpty()) | |||
{ | |||
StringArray paths; | |||
paths.addTokens (extraInternalSearchPaths, true); | |||
for (int i = 0; i < paths.size(); ++i) | |||
exporter.addToExtraSearchPaths (modulePath.getChildFile (paths.getReference(i))); | |||
exporter.addToExtraSearchPaths (moduleRelativePath.getChildFile (paths.getReference(i))); | |||
} | |||
{ | |||
@@ -357,9 +370,12 @@ void LibraryModule::addSettingsForModuleToExporter (ProjectExporter& exporter, P | |||
parseAndAddLibs (exporter.linuxLibs, moduleInfo.moduleInfo ["linuxLibs"].toString()); | |||
parseAndAddLibs (exporter.linuxPackages, moduleInfo.moduleInfo ["linuxPackages"].toString()); | |||
} | |||
else if (exporter.isCodeBlocks() && exporter.isWindows()) | |||
else if (exporter.isWindows()) | |||
{ | |||
parseAndAddLibs (exporter.mingwLibs, moduleInfo.moduleInfo ["mingwLibs"].toString()); | |||
if (exporter.isCodeBlocks()) | |||
parseAndAddLibs (exporter.mingwLibs, moduleInfo.moduleInfo ["mingwLibs"].toString()); | |||
else | |||
parseAndAddLibs (exporter.windowsLibs, moduleInfo.moduleInfo ["windowsLibs"].toString()); | |||
} | |||
} | |||
@@ -424,20 +440,15 @@ void LibraryModule::CompileUnit::writeInclude (MemoryOutputStream&) const | |||
bool LibraryModule::CompileUnit::isNeededForExporter (ProjectExporter& exporter) const | |||
{ | |||
Project& project = exporter.getProject(); | |||
if ((hasSuffix (file, "_OSX") && ! exporter.isOSX()) | |||
|| (hasSuffix (file, "_iOS") && ! exporter.isiOS()) | |||
|| (hasSuffix (file, "_Windows") && ! exporter.isWindows()) | |||
|| (hasSuffix (file, "_Linux") && ! exporter.isLinux()) | |||
|| (hasSuffix (file, "_Android") && ! exporter.isAndroid()) | |||
|| (hasSuffix (file, "_AU") && ! (project.shouldBuildAU() .getValue() && exporter.supportsAU())) | |||
|| (hasSuffix (file, "_AUv3") && ! (project.shouldBuildAUv3().getValue() && exporter.supportsAUv3())) | |||
|| (hasSuffix (file, "_AAX") && ! (project.shouldBuildAAX() .getValue() && exporter.supportsAAX())) | |||
|| (hasSuffix (file, "_RTAS") && ! (project.shouldBuildRTAS().getValue() && exporter.supportsRTAS())) | |||
|| (hasSuffix (file, "_VST2") && ! (project.shouldBuildVST() .getValue() && exporter.supportsVST())) | |||
|| (hasSuffix (file, "_VST3") && ! (project.shouldBuildVST3().getValue() && exporter.supportsVST3())) | |||
|| (hasSuffix (file, "_Standalone") && ! (project.shouldBuildStandalone().getValue() && exporter.supportsStandalone()))) | |||
|| (hasSuffix (file, "_Android") && ! exporter.isAndroid())) | |||
return false; | |||
const ProjectType::Target::Type targetType = Project::getTargetTypeFromFilePath (file, false); | |||
if (targetType != ProjectType::Target::unspecified && ! exporter.shouldBuildTargetType (targetType)) | |||
return false; | |||
return exporter.usesMMFiles() ? isCompiledForObjC | |||
@@ -24,7 +24,6 @@ | |||
#include "../jucer_Headers.h" | |||
#include "jucer_Project.h" | |||
#include "jucer_ProjectType.h" | |||
#include "../Project Saving/jucer_ProjectExporter.h" | |||
#include "../Project Saving/jucer_ProjectSaver.h" | |||
#include "../Application/jucer_OpenDocumentManager.h" | |||
@@ -147,13 +146,13 @@ void Project::setMissingAudioPluginDefaultValues() | |||
{ | |||
const String sanitisedProjectName (CodeHelpers::makeValidIdentifier (getTitle(), false, true, false)); | |||
setValueIfVoid (shouldBuildVST(), true); | |||
setValueIfVoid (shouldBuildVST3(), false); | |||
setValueIfVoid (shouldBuildAU(), true); | |||
setValueIfVoid (shouldBuildAUv3(), false); | |||
setValueIfVoid (shouldBuildRTAS(), false); | |||
setValueIfVoid (shouldBuildAAX(), false); | |||
setValueIfVoid (shouldBuildStandalone(), false); | |||
setValueIfVoid (getShouldBuildVSTAsValue(), true); | |||
setValueIfVoid (getShouldBuildVST3AsValue(), false); | |||
setValueIfVoid (getShouldBuildAUAsValue(), true); | |||
setValueIfVoid (getShouldBuildAUv3AsValue(), false); | |||
setValueIfVoid (getShouldBuildRTASAsValue(), false); | |||
setValueIfVoid (getShouldBuildAAXAsValue(), false); | |||
setValueIfVoid (getShouldBuildStandalonePluginAsValue(), false); | |||
setValueIfVoid (getPluginName(), getTitle()); | |||
setValueIfVoid (getPluginDesc(), getTitle()); | |||
@@ -222,10 +221,19 @@ void Project::removeDefunctExporters() | |||
for (;;) | |||
{ | |||
ValueTree oldVC6Exporter (exporters.getChildWithName ("MSVC6")); | |||
ValueTree oldVC6Exporter (exporters.getChildWithName ("MSVC6")); | |||
ValueTree oldAndroidAntExporter (exporters.getChildWithName ("ANDROID")); | |||
if (oldVC6Exporter.isValid()) | |||
if (oldVC6Exporter.isValid()) | |||
exporters.removeChild (oldVC6Exporter, nullptr); | |||
else if (oldAndroidAntExporter.isValid()) | |||
{ | |||
AlertWindow::showMessageBox (AlertWindow::WarningIcon, | |||
TRANS("Android Ant Exporter"), | |||
TRANS("The Android Ant Exporter is deprecated. The exporter will be removed from this project.")); | |||
exporters.removeChild (oldAndroidAntExporter, nullptr); | |||
} | |||
else | |||
break; | |||
} | |||
@@ -436,6 +444,98 @@ const ProjectType& Project::getProjectType() const | |||
return *guiType; | |||
} | |||
bool Project::shouldBuildTargetType (ProjectType::Target::Type targetType) const noexcept | |||
{ | |||
const ProjectType& projectType = getProjectType(); | |||
if (! projectType.supportsTargetType (targetType)) | |||
return false; | |||
switch (targetType) | |||
{ | |||
case ProjectType::Target::VSTPlugIn: | |||
return shouldBuildVST(); | |||
case ProjectType::Target::VST3PlugIn: | |||
return shouldBuildVST3(); | |||
case ProjectType::Target::AAXPlugIn: | |||
return shouldBuildAAX(); | |||
case ProjectType::Target::RTASPlugIn: | |||
return shouldBuildRTAS(); | |||
case ProjectType::Target::AudioUnitPlugIn: | |||
return shouldBuildAU(); | |||
case ProjectType::Target::AudioUnitv3PlugIn: | |||
return shouldBuildAUv3(); | |||
case ProjectType::Target::StandalonePlugIn: | |||
return shouldBuildStandalonePlugin(); | |||
case ProjectType::Target::AggregateTarget: | |||
case ProjectType::Target::SharedCodeTarget: | |||
return projectType.isAudioPlugin(); | |||
case ProjectType::Target::unspecified: | |||
return false; | |||
default: | |||
break; | |||
} | |||
return true; | |||
} | |||
ProjectType::Target::Type Project::getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix) | |||
{ | |||
if (LibraryModule::CompileUnit::hasSuffix (file, "_AU")) return ProjectType::Target::AudioUnitPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_AUv3")) return ProjectType::Target::AudioUnitv3PlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_AAX")) return ProjectType::Target::AAXPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_RTAS")) return ProjectType::Target::RTASPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST2")) return ProjectType::Target::VSTPlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_VST3")) return ProjectType::Target::VST3PlugIn; | |||
else if (LibraryModule::CompileUnit::hasSuffix (file, "_Standalone")) return ProjectType::Target::StandalonePlugIn; | |||
return (returnSharedTargetIfNoValidSuffix ? ProjectType::Target::SharedCodeTarget : ProjectType::Target::unspecified); | |||
} | |||
const char* ProjectType::Target::getName() const noexcept | |||
{ | |||
switch (type) | |||
{ | |||
case GUIApp: return "App"; | |||
case ConsoleApp: return "ConsoleApp"; | |||
case StaticLibrary: return "Static Library"; | |||
case DynamicLibrary: return "Dynamic Library"; | |||
case VSTPlugIn: return "VST"; | |||
case VST3PlugIn: return "VST3"; | |||
case AudioUnitPlugIn: return "AU"; | |||
case StandalonePlugIn: return "Standalone Plugin"; | |||
case AudioUnitv3PlugIn: return "AUv3 AppExtension"; | |||
case AAXPlugIn: return "AAX"; | |||
case RTASPlugIn: return "RTAS"; | |||
case SharedCodeTarget: return "Shared Code"; | |||
case AggregateTarget: return "All"; | |||
default: return "undefined"; | |||
} | |||
} | |||
ProjectType::Target::TargetFileType ProjectType::Target::getTargetFileType() const noexcept | |||
{ | |||
switch (type) | |||
{ | |||
case GUIApp: return executable; | |||
case ConsoleApp: return executable; | |||
case StaticLibrary: return staticLibrary; | |||
case DynamicLibrary: return sharedLibraryOrDLL; | |||
case VSTPlugIn: return pluginBundle; | |||
case VST3PlugIn: return pluginBundle; | |||
case AudioUnitPlugIn: return pluginBundle; | |||
case StandalonePlugIn: return executable; | |||
case AudioUnitv3PlugIn: return macOSAppex; | |||
case AAXPlugIn: return pluginBundle; | |||
case RTASPlugIn: return pluginBundle; | |||
case SharedCodeTarget: return staticLibrary; | |||
default: | |||
break; | |||
} | |||
return unknown; | |||
} | |||
//============================================================================== | |||
void Project::createPropertyEditors (PropertyListBuilder& props) | |||
{ | |||
@@ -515,25 +615,20 @@ void Project::createPropertyEditors (PropertyListBuilder& props) | |||
void Project::createAudioPluginPropertyEditors (PropertyListBuilder& props) | |||
{ | |||
props.add (new BooleanPropertyComponent (shouldBuildVST(), "Build VST", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildVSTAsValue(), "Build VST", "Enabled"), | |||
"Whether the project should produce a VST plugin."); | |||
props.add (new BooleanPropertyComponent (shouldBuildVST3(), "Build VST3", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildVST3AsValue(), "Build VST3", "Enabled"), | |||
"Whether the project should produce a VST3 plugin."); | |||
props.add (new BooleanPropertyComponent (shouldBuildAU(), "Build AudioUnit", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildAUAsValue(), "Build AudioUnit", "Enabled"), | |||
"Whether the project should produce an AudioUnit plugin."); | |||
props.add (new BooleanPropertyComponent (shouldBuildAUv3(), "Build AudioUnit v3", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildAUv3AsValue(), "Build AudioUnit v3", "Enabled"), | |||
"Whether the project should produce an AudioUnit version 3 plugin."); | |||
props.add (new BooleanPropertyComponent (shouldBuildRTAS(), "Build RTAS", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildRTASAsValue(), "Build RTAS", "Enabled"), | |||
"Whether the project should produce an RTAS plugin."); | |||
props.add (new BooleanPropertyComponent (shouldBuildAAX(), "Build AAX", "Enabled"), | |||
props.add (new BooleanPropertyComponent (getShouldBuildAAXAsValue(), "Build AAX", "Enabled"), | |||
"Whether the project should produce an AAX plugin."); | |||
/* TODO: this property editor is temporarily disabled because right now we build standalone if and only if | |||
we also build AUv3. However as soon as targets are supported on non-Xcode exporters as well, we should | |||
re-enable this option and allow to build the standalone plug-in independently from AUv3. | |||
*/ | |||
// props.add (new BooleanPropertyComponent (shouldBuildStandalone(), "Build Standalone", "Enabled"), | |||
// "Whether the project should produce a standalone version of the plugin. Required for AUv3."); | |||
props.add (new BooleanPropertyComponent (getShouldBuildStandalonePluginAsValue(), "Build Standalone Plug-In", "Enabled"), | |||
"Whether the project should produce a standalone version of your plugin."); | |||
props.add (new TextPropertyComponent (getPluginName(), "Plugin Name", 128, false), | |||
"The name of your plugin (keep it short!)"); | |||
@@ -25,8 +25,9 @@ | |||
#ifndef JUCER_PROJECT_H_INCLUDED | |||
#define JUCER_PROJECT_H_INCLUDED | |||
#include "jucer_ProjectType.h" | |||
class ProjectExporter; | |||
class ProjectType; | |||
class LibraryModule; | |||
class EnabledModuleList; | |||
@@ -95,7 +96,8 @@ public: | |||
Value getCompanyEmail() { return getProjectValue (Ids::companyEmail); } | |||
//============================================================================== | |||
Value getProjectValue (const Identifier& name) { return projectRoot.getPropertyAsValue (name, getUndoManagerFor (projectRoot)); } | |||
Value getProjectValue (const Identifier& name) { return projectRoot.getPropertyAsValue (name, getUndoManagerFor (projectRoot)); } | |||
var getProjectVar (const Identifier& name) const { return projectRoot.getProperty (name); } | |||
Value getProjectPreprocessorDefs() { return getProjectValue (Ids::defines); } | |||
StringPairArray getPreprocessorDefs() const; | |||
@@ -122,13 +124,23 @@ public: | |||
//============================================================================== | |||
// Some helper methods for audio plugin/host projects. | |||
Value shouldBuildVST() { return getProjectValue ("buildVST"); } | |||
Value shouldBuildVST3() { return getProjectValue ("buildVST3"); } | |||
Value shouldBuildAU() { return getProjectValue ("buildAU"); } | |||
Value shouldBuildAUv3() { return getProjectValue ("buildAUv3"); } | |||
Value shouldBuildRTAS() { return getProjectValue ("buildRTAS"); } | |||
Value shouldBuildAAX() { return getProjectValue ("buildAAX"); } | |||
Value shouldBuildStandalone() { return shouldBuildAUv3(); /* TODO: enable this when standalone becomes independent from AUv3: getProjectValue ("buildStandalone"); */} | |||
Value getShouldBuildVSTAsValue() { return getProjectValue ("buildVST"); } | |||
Value getShouldBuildVST3AsValue() { return getProjectValue ("buildVST3"); } | |||
Value getShouldBuildAUAsValue() { return getProjectValue ("buildAU"); } | |||
Value getShouldBuildAUv3AsValue() { return getProjectValue ("buildAUv3"); } | |||
Value getShouldBuildRTASAsValue() { return getProjectValue ("buildRTAS"); } | |||
Value getShouldBuildAAXAsValue() { return getProjectValue ("buildAAX"); } | |||
Value getShouldBuildStandalonePluginAsValue() { return getProjectValue ("buildStandalone");} | |||
bool shouldBuildVST() const { return getProjectVar ("buildVST"); } | |||
bool shouldBuildVST3() const { return getProjectVar ("buildVST3"); } | |||
bool shouldBuildAU() const { return getProjectVar ("buildAU"); } | |||
bool shouldBuildAUv3() const { return getProjectVar ("buildAUv3"); } | |||
bool shouldBuildRTAS() const { return getProjectVar ("buildRTAS"); } | |||
bool shouldBuildAAX() const { return getProjectVar ("buildAAX"); } | |||
bool shouldBuildStandalonePlugin() const { return getProjectVar ("buildStandalone"); } | |||
//============================================================================== | |||
Value getPluginName() { return getProjectValue ("pluginName"); } | |||
Value getPluginDesc() { return getProjectValue ("pluginDesc"); } | |||
Value getPluginManufacturer() { return getProjectValue ("pluginManufacturer"); } | |||
@@ -158,6 +170,10 @@ public: | |||
bool isVSTPluginHost(); | |||
bool isVST3PluginHost(); | |||
bool shouldBuildTargetType (ProjectType::Target::Type targetType) const noexcept; | |||
static ProjectType::Target::Type getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix); | |||
//============================================================================== | |||
void updateDeprecatedProjectSettingsInteractively(); | |||
//============================================================================== | |||
@@ -49,6 +49,55 @@ public: | |||
virtual bool isCommandLineApp() const { return false; } | |||
virtual bool isAudioPlugin() const { return false; } | |||
//============================================================================== | |||
struct Target | |||
{ | |||
enum Type | |||
{ | |||
GUIApp = 0, | |||
ConsoleApp = 1, | |||
StaticLibrary = 2, | |||
DynamicLibrary = 3, | |||
VSTPlugIn = 10, | |||
VST3PlugIn = 11, | |||
AAXPlugIn = 12, | |||
RTASPlugIn = 13, | |||
AudioUnitPlugIn = 14, | |||
AudioUnitv3PlugIn = 15, | |||
StandalonePlugIn = 16, | |||
SharedCodeTarget = 20, // internal | |||
AggregateTarget = 21, | |||
unspecified = 30 | |||
}; | |||
enum TargetFileType | |||
{ | |||
executable = 0, | |||
staticLibrary = 1, | |||
sharedLibraryOrDLL = 2, | |||
pluginBundle = 3, | |||
macOSAppex = 4, | |||
unknown = 5 | |||
}; | |||
//============================================================================== | |||
Target (Type targetType) : type (targetType) {} | |||
const char* getName() const noexcept; | |||
TargetFileType getTargetFileType() const noexcept; | |||
const Type type; | |||
private: | |||
//============================================================================== | |||
Target& operator= (const Target&) JUCE_DELETED_FUNCTION; | |||
}; | |||
virtual bool supportsTargetType (Target::Type /*targetType*/) const { return false; } | |||
protected: | |||
ProjectType (const String& type, const String& desc); | |||
@@ -86,32 +135,36 @@ struct ProjectType_GUIApp : public ProjectType | |||
{ | |||
ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {} | |||
static const char* getTypeName() noexcept { return "guiapp"; } | |||
bool isGUIApplication() const override { return true; } | |||
static const char* getTypeName() noexcept { return "guiapp"; } | |||
bool isGUIApplication() const override { return true; } | |||
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::GUIApp); } | |||
}; | |||
struct ProjectType_ConsoleApp : public ProjectType | |||
{ | |||
ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {} | |||
static const char* getTypeName() noexcept { return "consoleapp"; } | |||
bool isCommandLineApp() const override { return true; } | |||
static const char* getTypeName() noexcept { return "consoleapp"; } | |||
bool isCommandLineApp() const override { return true; } | |||
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::ConsoleApp); } | |||
}; | |||
struct ProjectType_StaticLibrary : public ProjectType | |||
{ | |||
ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {} | |||
static const char* getTypeName() noexcept { return "library"; } | |||
bool isStaticLibrary() const override { return true; } | |||
static const char* getTypeName() noexcept { return "library"; } | |||
bool isStaticLibrary() const override { return true; } | |||
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::StaticLibrary); } | |||
}; | |||
struct ProjectType_DLL : public ProjectType | |||
{ | |||
ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {} | |||
static const char* getTypeName() noexcept { return "dll"; } | |||
bool isDynamicLibrary() const override { return true; } | |||
static const char* getTypeName() noexcept { return "dll"; } | |||
bool isDynamicLibrary() const override { return true; } | |||
bool supportsTargetType (Target::Type targetType) const override { return (targetType == Target::DynamicLibrary); } | |||
}; | |||
struct ProjectType_AudioPlugin : public ProjectType | |||
@@ -120,6 +173,27 @@ struct ProjectType_AudioPlugin : public ProjectType | |||
static const char* getTypeName() noexcept { return "audioplug"; } | |||
bool isAudioPlugin() const override { return true; } | |||
bool supportsTargetType (Target::Type targetType) const override | |||
{ | |||
switch (targetType) | |||
{ | |||
case Target::VSTPlugIn: | |||
case Target::VST3PlugIn: | |||
case Target::AAXPlugIn: | |||
case Target::RTASPlugIn: | |||
case Target::AudioUnitPlugIn: | |||
case Target::AudioUnitv3PlugIn: | |||
case Target::StandalonePlugIn: | |||
case Target::SharedCodeTarget: | |||
case Target::AggregateTarget: | |||
return true; | |||
default: | |||
break; | |||
} | |||
return false; | |||
} | |||
}; | |||
//============================================================================== | |||
@@ -104,6 +104,8 @@ namespace Ids | |||
DECLARE_ID (winWarningLevel); | |||
DECLARE_ID (warningsAreErrors); | |||
DECLARE_ID (linuxArchitecture); | |||
DECLARE_ID (linuxCodeBlocksArchitecture); | |||
DECLARE_ID (windowsCodeBlocksArchitecture); | |||
DECLARE_ID (toolset); | |||
DECLARE_ID (IPPLibrary); | |||
DECLARE_ID (msvcModuleDefinitionFile); | |||
@@ -112,7 +114,6 @@ namespace Ids | |||
DECLARE_ID (jucerVersion); | |||
DECLARE_ID (prebuildCommand); | |||
DECLARE_ID (postbuildCommand); | |||
DECLARE_ID (internalPostBuildComamnd); | |||
DECLARE_ID (generateManifest); | |||
DECLARE_ID (useRuntimeLibDLL); | |||
DECLARE_ID (wholeProgramOptimisation); | |||
@@ -173,7 +174,7 @@ namespace Ids | |||
DECLARE_ID (iosDevelopmentTeamID); | |||
DECLARE_ID (buildToolsVersion); | |||
DECLARE_ID (gradleVersion); | |||
DECLARE_ID (gradleWrapperVersion); | |||
const Identifier androidPluginVersion ("gradleWrapperVersion"); // old name is very confusing, but we need to remain backward compatible | |||
DECLARE_ID (gradleToolchain); | |||
DECLARE_ID (gradleToolchainVersion); | |||
DECLARE_ID (linuxExtraPkgConfig); | |||