@@ -36,11 +36,19 @@ public: | |||||
bool isAndroidStudio() const override { return false; } | bool isAndroidStudio() const override { return false; } | ||||
bool isAndroidAnt() const override { return true; } | 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"; } | static const char* getName() { return "Android Ant Project"; } | ||||
@@ -340,7 +348,7 @@ private: | |||||
flags << " -std=gnu++11"; | flags << " -std=gnu++11"; | ||||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs ()); | |||||
return flags + createGCCPreprocessorFlags (defines); | return flags + createGCCPreprocessorFlags (defines); | ||||
} | } | ||||
@@ -58,13 +58,19 @@ public: | |||||
bool isOSX() const override { return false; } | bool isOSX() const override { return false; } | ||||
bool isiOS() 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 | void create (const OwnedArray<LibraryModule>& modules) const override | ||||
@@ -51,7 +51,7 @@ public: | |||||
AndroidStudioProjectExporter (Project& p, const ValueTree& t) | AndroidStudioProjectExporter (Project& p, const ValueTree& t) | ||||
: AndroidProjectExporterBase (p, t), | : AndroidProjectExporterBase (p, t), | ||||
gradleVersion (settings, Ids::gradleVersion, nullptr, "2.14.1"), | 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"), | gradleToolchain (settings, Ids::gradleToolchain, nullptr, "clang"), | ||||
buildToolsVersion (settings, Ids::buildToolsVersion, nullptr, "23.0.2"), | buildToolsVersion (settings, Ids::buildToolsVersion, nullptr, "23.0.2"), | ||||
androidStudioExecutable (findAndroidStudioExecutable()) | androidStudioExecutable (findAndroidStudioExecutable()) | ||||
@@ -113,13 +113,25 @@ public: | |||||
bool isOSX() const override { return false; } | bool isOSX() const override { return false; } | ||||
bool isiOS() 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 | 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: | private: | ||||
@@ -151,14 +184,52 @@ private: | |||||
CodeBlocksBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e) | CodeBlocksBuildConfiguration (Project& p, const ValueTree& settings, const ProjectExporter& e) | ||||
: BuildConfiguration (p, settings, 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 | void createConfigProperties (PropertyListBuilder& props) override | ||||
{ | { | ||||
addGCCOptimisationProperty (props); | 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 | BuildConfiguration::Ptr createBuildConfig (const ValueTree& tree) const override | ||||
@@ -166,6 +237,59 @@ private: | |||||
return new CodeBlocksBuildConfiguration (project, tree, *this); | 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 | void addVersion (XmlElement& xml) const | ||||
{ | { | ||||
@@ -181,7 +305,7 @@ private: | |||||
xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc"); | xml.createNewChildElement ("Option")->setAttribute ("compiler", "gcc"); | ||||
} | } | ||||
StringArray getDefines (const BuildConfiguration& config) const | |||||
StringArray getDefines (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||||
{ | { | ||||
StringPairArray defines; | StringPairArray defines; | ||||
@@ -205,7 +329,7 @@ private: | |||||
defines.set ("NDEBUG", "1"); | defines.set ("NDEBUG", "1"); | ||||
} | } | ||||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config)); | |||||
defines = mergePreprocessorDefs (defines, getAllPreprocessorDefs (config, target.type)); | |||||
StringArray defs; | StringArray defs; | ||||
for (int i = 0; i < defines.size(); ++i) | for (int i = 0; i < defines.size(); ++i) | ||||
@@ -214,9 +338,12 @@ private: | |||||
return getCleanedStringArray (defs); | return getCleanedStringArray (defs); | ||||
} | } | ||||
StringArray getCompilerFlags (const BuildConfiguration& config) const | |||||
StringArray getCompilerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||||
{ | { | ||||
StringArray flags; | StringArray flags; | ||||
if (const auto codeBlocksConfig = dynamic_cast<const CodeBlocksBuildConfiguration*> (&config)) | |||||
flags.add (codeBlocksConfig->getArchitectureTypeVar()); | |||||
flags.add ("-O" + config.getGCCOptimisationFlag()); | flags.add ("-O" + config.getGCCOptimisationFlag()); | ||||
flags.add ("-std=c++11"); | flags.add ("-std=c++11"); | ||||
flags.add ("-mstackrealign"); | flags.add ("-mstackrealign"); | ||||
@@ -228,7 +355,7 @@ private: | |||||
" \n", "\"'"); | " \n", "\"'"); | ||||
{ | { | ||||
const StringArray defines (getDefines (config)); | |||||
const StringArray defines (getDefines (config, target)); | |||||
for (int i = 0; i < defines.size(); ++i) | for (int i = 0; i < defines.size(); ++i) | ||||
{ | { | ||||
@@ -243,7 +370,7 @@ private: | |||||
if (config.exporter.isLinux()) | if (config.exporter.isLinux()) | ||||
{ | { | ||||
if (createDynamicLibrary) | |||||
if (target.isDynamicLibrary() || getProject().getProjectType().isAudioPlugin()) | |||||
flags.add ("-fPIC"); | flags.add ("-fPIC"); | ||||
if (linuxPackages.size() > 0) | if (linuxPackages.size() > 0) | ||||
@@ -263,19 +390,25 @@ private: | |||||
return getCleanedStringArray (flags); | return getCleanedStringArray (flags); | ||||
} | } | ||||
StringArray getLinkerFlags (const BuildConfiguration& config) const | |||||
StringArray getLinkerFlags (const BuildConfiguration& config, CodeBlocksTarget& target) const | |||||
{ | { | ||||
StringArray flags (makefileExtraLinkerFlags); | StringArray flags (makefileExtraLinkerFlags); | ||||
if (const auto codeBlocksConfig = dynamic_cast<const CodeBlocksBuildConfiguration*> (&config)) | |||||
flags.add (codeBlocksConfig->getArchitectureTypeVar()); | |||||
if (! config.isDebug()) | if (! config.isDebug()) | ||||
flags.add ("-s"); | flags.add ("-s"); | ||||
flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(), | flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(), | ||||
" \n", "\"'"); | " \n", "\"'"); | ||||
if (getProject().getProjectType().isAudioPlugin() && target.type != ProjectType::Target::SharedCodeTarget) | |||||
flags.add ("-l" + config.getTargetBinaryNameString()); | |||||
if (config.exporter.isLinux() && linuxPackages.size() > 0) | if (config.exporter.isLinux() && linuxPackages.size() > 0) | ||||
{ | { | ||||
if (createDynamicLibrary) | |||||
if (target.isDynamicLibrary()) | |||||
flags.add ("-shared"); | flags.add ("-shared"); | ||||
auto pkgconfigLibs = String ("`pkg-config --libs"); | auto pkgconfigLibs = String ("`pkg-config --libs"); | ||||
@@ -303,80 +436,119 @@ private: | |||||
return getCleanedStringArray (paths); | 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; | 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"); | 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") | xml.createNewChildElement ("Option") | ||||
->setAttribute ("object_output", "obj/" + File::createLegalFileName (config.getName().trim())); | ->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"); | 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"); | 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)); | 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"); | 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; | 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"); | XmlElement* const build = xml.createNewChildElement ("Build"); | ||||
for (ConstConfigIterator config (*this); config.next();) | 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 | void addProjectCompilerOptions (XmlElement& xml) const | ||||
@@ -416,6 +617,54 @@ private: | |||||
setAddOption (*linker, "library", replacePreprocessorDefs (getAllPreprocessorDefs(), libs[i])); | 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 | void addCompileUnits (const Project::Item& projectItem, XmlElement& xml) const | ||||
{ | { | ||||
if (projectItem.isGroup()) | if (projectItem.isGroup()) | ||||
@@ -430,10 +679,16 @@ private: | |||||
XmlElement* unit = xml.createNewChildElement ("Unit"); | XmlElement* unit = xml.createNewChildElement ("Unit"); | ||||
unit->setAttribute ("filename", file.toUnixStyle()); | 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()) | 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); | addOptions (xml); | ||||
addBuild (xml); | addBuild (xml); | ||||
addVirtualTargets (xml); | |||||
addProjectCompilerOptions (xml); | addProjectCompilerOptions (xml); | ||||
addProjectLinkerOptions (xml); | addProjectLinkerOptions (xml); | ||||
addCompileUnits (xml); | addCompileUnits (xml); | ||||
@@ -473,7 +729,8 @@ private: | |||||
} | } | ||||
CodeBlocksOS os; | CodeBlocksOS os; | ||||
bool createDynamicLibrary = false; | |||||
OwnedArray<CodeBlocksTarget> targets; | |||||
JUCE_DECLARE_NON_COPYABLE (CodeBlocksProjectExporter) | JUCE_DECLARE_NON_COPYABLE (CodeBlocksProjectExporter) | ||||
}; | }; |
@@ -24,7 +24,243 @@ | |||||
class MakefileProjectExporter : public ProjectExporter | 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: | 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* getNameLinux() { return "Linux Makefile"; } | ||||
static const char* getValueTreeTypeName() { return "LINUX_MAKE"; } | static const char* getValueTreeTypeName() { return "LINUX_MAKE"; } | ||||
@@ -72,13 +308,25 @@ public: | |||||
bool isOSX() const override { return false; } | bool isOSX() const override { return false; } | ||||
bool isiOS() 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); } | Value getCppStandardValue() { return getSetting (Ids::cppLanguageStandard); } | ||||
String getCppStandardString() const { return settings[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: | 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 | void writeDefineFlags (OutputStream& out, const BuildConfiguration& config) const | ||||
{ | { | ||||
StringPairArray defines; | StringPairArray defines; | ||||
@@ -189,7 +405,7 @@ private: | |||||
defines.set ("NDEBUG", "1"); | 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 | void writeHeaderPathFlags (OutputStream& out, const BuildConfiguration& config) const | ||||
@@ -239,9 +455,6 @@ private: | |||||
{ | { | ||||
StringArray flags (makefileExtraLinkerFlags); | StringArray flags (makefileExtraLinkerFlags); | ||||
if (makefileIsDLL) | |||||
flags.add ("-shared"); | |||||
if (! config.isDebug()) | if (! config.isDebug()) | ||||
flags.add ("-fvisibility=hidden"); | flags.add ("-fvisibility=hidden"); | ||||
@@ -282,6 +495,36 @@ private: | |||||
<< " $(LDFLAGS)" << newLine; | << " $(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 | void writeConfig (OutputStream& out, const BuildConfiguration& config) const | ||||
{ | { | ||||
const String buildDirName ("build"); | const String buildDirName ("build"); | ||||
@@ -307,14 +550,24 @@ private: | |||||
writeCppFlags (out, config); | 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)"; | out << " JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH)"; | ||||
if (anyTargetIsSharedLibrary()) | |||||
out << " -fPIC"; | |||||
if (config.isDebug()) | if (config.isDebug()) | ||||
out << " -g -ggdb"; | out << " -g -ggdb"; | ||||
if (makefileIsDLL) | |||||
out << " -fPIC"; | |||||
out << " -O" << config.getGCCOptimisationFlag() | out << " -O" << config.getGCCOptimisationFlag() | ||||
<< (" " + replacePreprocessorTokens (config, getExtraCompilerFlagsString())).trimEnd() | << (" " + replacePreprocessorTokens (config, getExtraCompilerFlagsString())).trimEnd() | ||||
<< " $(CFLAGS)" << newLine; | << " $(CFLAGS)" << newLine; | ||||
@@ -324,44 +577,19 @@ private: | |||||
if (cppStandardToUse.isEmpty()) | if (cppStandardToUse.isEmpty()) | ||||
cppStandardToUse = "-std=c++11"; | cppStandardToUse = "-std=c++11"; | ||||
out << " JUCE_CXXFLAGS += $(JUCE_CFLAGS) " | |||||
out << " JUCE_CXXFLAGS += $(CXXFLAGS) $(JUCE_CFLAGS) " | |||||
<< cppStandardToUse << " $(CXXFLAGS)" << newLine; | << cppStandardToUse << " $(CXXFLAGS)" << newLine; | ||||
writeLinkerFlags (out, config); | writeLinkerFlags (out, config); | ||||
out << newLine; | 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 | out << " CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)" << newLine | ||||
<< "endif" << newLine | << "endif" << newLine | ||||
<< 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 | 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 | << "# 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();) | for (ConstConfigIterator config (*this); config.next();) | ||||
writeConfig (out, *config); | writeConfig (out, *config); | ||||
writeObjects (out, files); | |||||
for (auto target : targets) | |||||
target->writeObjects (out); | |||||
out << ".PHONY: clean" << newLine | |||||
out << ".PHONY: clean all" << newLine | |||||
<< newLine; | << newLine; | ||||
StringArray packages; | StringArray packages; | ||||
packages.addTokens (getExtraPkgConfigString(), " ", "\"'"); | packages.addTokens (getExtraPkgConfigString(), " ", "\"'"); | ||||
packages.removeEmptyStrings(); | 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) | if (useLinuxPackages) | ||||
{ | { | ||||
@@ -442,25 +666,9 @@ private: | |||||
out << "strip:" << newLine | out << "strip:" << newLine | ||||
<< "\t@echo Stripping " << projectName << 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; | << 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; | out << "-include $(OBJECTS:%.o=%.d)" << newLine; | ||||
} | } | ||||
@@ -486,5 +694,7 @@ private: | |||||
TargetOS::linux))); | TargetOS::linux))); | ||||
} | } | ||||
OwnedArray<MakefileTarget> targets; | |||||
JUCE_DECLARE_NON_COPYABLE (MakefileProjectExporter) | JUCE_DECLARE_NON_COPYABLE (MakefileProjectExporter) | ||||
}; | }; |
@@ -127,13 +127,31 @@ public: | |||||
bool isOSX() const override { return ! iOS; } | bool isOSX() const override { return ! iOS; } | ||||
bool isiOS() 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 | void createExporterProperties (PropertyListBuilder& props) override | ||||
{ | { | ||||
@@ -206,7 +224,8 @@ public: | |||||
"You can find this string in the OS X app Keychain Access under \"Certificates\"."); | "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"), | 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 | bool launchProject() override | ||||
@@ -231,7 +250,7 @@ public: | |||||
void create (const OwnedArray<LibraryModule>&) const override | void create (const OwnedArray<LibraryModule>&) const override | ||||
{ | { | ||||
for (auto& target : targets) | for (auto& target : targets) | ||||
if (target->xcodeCreatePList) | |||||
if (target->shouldCreatePList()) | |||||
target->infoPlistFile = getTargetFolder().getChildFile (target->getInfoPlistName()); | target->infoPlistFile = getTargetFolder().getChildFile (target->getInfoPlistName()); | ||||
menuNibFile = getTargetFolder().getChildFile ("RecentFilesMenuTemplate.nib"); | 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 | // If you hit this assert, you tried to generate a project for an exporter | ||||
// that does not support any of your targets! | // that does not support any of your targets! | ||||
@@ -400,7 +385,9 @@ protected: | |||||
osxVersionNames.add ("Use Default"); | osxVersionNames.add ("Use Default"); | ||||
versionValues.add (osxVersionDefault); | 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)); | sdkVersionNames.add (getSDKName (ver)); | ||||
osxVersionNames.add (getOSXVersionName (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."); | "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: | private: | ||||
//========================================================================== | //========================================================================== | ||||
void addXcodePluginInstallPathProperties (PropertyListBuilder& props) | void addXcodePluginInstallPathProperties (PropertyListBuilder& props) | ||||
{ | { | ||||
if (project.shouldBuildVST().getValue()) | |||||
if (project.shouldBuildVST()) | |||||
props.add (new TextWithDefaultPropertyComponent<String> (vstBinaryLocation, "VST Binary location", 1024), | props.add (new TextWithDefaultPropertyComponent<String> (vstBinaryLocation, "VST Binary location", 1024), | ||||
"The folder in which the compiled VST binary should be placed."); | "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), | props.add (new TextWithDefaultPropertyComponent<String> (vst3BinaryLocation, "VST3 Binary location", 1024), | ||||
"The folder in which the compiled VST3 binary should be placed."); | "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), | props.add (new TextWithDefaultPropertyComponent<String> (auBinaryLocation, "AU Binary location", 1024), | ||||
"The folder in which the compiled AU binary should be placed."); | "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), | props.add (new TextWithDefaultPropertyComponent<String> (rtasBinaryLocation, "RTAS Binary location", 1024), | ||||
"The folder in which the compiled RTAS binary should be placed."); | "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), | props.add (new TextWithDefaultPropertyComponent<String> (aaxBinaryLocation, "AAX Binary location", 1024), | ||||
"The folder in which the compiled AAX binary should be placed."); | "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) | owner (exporter) | ||||
{ | { | ||||
switch (type) | switch (type) | ||||
{ | { | ||||
case GUIApp: | case GUIApp: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = true; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "APPL"; | xcodePackageType = "APPL"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeFileType = "wrapper.application"; | xcodeFileType = "wrapper.application"; | ||||
@@ -556,9 +524,6 @@ public: | |||||
break; | break; | ||||
case ConsoleApp: | case ConsoleApp: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = true; | |||||
xcodeCreatePList = false; | |||||
xcodeFileType = "compiled.mach-o.executable"; | xcodeFileType = "compiled.mach-o.executable"; | ||||
xcodeBundleExtension = String(); | xcodeBundleExtension = String(); | ||||
xcodeProductType = "com.apple.product-type.tool"; | xcodeProductType = "com.apple.product-type.tool"; | ||||
@@ -566,55 +531,37 @@ public: | |||||
break; | break; | ||||
case StaticLibrary: | case StaticLibrary: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = false; | |||||
xcodeFileType = "archive.ar"; | xcodeFileType = "archive.ar"; | ||||
xcodeProductType = "com.apple.product-type.library.static"; | xcodeProductType = "com.apple.product-type.library.static"; | ||||
xcodeCopyToProductInstallPathAfterBuild = false; | xcodeCopyToProductInstallPathAfterBuild = false; | ||||
break; | break; | ||||
case DynamicLibrary: | case DynamicLibrary: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = false; | |||||
xcodeFileType = "compiled.mach-o.dylib"; | xcodeFileType = "compiled.mach-o.dylib"; | ||||
xcodeProductType = "com.apple.product-type.library.dynamic"; | xcodeProductType = "com.apple.product-type.library.dynamic"; | ||||
xcodeBundleExtension = ".dylib"; | xcodeBundleExtension = ".dylib"; | ||||
xcodeCopyToProductInstallPathAfterBuild = false; | xcodeCopyToProductInstallPathAfterBuild = false; | ||||
break; | break; | ||||
case VSTPlugIn: | case VSTPlugIn: | ||||
xcodeIsBundle = true; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "BNDL"; | xcodePackageType = "BNDL"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeFileType = "wrapper.cfbundle"; | xcodeFileType = "wrapper.cfbundle"; | ||||
xcodeBundleExtension = ".vst"; | xcodeBundleExtension = ".vst"; | ||||
xcodeProductType = "com.apple.product-type.bundle"; | xcodeProductType = "com.apple.product-type.bundle"; | ||||
xcodeCopyToProductInstallPathAfterBuild = true; | xcodeCopyToProductInstallPathAfterBuild = true; | ||||
break; | break; | ||||
case VST3PlugIn: | case VST3PlugIn: | ||||
xcodeIsBundle = true; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "BNDL"; | xcodePackageType = "BNDL"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeFileType = "wrapper.cfbundle"; | xcodeFileType = "wrapper.cfbundle"; | ||||
xcodeBundleExtension = ".vst3"; | xcodeBundleExtension = ".vst3"; | ||||
xcodeProductType = "com.apple.product-type.bundle"; | xcodeProductType = "com.apple.product-type.bundle"; | ||||
xcodeCopyToProductInstallPathAfterBuild = true; | xcodeCopyToProductInstallPathAfterBuild = true; | ||||
break; | break; | ||||
case AudioUnitPlugIn: | case AudioUnitPlugIn: | ||||
xcodeIsBundle = true; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "BNDL"; | xcodePackageType = "BNDL"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeFileType = "wrapper.cfbundle"; | xcodeFileType = "wrapper.cfbundle"; | ||||
@@ -626,12 +573,8 @@ public: | |||||
break; | break; | ||||
case StandalonePlugIn: | case StandalonePlugIn: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = true; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "APPL"; | xcodePackageType = "APPL"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeCreatePList = true; | |||||
xcodeFileType = "wrapper.application"; | xcodeFileType = "wrapper.application"; | ||||
xcodeBundleExtension = ".app"; | xcodeBundleExtension = ".app"; | ||||
xcodeProductType = "com.apple.product-type.application"; | xcodeProductType = "com.apple.product-type.application"; | ||||
@@ -639,9 +582,6 @@ public: | |||||
break; | break; | ||||
case AudioUnitv3PlugIn: | case AudioUnitv3PlugIn: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "XPC!"; | xcodePackageType = "XPC!"; | ||||
xcodeBundleSignature = "????"; | xcodeBundleSignature = "????"; | ||||
xcodeFileType = "wrapper.app-extension"; | xcodeFileType = "wrapper.app-extension"; | ||||
@@ -654,9 +594,6 @@ public: | |||||
break; | break; | ||||
case AAXPlugIn: | case AAXPlugIn: | ||||
xcodeIsBundle = true; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "TDMw"; | xcodePackageType = "TDMw"; | ||||
xcodeBundleSignature = "PTul"; | xcodeBundleSignature = "PTul"; | ||||
xcodeFileType = "wrapper.cfbundle"; | xcodeFileType = "wrapper.cfbundle"; | ||||
@@ -668,9 +605,6 @@ public: | |||||
break; | break; | ||||
case RTASPlugIn: | case RTASPlugIn: | ||||
xcodeIsBundle = true; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = true; | |||||
xcodePackageType = "TDMw"; | xcodePackageType = "TDMw"; | ||||
xcodeBundleSignature = "PTul"; | xcodeBundleSignature = "PTul"; | ||||
xcodeFileType = "wrapper.cfbundle"; | xcodeFileType = "wrapper.cfbundle"; | ||||
@@ -682,18 +616,12 @@ public: | |||||
break; | break; | ||||
case SharedCodeTarget: | case SharedCodeTarget: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = false; | |||||
xcodeFileType = "archive.ar"; | xcodeFileType = "archive.ar"; | ||||
xcodeProductType = "com.apple.product-type.library.static"; | xcodeProductType = "com.apple.product-type.library.static"; | ||||
xcodeCopyToProductInstallPathAfterBuild = false; | xcodeCopyToProductInstallPathAfterBuild = false; | ||||
break; | break; | ||||
case AggregateTarget: | case AggregateTarget: | ||||
xcodeIsBundle = false; | |||||
xcodeIsExecutable = false; | |||||
xcodeCreatePList = false; | |||||
xcodeCopyToProductInstallPathAfterBuild = false; | xcodeCopyToProductInstallPathAfterBuild = false; | ||||
break; | 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 | String getXCodeSchemeName() const | ||||
{ | { | ||||
return owner.projectName + " (" + getName() + ")"; | 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 | String getID() const | ||||
{ | { | ||||
return owner.createID (String ("__target") + getName()); | return owner.createID (String ("__target") + getName()); | ||||
@@ -751,9 +650,8 @@ public: | |||||
String xcodePackageType, xcodeBundleSignature, xcodeBundleExtension; | String xcodePackageType, xcodeBundleSignature, xcodeBundleExtension; | ||||
String xcodeProductType, xcodeFileType; | String xcodeProductType, xcodeFileType; | ||||
String xcodeOtherRezFlags, xcodeExcludedFiles64Bit, xcodeBundleIDSubPath; | String xcodeOtherRezFlags, xcodeExcludedFiles64Bit, xcodeBundleIDSubPath; | ||||
bool xcodeIsBundle, xcodeCreatePList, xcodeIsExecutable, xcodeCopyToProductInstallPathAfterBuild; | |||||
bool xcodeCopyToProductInstallPathAfterBuild; | |||||
StringArray xcodeFrameworks, xcodeLibs; | StringArray xcodeFrameworks, xcodeLibs; | ||||
Type type; | |||||
Array<XmlElement> xcodeExtraPListEntries; | Array<XmlElement> xcodeExtraPListEntries; | ||||
Array<RelativePath> xcodeExtraLibrariesDebug, xcodeExtraLibrariesRelease; | Array<RelativePath> xcodeExtraLibrariesDebug, xcodeExtraLibrariesRelease; | ||||
@@ -874,6 +772,12 @@ public: | |||||
return *v; | 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 | StringArray getTargetSettings (const XcodeBuildConfiguration& config) const | ||||
{ | { | ||||
@@ -904,7 +808,7 @@ public: | |||||
s.add ("HEADER_SEARCH_PATHS = " + owner.getHeaderSearchPaths (config)); | s.add ("HEADER_SEARCH_PATHS = " + owner.getHeaderSearchPaths (config)); | ||||
s.add ("GCC_OPTIMIZATION_LEVEL = " + config.getGCCOptimisationFlag()); | s.add ("GCC_OPTIMIZATION_LEVEL = " + config.getGCCOptimisationFlag()); | ||||
if (xcodeCreatePList) | |||||
if (shouldCreatePList()) | |||||
s.add ("INFOPLIST_FILE = " + infoPlistFile.getFileName()); | s.add ("INFOPLIST_FILE = " + infoPlistFile.getFileName()); | ||||
if (config.linkTimeOptimisationEnabled.get()) | if (config.linkTimeOptimisationEnabled.get()) | ||||
@@ -930,7 +834,7 @@ public: | |||||
} | } | ||||
} | } | ||||
if (xcodeIsBundle) | |||||
if (getTargetFileType() == pluginBundle) | |||||
{ | { | ||||
s.add ("LIBRARY_STYLE = Bundle"); | s.add ("LIBRARY_STYLE = Bundle"); | ||||
s.add ("WRAPPER_EXTENSION = " + xcodeBundleExtension.substring (1)); | 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 | // if the user doesn't set it, then use the last known version that works well with JUCE | ||||
String deploymentTarget = "10.11"; | 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 (sdk == getSDKName (ver)) s.add ("SDKROOT = macosx10." + String (ver)); | ||||
if (sdkCompat == getSDKName (ver)) deploymentTarget = "10." + String (ver); | if (sdkCompat == getSDKName (ver)) deploymentTarget = "10." + String (ver); | ||||
@@ -1052,24 +954,10 @@ public: | |||||
s.add ("SEPARATE_STRIP = YES"); | 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()) | if (owner.project.getProjectType().isAudioPlugin() && type == Target::AudioUnitv3PlugIn && owner.isOSX()) | ||||
s.add (String ("CODE_SIGN_ENTITLEMENTS = \"") + owner.getEntitlementsFileName() + String ("\"")); | 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; | StringArray defsList; | ||||
@@ -1109,7 +997,7 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
void getLinkerSettings (const BuildConfiguration& config, StringArray& flags, StringArray& librarySearchPaths) const | void getLinkerSettings (const BuildConfiguration& config, StringArray& flags, StringArray& librarySearchPaths) const | ||||
{ | { | ||||
if (xcodeIsBundle) | |||||
if (getTargetFileType() == pluginBundle) | |||||
flags.add (owner.isiOS() ? "-bitcode_bundle" : "-bundle"); | flags.add (owner.isiOS() ? "-bitcode_bundle" : "-bundle"); | ||||
const Array<RelativePath>& extraLibs = config.isDebug() ? xcodeExtraLibrariesDebug | const Array<RelativePath>& extraLibs = config.isDebug() ? xcodeExtraLibrariesDebug | ||||
@@ -1147,7 +1035,7 @@ public: | |||||
//========================================================================== c | //========================================================================== c | ||||
void writeInfoPlistFile() const | void writeInfoPlistFile() const | ||||
{ | { | ||||
if (! xcodeCreatePList) | |||||
if (! shouldCreatePList()) | |||||
return; | return; | ||||
ScopedPointer<XmlElement> plist (XmlDocument::parse (owner.getPListToMergeString())); | ScopedPointer<XmlElement> plist (XmlDocument::parse (owner.getPListToMergeString())); | ||||
@@ -1409,7 +1297,7 @@ public: | |||||
private: | private: | ||||
//============================================================================== | //============================================================================== | ||||
bool xcodeCanUseDwarf; | bool xcodeCanUseDwarf; | ||||
OwnedArray<Target> targets; | |||||
OwnedArray<XCodeTarget> targets; | |||||
mutable OwnedArray<ValueTree> pbxBuildFiles, pbxFileReferences, pbxGroups, misc, projectConfigs, targetConfigs; | mutable OwnedArray<ValueTree> pbxBuildFiles, pbxFileReferences, pbxGroups, misc, projectConfigs, targetConfigs; | ||||
mutable StringArray resourceIDs, sourceIDs, targetIDs; | mutable StringArray resourceIDs, sourceIDs, targetIDs; | ||||
@@ -1471,7 +1359,7 @@ private: | |||||
{ | { | ||||
for (auto* target : targets) | for (auto* target : targets) | ||||
{ | { | ||||
if (target->type == Target::AggregateTarget) | |||||
if (target->type == XCodeTarget::AggregateTarget) | |||||
continue; | continue; | ||||
target->addMainBuildProduct(); | target->addMainBuildProduct(); | ||||
@@ -1495,10 +1383,10 @@ private: | |||||
{ | { | ||||
for (auto* target : targets) | for (auto* target : targets) | ||||
{ | { | ||||
if (target->type == Target::AggregateTarget) | |||||
if (target->type == XCodeTarget::AggregateTarget) | |||||
continue; | continue; | ||||
if (target->xcodeCreatePList) | |||||
if (target->shouldCreatePList()) | |||||
{ | { | ||||
RelativePath plistPath (target->infoPlistFile, getTargetFolder(), RelativePath::buildTargetFolder); | RelativePath plistPath (target->infoPlistFile, getTargetFolder(), RelativePath::buildTargetFolder); | ||||
addFileReference (plistPath.toUnixStyle()); | addFileReference (plistPath.toUnixStyle()); | ||||
@@ -1576,7 +1464,7 @@ private: | |||||
// add build phases | // add build phases | ||||
for (auto* target : targets) | for (auto* target : targets) | ||||
{ | { | ||||
if (target->type != Target::AggregateTarget) | |||||
if (target->type != XCodeTarget::AggregateTarget) | |||||
buildProducts.add (createID (String ("__productFileID") + String (target->getName()))); | buildProducts.add (createID (String ("__productFileID") + String (target->getName()))); | ||||
for (ConstConfigIterator config (*this); config.next();) | for (ConstConfigIterator config (*this); config.next();) | ||||
@@ -1589,11 +1477,11 @@ private: | |||||
target->addShellScriptBuildPhase ("Pre-build script", getPreBuildScript()); | 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. | // TODO: ideally resources wouldn't be copied into the AUv3 bundle as well. | ||||
// However, fixing this requires supporting App groups -> TODO: add app groups | // 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); | target->addBuildPhase ("PBXResourcesBuildPhase", resourceIDs); | ||||
StringArray rezFiles (rezFileIDs); | StringArray rezFiles (rezFileIDs); | ||||
@@ -1604,20 +1492,20 @@ private: | |||||
StringArray sourceFiles (target->sourceIDs); | StringArray sourceFiles (target->sourceIDs); | ||||
if (target->type == Target::SharedCodeTarget | |||||
if (target->type == XCodeTarget::SharedCodeTarget | |||||
|| (! project.getProjectType().isAudioPlugin())) | || (! project.getProjectType().isAudioPlugin())) | ||||
sourceFiles.addArray (sourceIDs); | sourceFiles.addArray (sourceIDs); | ||||
target->addBuildPhase ("PBXSourcesBuildPhase", sourceFiles); | target->addBuildPhase ("PBXSourcesBuildPhase", sourceFiles); | ||||
if (! projectType.isStaticLibrary() && target->type != Target::SharedCodeTarget) | |||||
if (! projectType.isStaticLibrary() && target->type != XCodeTarget::SharedCodeTarget) | |||||
target->addBuildPhase ("PBXFrameworksBuildPhase", target->frameworkIDs); | target->addBuildPhase ("PBXFrameworksBuildPhase", target->frameworkIDs); | ||||
} | } | ||||
target->addShellScriptBuildPhase ("Post-build script", getPostBuildScript()); | 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(); | embedAppExtension(); | ||||
addTargetObject (*target); | addTargetObject (*target); | ||||
@@ -1626,9 +1514,9 @@ private: | |||||
void embedAppExtension() const | 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; | StringArray files; | ||||
files.add (auv3Target->mainBuildProductID); | 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) | for (auto& target : targets) | ||||
if (target->type == type) | if (target->type == type) | ||||
@@ -1671,13 +1559,13 @@ private: | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
void addTargetObject (Target& target) const | |||||
void addTargetObject (XCodeTarget& target) const | |||||
{ | { | ||||
String targetName = target.getName(); | String targetName = target.getName(); | ||||
String targetID = target.getID(); | String targetID = target.getID(); | ||||
ValueTree* const v = new ValueTree (targetID); | 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 ("buildConfigurationList", createID (String ("__configList") + targetName), nullptr); | ||||
v->setProperty ("buildPhases", indentParenthesisedList (target.buildPhaseIDs), nullptr); | v->setProperty ("buildPhases", indentParenthesisedList (target.buildPhaseIDs), nullptr); | ||||
@@ -1687,7 +1575,7 @@ private: | |||||
v->setProperty (Ids::name, target.getXCodeSchemeName(), nullptr); | v->setProperty (Ids::name, target.getXCodeSchemeName(), nullptr); | ||||
v->setProperty ("productName", projectName, nullptr); | v->setProperty ("productName", projectName, nullptr); | ||||
if (target.type != Target::AggregateTarget) | |||||
if (target.type != XCodeTarget::AggregateTarget) | |||||
{ | { | ||||
v->setProperty ("productReference", createID (String ("__productFileID") + targetName), nullptr); | v->setProperty ("productReference", createID (String ("__productFileID") + targetName), nullptr); | ||||
@@ -1699,28 +1587,28 @@ private: | |||||
misc.add (v); | misc.add (v); | ||||
} | } | ||||
StringArray getTargetDependencies (const Target& target) const | |||||
StringArray getTargetDependencies (const XCodeTarget& target) const | |||||
{ | { | ||||
StringArray dependencies; | StringArray dependencies; | ||||
if (project.getProjectType().isAudioPlugin()) | 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()); | dependencies.add (auv3Target->getDependencyID()); | ||||
if (Target* sharedCodeTarget = getTargetOfType (Target::SharedCodeTarget)) | |||||
if (XCodeTarget* sharedCodeTarget = getTargetOfType (XCodeTarget::SharedCodeTarget)) | |||||
dependencies.add (sharedCodeTarget->getDependencyID()); | 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) | for (int i = 1; i < targets.size(); ++i) | ||||
dependencies.add (targets[i]->getDependencyID()); | 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()); | dependencies.add (sharedCodeTarget->getDependencyID()); | ||||
} | } | ||||
} | } | ||||
@@ -2099,7 +1987,7 @@ private: | |||||
output << "\t};\n\trootObject = " << createID ("__root") << ";\n}\n"; | 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")); | String fileID (createID (path + "buildref")); | ||||
@@ -2120,7 +2008,7 @@ private: | |||||
return fileID; | 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); | return addBuildFile (path.toUnixStyle(), createFileRefID (path), addToSourceBuildPhase, inhibitWarnings, xcodeTarget); | ||||
} | } | ||||
@@ -2204,7 +2092,7 @@ private: | |||||
} | } | ||||
String addFile (const RelativePath& path, bool shouldBeCompiled, bool shouldBeAddedToBinaryResources, | 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 pathAsString (path.toUnixStyle()); | ||||
const String refID (addFileReference (path.toUnixStyle())); | const String refID (addFileReference (path.toUnixStyle())); | ||||
@@ -2234,7 +2122,7 @@ private: | |||||
if (projectItem.isModuleCode()) | 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); | String rezFileID = addBuildFile (pathAsString, refID, false, false, xcodeTarget); | ||||
xcodeTarget->rezFileIDs.add (rezFileID); | xcodeTarget->rezFileIDs.add (rezFileID); | ||||
@@ -2299,9 +2187,9 @@ private: | |||||
if (path.hasFileExtension (".r")) | if (path.hasFileExtension (".r")) | ||||
return addRezFile (projectItem, path); | return addRezFile (projectItem, path); | ||||
Target* xcodeTarget = nullptr; | |||||
XCodeTarget* xcodeTarget = nullptr; | |||||
if (projectItem.isModuleCode() && projectItem.shouldBeCompiled()) | if (projectItem.isModuleCode() && projectItem.shouldBeCompiled()) | ||||
xcodeTarget = getTargetOfType (getTargetTypeFromFilePath (projectItem.getFile(), false)); | |||||
xcodeTarget = getTargetOfType (project.getTargetTypeFromFilePath (projectItem.getFile(), false)); | |||||
return addFile (path, projectItem.shouldBeCompiled(), | return addFile (path, projectItem.shouldBeCompiled(), | ||||
projectItem.shouldBeAddedToBinaryResources(), | projectItem.shouldBeAddedToBinaryResources(), | ||||
@@ -2357,7 +2245,7 @@ private: | |||||
projectConfigs.add (v); | 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); | ValueTree* v = new ValueTree (listID); | ||||
v->setProperty ("isa", "XCConfigurationList", nullptr); | v->setProperty ("isa", "XCConfigurationList", nullptr); | ||||
@@ -2370,7 +2258,7 @@ private: | |||||
misc.add (v); | 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; | StringArray configIDs; | ||||
@@ -2405,19 +2293,6 @@ private: | |||||
misc.add (v); | 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 | void removeMismatchedXcuserdata() const | ||||
{ | { | ||||
@@ -173,15 +173,11 @@ bool ProjectExporter::canProjectBeLaunched (Project* project) | |||||
//============================================================================== | //============================================================================== | ||||
ProjectExporter::ProjectExporter (Project& p, const ValueTree& state) | ProjectExporter::ProjectExporter (Project& p, const ValueTree& state) | ||||
: makefileIsDLL (false), | |||||
msvcIsDLL (false), | |||||
msvcIsWindowsSubsystem (true), | |||||
settings (state), | |||||
: settings (state), | |||||
project (p), | project (p), | ||||
projectType (p.getProjectType()), | projectType (p.getProjectType()), | ||||
projectName (p.getTitle()), | 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) | 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"), | 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 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"), | 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 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"), | 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."); | "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() | 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() | 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"); | makefileExtraLinkerFlags.add ("-Wl,--no-undefined"); | ||||
if (supportsAAX() && getProject().shouldBuildAAX().getValue()) | |||||
if (shouldBuildTargetType (ProjectType::Target::AAXPlugIn)) | |||||
addAAXFoldersToPath(); | addAAXFoldersToPath(); | ||||
// Note: RTAS paths are platform-dependent, impl -> addPlatformSpecificSettingsForProjectType | // 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(), | StringPairArray defs (mergePreprocessorDefs (config.getAllPreprocessorDefs(), | ||||
parsePreprocessorDefs (getExporterPreprocessorDefsString()))); | parsePreprocessorDefs (getExporterPreprocessorDefsString()))); | ||||
addDefaultPreprocessorDefs (defs); | addDefaultPreprocessorDefs (defs); | ||||
addTargetSpecificPreprocessorDefs (defs, targetType); | |||||
return defs; | return defs; | ||||
} | } | ||||
@@ -363,6 +353,31 @@ StringPairArray ProjectExporter::getAllPreprocessorDefs() const | |||||
return defs; | 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 | void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const | ||||
{ | { | ||||
defs.set (getExporterIdentifierMacro(), "1"); | defs.set (getExporterIdentifierMacro(), "1"); | ||||
@@ -370,9 +385,10 @@ void ProjectExporter::addDefaultPreprocessorDefs (StringPairArray& defs) const | |||||
defs.set ("JUCE_APP_VERSION_HEX", project.getVersionAsHex()); | 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() | void ProjectExporter::copyMainGroupFromProject() | ||||
@@ -393,14 +409,24 @@ Project::Item& ProjectExporter::getModulesGroup() | |||||
return *modulesGroup; | 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) | Value ProjectExporter::getPathForModuleValue (const String& moduleID) | ||||
@@ -810,16 +836,24 @@ StringArray ProjectExporter::BuildConfiguration::getHeaderSearchPaths() const | |||||
StringArray ProjectExporter::BuildConfiguration::getLibrarySearchPaths() 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 ProjectExporter::BuildConfiguration::getGCCLibraryPathFlags() const | ||||
{ | { | ||||
String s; | 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; | return s; | ||||
} | } | ||||
@@ -84,14 +84,21 @@ public: | |||||
virtual bool isOSX() const = 0; | virtual bool isOSX() const = 0; | ||||
virtual bool isiOS() const = 0; | virtual bool isiOS() const = 0; | ||||
//============================================================================== | |||||
// cross-platform audio plug-ins supported by exporter | // 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 | bool mayCompileOnCurrentOS() const | ||||
@@ -150,6 +157,7 @@ public: | |||||
RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const; | RelativePath rebaseFromProjectFolderToBuildTarget (const RelativePath& path) const; | ||||
void addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index = -1); | void addToExtraSearchPaths (const RelativePath& pathFromProjectFolder, int index = -1); | ||||
void addToModuleLibPaths (const RelativePath& pathFromProjectFolder); | |||||
Value getBigIconImageItemID() { return getSetting (Ids::bigIcon); } | Value getBigIconImageItemID() { return getSetting (Ids::bigIcon); } | ||||
Value getSmallIconImageItemID() { return getSetting (Ids::smallIcon); } | Value getSmallIconImageItemID() { return getSetting (Ids::smallIcon); } | ||||
@@ -187,19 +195,16 @@ public: | |||||
Project::Item& getModulesGroup(); | Project::Item& getModulesGroup(); | ||||
//============================================================================== | //============================================================================== | ||||
String makefileTargetSuffix; | |||||
bool makefileIsDLL; | |||||
StringArray linuxLibs, linuxPackages, makefileExtraLinkerFlags; | StringArray linuxLibs, linuxPackages, makefileExtraLinkerFlags; | ||||
//============================================================================== | //============================================================================== | ||||
String msvcTargetSuffix; | |||||
StringPairArray msvcExtraPreprocessorDefs; | StringPairArray msvcExtraPreprocessorDefs; | ||||
bool msvcIsDLL, msvcIsWindowsSubsystem; | |||||
String msvcDelayLoadedDLLs; | String msvcDelayLoadedDLLs; | ||||
StringArray mingwLibs; | |||||
StringArray mingwLibs, windowsLibs; | |||||
//============================================================================== | //============================================================================== | ||||
StringArray extraSearchPaths; | StringArray extraSearchPaths; | ||||
StringArray moduleLibSearchPaths; | |||||
//============================================================================== | //============================================================================== | ||||
class BuildConfiguration : public ReferenceCountedObject | class BuildConfiguration : public ReferenceCountedObject | ||||
@@ -213,6 +218,8 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
virtual void createConfigProperties (PropertyListBuilder&) = 0; | virtual void createConfigProperties (PropertyListBuilder&) = 0; | ||||
virtual var getDefaultOptimisationLevel() const = 0; | virtual var getDefaultOptimisationLevel() const = 0; | ||||
virtual String getLibrarySubdirPath() const { return String(); } | |||||
//============================================================================== | //============================================================================== | ||||
Value getNameValue() { return getValue (Ids::name); } | Value getNameValue() { return getValue (Ids::name); } | ||||
@@ -316,10 +323,12 @@ public: | |||||
String getExporterPreprocessorDefsString() const { return getSettingString (Ids::extraDefs); } | String getExporterPreprocessorDefsString() const { return getSettingString (Ids::extraDefs); } | ||||
// includes exporter, project + config defs | // 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.. | // includes exporter + project defs.. | ||||
StringPairArray getAllPreprocessorDefs() const; | StringPairArray getAllPreprocessorDefs() const; | ||||
void addTargetSpecificPreprocessorDefs (StringPairArray& defs, const ProjectType::Target::Type targetType) const; | |||||
String replacePreprocessorTokens (const BuildConfiguration&, const String& sourceString) const; | String replacePreprocessorTokens (const BuildConfiguration&, const String& sourceString) const; | ||||
ValueTree settings; | ValueTree settings; | ||||
@@ -345,7 +354,7 @@ protected: | |||||
mutable Array<Project::Item> itemGroups; | mutable Array<Project::Item> itemGroups; | ||||
void initItemGroups() const; | void initItemGroups() const; | ||||
Project::Item* modulesGroup; | |||||
Project::Item* modulesGroup = nullptr; | |||||
virtual BuildConfiguration::Ptr createBuildConfig (const ValueTree&) const = 0; | virtual BuildConfiguration::Ptr createBuildConfig (const ValueTree&) const = 0; | ||||
@@ -408,6 +417,7 @@ private: | |||||
void addCommonAudioPluginSettings(); | void addCommonAudioPluginSettings(); | ||||
void addVST3FolderToPath(); | void addVST3FolderToPath(); | ||||
void addAAXFoldersToPath(); | void addAAXFoldersToPath(); | ||||
void addProjectPathToBuildPathList (StringArray&, const RelativePath&, int index = -1); | |||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter) | JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProjectExporter) | ||||
}; | }; | ||||
@@ -73,13 +73,13 @@ namespace | |||||
void ProjectSaver::writePluginCharacteristicsFile() | void ProjectSaver::writePluginCharacteristicsFile() | ||||
{ | { | ||||
StringPairArray flags; | 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_Name", valueToStringLiteral (project.getPluginName())); | ||||
flags.set ("JucePlugin_Desc", valueToStringLiteral (project.getPluginDesc())); | flags.set ("JucePlugin_Desc", valueToStringLiteral (project.getPluginDesc())); | ||||
flags.set ("JucePlugin_Manufacturer", valueToStringLiteral (project.getPluginManufacturer())); | 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 | 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()) | if (extraInternalSearchPaths.isNotEmpty()) | ||||
{ | { | ||||
StringArray paths; | StringArray paths; | ||||
paths.addTokens (extraInternalSearchPaths, true); | paths.addTokens (extraInternalSearchPaths, true); | ||||
for (int i = 0; i < paths.size(); ++i) | 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.linuxLibs, moduleInfo.moduleInfo ["linuxLibs"].toString()); | ||||
parseAndAddLibs (exporter.linuxPackages, moduleInfo.moduleInfo ["linuxPackages"].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 | bool LibraryModule::CompileUnit::isNeededForExporter (ProjectExporter& exporter) const | ||||
{ | { | ||||
Project& project = exporter.getProject(); | |||||
if ((hasSuffix (file, "_OSX") && ! exporter.isOSX()) | if ((hasSuffix (file, "_OSX") && ! exporter.isOSX()) | ||||
|| (hasSuffix (file, "_iOS") && ! exporter.isiOS()) | || (hasSuffix (file, "_iOS") && ! exporter.isiOS()) | ||||
|| (hasSuffix (file, "_Windows") && ! exporter.isWindows()) | || (hasSuffix (file, "_Windows") && ! exporter.isWindows()) | ||||
|| (hasSuffix (file, "_Linux") && ! exporter.isLinux()) | || (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 false; | ||||
return exporter.usesMMFiles() ? isCompiledForObjC | return exporter.usesMMFiles() ? isCompiledForObjC | ||||
@@ -24,7 +24,6 @@ | |||||
#include "../jucer_Headers.h" | #include "../jucer_Headers.h" | ||||
#include "jucer_Project.h" | #include "jucer_Project.h" | ||||
#include "jucer_ProjectType.h" | |||||
#include "../Project Saving/jucer_ProjectExporter.h" | #include "../Project Saving/jucer_ProjectExporter.h" | ||||
#include "../Project Saving/jucer_ProjectSaver.h" | #include "../Project Saving/jucer_ProjectSaver.h" | ||||
#include "../Application/jucer_OpenDocumentManager.h" | #include "../Application/jucer_OpenDocumentManager.h" | ||||
@@ -147,13 +146,13 @@ void Project::setMissingAudioPluginDefaultValues() | |||||
{ | { | ||||
const String sanitisedProjectName (CodeHelpers::makeValidIdentifier (getTitle(), false, true, false)); | 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 (getPluginName(), getTitle()); | ||||
setValueIfVoid (getPluginDesc(), getTitle()); | setValueIfVoid (getPluginDesc(), getTitle()); | ||||
@@ -222,10 +221,19 @@ void Project::removeDefunctExporters() | |||||
for (;;) | 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); | 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 | else | ||||
break; | break; | ||||
} | } | ||||
@@ -436,6 +444,98 @@ const ProjectType& Project::getProjectType() const | |||||
return *guiType; | 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) | void Project::createPropertyEditors (PropertyListBuilder& props) | ||||
{ | { | ||||
@@ -515,25 +615,20 @@ void Project::createPropertyEditors (PropertyListBuilder& props) | |||||
void Project::createAudioPluginPropertyEditors (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."); | "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."); | "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."); | "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."); | "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."); | "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."); | "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), | props.add (new TextPropertyComponent (getPluginName(), "Plugin Name", 128, false), | ||||
"The name of your plugin (keep it short!)"); | "The name of your plugin (keep it short!)"); | ||||
@@ -25,8 +25,9 @@ | |||||
#ifndef JUCER_PROJECT_H_INCLUDED | #ifndef JUCER_PROJECT_H_INCLUDED | ||||
#define JUCER_PROJECT_H_INCLUDED | #define JUCER_PROJECT_H_INCLUDED | ||||
#include "jucer_ProjectType.h" | |||||
class ProjectExporter; | class ProjectExporter; | ||||
class ProjectType; | |||||
class LibraryModule; | class LibraryModule; | ||||
class EnabledModuleList; | class EnabledModuleList; | ||||
@@ -95,7 +96,8 @@ public: | |||||
Value getCompanyEmail() { return getProjectValue (Ids::companyEmail); } | 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); } | Value getProjectPreprocessorDefs() { return getProjectValue (Ids::defines); } | ||||
StringPairArray getPreprocessorDefs() const; | StringPairArray getPreprocessorDefs() const; | ||||
@@ -122,13 +124,23 @@ public: | |||||
//============================================================================== | //============================================================================== | ||||
// Some helper methods for audio plugin/host projects. | // 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 getPluginName() { return getProjectValue ("pluginName"); } | ||||
Value getPluginDesc() { return getProjectValue ("pluginDesc"); } | Value getPluginDesc() { return getProjectValue ("pluginDesc"); } | ||||
Value getPluginManufacturer() { return getProjectValue ("pluginManufacturer"); } | Value getPluginManufacturer() { return getProjectValue ("pluginManufacturer"); } | ||||
@@ -158,6 +170,10 @@ public: | |||||
bool isVSTPluginHost(); | bool isVSTPluginHost(); | ||||
bool isVST3PluginHost(); | bool isVST3PluginHost(); | ||||
bool shouldBuildTargetType (ProjectType::Target::Type targetType) const noexcept; | |||||
static ProjectType::Target::Type getTargetTypeFromFilePath (const File& file, bool returnSharedTargetIfNoValidSuffix); | |||||
//============================================================================== | |||||
void updateDeprecatedProjectSettingsInteractively(); | void updateDeprecatedProjectSettingsInteractively(); | ||||
//============================================================================== | //============================================================================== | ||||
@@ -49,6 +49,55 @@ public: | |||||
virtual bool isCommandLineApp() const { return false; } | virtual bool isCommandLineApp() const { return false; } | ||||
virtual bool isAudioPlugin() 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: | protected: | ||||
ProjectType (const String& type, const String& desc); | ProjectType (const String& type, const String& desc); | ||||
@@ -86,32 +135,36 @@ struct ProjectType_GUIApp : public ProjectType | |||||
{ | { | ||||
ProjectType_GUIApp() : ProjectType (getTypeName(), "GUI Application") {} | 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 | struct ProjectType_ConsoleApp : public ProjectType | ||||
{ | { | ||||
ProjectType_ConsoleApp() : ProjectType (getTypeName(), "Console Application") {} | 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 | struct ProjectType_StaticLibrary : public ProjectType | ||||
{ | { | ||||
ProjectType_StaticLibrary() : ProjectType (getTypeName(), "Static Library") {} | 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 | struct ProjectType_DLL : public ProjectType | ||||
{ | { | ||||
ProjectType_DLL() : ProjectType (getTypeName(), "Dynamic Library") {} | 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 | struct ProjectType_AudioPlugin : public ProjectType | ||||
@@ -120,6 +173,27 @@ struct ProjectType_AudioPlugin : public ProjectType | |||||
static const char* getTypeName() noexcept { return "audioplug"; } | static const char* getTypeName() noexcept { return "audioplug"; } | ||||
bool isAudioPlugin() const override { return true; } | 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 (winWarningLevel); | ||||
DECLARE_ID (warningsAreErrors); | DECLARE_ID (warningsAreErrors); | ||||
DECLARE_ID (linuxArchitecture); | DECLARE_ID (linuxArchitecture); | ||||
DECLARE_ID (linuxCodeBlocksArchitecture); | |||||
DECLARE_ID (windowsCodeBlocksArchitecture); | |||||
DECLARE_ID (toolset); | DECLARE_ID (toolset); | ||||
DECLARE_ID (IPPLibrary); | DECLARE_ID (IPPLibrary); | ||||
DECLARE_ID (msvcModuleDefinitionFile); | DECLARE_ID (msvcModuleDefinitionFile); | ||||
@@ -112,7 +114,6 @@ namespace Ids | |||||
DECLARE_ID (jucerVersion); | DECLARE_ID (jucerVersion); | ||||
DECLARE_ID (prebuildCommand); | DECLARE_ID (prebuildCommand); | ||||
DECLARE_ID (postbuildCommand); | DECLARE_ID (postbuildCommand); | ||||
DECLARE_ID (internalPostBuildComamnd); | |||||
DECLARE_ID (generateManifest); | DECLARE_ID (generateManifest); | ||||
DECLARE_ID (useRuntimeLibDLL); | DECLARE_ID (useRuntimeLibDLL); | ||||
DECLARE_ID (wholeProgramOptimisation); | DECLARE_ID (wholeProgramOptimisation); | ||||
@@ -173,7 +174,7 @@ namespace Ids | |||||
DECLARE_ID (iosDevelopmentTeamID); | DECLARE_ID (iosDevelopmentTeamID); | ||||
DECLARE_ID (buildToolsVersion); | DECLARE_ID (buildToolsVersion); | ||||
DECLARE_ID (gradleVersion); | 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 (gradleToolchain); | ||||
DECLARE_ID (gradleToolchainVersion); | DECLARE_ID (gradleToolchainVersion); | ||||
DECLARE_ID (linuxExtraPkgConfig); | DECLARE_ID (linuxExtraPkgConfig); | ||||