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