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