| @@ -303,10 +303,8 @@ private: | |||
| if (forDebug) | |||
| flags << " -g"; | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| if (config->isDebug() == forDebug) | |||
| { | |||
| flags << createIncludePathFlags (*config); | |||
| @@ -327,10 +325,8 @@ private: | |||
| defines.set ("NDEBUG", "1"); | |||
| } | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| if (config->isDebug() == forDebug) | |||
| { | |||
| flags << " -O" << config->getGCCOptimisationFlag(); | |||
| @@ -210,19 +210,18 @@ protected: | |||
| << "Global" << newLine | |||
| << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution" << newLine; | |||
| int i; | |||
| for (i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator i (*this); i.next();) | |||
| { | |||
| const String configName (createConfigName (*getConfiguration(i))); | |||
| const String configName (createConfigName (*i)); | |||
| out << "\t\t" << configName << " = " << configName << newLine; | |||
| } | |||
| out << "\tEndGlobalSection" << newLine | |||
| << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution" << newLine; | |||
| for (i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator i (*this); i.next();) | |||
| { | |||
| const String configName (createConfigName (*getConfiguration(i))); | |||
| const String configName (createConfigName (*i)); | |||
| out << "\t\t" << projectGUID << "." << configName << ".ActiveCfg = " << configName << newLine; | |||
| out << "\t\t" << projectGUID << "." << configName << ".Build.0 = " << configName << newLine; | |||
| } | |||
| @@ -493,10 +492,10 @@ protected: | |||
| if (excludeFromBuild || useStdcall) | |||
| { | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator i (*this); i.next();) | |||
| { | |||
| XmlElement* fileConfig = fileXml->createNewChildElement ("FileConfiguration"); | |||
| fileConfig->setAttribute ("Name", createConfigName (*getConfiguration (i))); | |||
| fileConfig->setAttribute ("Name", createConfigName (*i)); | |||
| if (excludeFromBuild) | |||
| fileConfig->setAttribute ("ExcludedFromBuild", "true"); | |||
| @@ -721,8 +720,8 @@ protected: | |||
| void createConfigs (XmlElement& xml) | |||
| { | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| createConfig (*xml.createNewChildElement ("Configuration"), *getConfiguration(i)); | |||
| for (ConfigIterator i (*this); i.next();) | |||
| createConfig (*xml.createNewChildElement ("Configuration"), *i); | |||
| } | |||
| //============================================================================== | |||
| @@ -857,9 +856,8 @@ private: | |||
| << "!MESSAGE Possible choices for configuration are:" << newLine | |||
| << "!MESSAGE " << newLine; | |||
| int i; | |||
| for (i = 0; i < getNumConfigurations(); ++i) | |||
| out << "!MESSAGE \"" << createConfigName (*getConfiguration (i)) << "\" (based on " << targetType << ")" << newLine; | |||
| for (ConfigIterator i (*this); i.next();) | |||
| out << "!MESSAGE \"" << createConfigName (*i) << "\" (based on " << targetType << ")" << newLine; | |||
| out << "!MESSAGE " << newLine | |||
| << "# Begin Project" << newLine | |||
| @@ -872,9 +870,8 @@ private: | |||
| String targetList; | |||
| for (i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| const String configName (createConfigName (*config)); | |||
| targetList << "# Name \"" << configName << '"' << newLine; | |||
| @@ -885,7 +882,7 @@ private: | |||
| const bool isDebug = (bool) config->isDebug().getValue(); | |||
| const String extraDebugFlags (isDebug ? "/Gm /ZI /GZ" : ""); | |||
| out << (i == 0 ? "!IF" : "!ELSEIF") << " \"$(CFG)\" == \"" << configName << '"' << newLine | |||
| out << (config.index == 0 ? "!IF" : "!ELSEIF") << " \"$(CFG)\" == \"" << configName << '"' << newLine | |||
| << "# PROP BASE Use_MFC 0" << newLine | |||
| << "# PROP BASE Use_Debug_Libraries " << (isDebug ? "1" : "0") << newLine | |||
| << "# PROP BASE Output_Dir \"" << binariesPath << '"' << newLine | |||
| @@ -996,34 +993,14 @@ private: | |||
| void writeDSWFile (OutputStream& out) | |||
| { | |||
| out << "Microsoft Developer Studio Workspace File, Format Version 6.00 " << newLine; | |||
| /*if (! project.isUsingWrapperFiles()) | |||
| { | |||
| out << "Project: \"JUCE\"= ..\\JUCE.dsp - Package Owner=<4>" << newLine | |||
| << "Package=<5>" << newLine | |||
| << "{{{" << newLine | |||
| << "}}}" << newLine | |||
| << "Package=<4>" << newLine | |||
| << "{{{" << newLine | |||
| << "}}}" << newLine; | |||
| }*/ | |||
| out << "Project: \"" << projectName << "\" = .\\" << getDSPFile().getFileName() << " - Package Owner=<4>" << newLine | |||
| out << "Microsoft Developer Studio Workspace File, Format Version 6.00 " << newLine | |||
| << "Project: \"" << projectName << "\" = .\\" << getDSPFile().getFileName() << " - Package Owner=<4>" << newLine | |||
| << "Package=<5>" << newLine | |||
| << "{{{" << newLine | |||
| << "}}}" << newLine | |||
| << "Package=<4>" << newLine | |||
| << "{{{" << newLine; | |||
| /*if (! project.isUsingWrapperFiles()) | |||
| { | |||
| out << " Begin Project Dependency" << newLine | |||
| << " Project_Dep_Name JUCE" << newLine | |||
| << " End Project Dependency" << newLine; | |||
| }*/ | |||
| out << "}}}" << newLine | |||
| << "{{{" << newLine | |||
| << "}}}" << newLine | |||
| << "Global:" << newLine | |||
| << "Package=<5>" << newLine | |||
| << "{{{" << newLine | |||
| @@ -1161,10 +1138,8 @@ protected: | |||
| XmlElement* configsGroup = projectXml.createNewChildElement ("ItemGroup"); | |||
| configsGroup->setAttribute ("Label", "ProjectConfigurations"); | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| XmlElement* e = configsGroup->createNewChildElement ("ProjectConfiguration"); | |||
| e->setAttribute ("Include", createConfigName (*config)); | |||
| e->createNewChildElement ("Configuration")->addTextElement (config->getName().toString()); | |||
| @@ -1183,10 +1158,8 @@ protected: | |||
| imports->setAttribute ("Project", "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"); | |||
| } | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| XmlElement* e = projectXml.createNewChildElement ("PropertyGroup"); | |||
| setConditionAttribute (*e, *config); | |||
| e->setAttribute ("Label", "Configuration"); | |||
| @@ -1229,10 +1202,8 @@ protected: | |||
| XmlElement* props = projectXml.createNewChildElement ("PropertyGroup"); | |||
| props->createNewChildElement ("_ProjectFileVersion")->addTextElement ("10.0.30319.1"); | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| XmlElement* outdir = props->createNewChildElement ("OutDir"); | |||
| setConditionAttribute (*outdir, *config); | |||
| outdir->addTextElement (getConfigTargetPath (*config) + "\\"); | |||
| @@ -1247,9 +1218,8 @@ protected: | |||
| } | |||
| } | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration(i)); | |||
| String binariesPath (getConfigTargetPath (*config)); | |||
| String intermediatesPath (getIntermediatesPath (*config)); | |||
| const bool isDebug = (bool) config->isDebug().getValue(); | |||
| @@ -1333,6 +1303,26 @@ protected: | |||
| bsc->createNewChildElement ("SuppressStartupBanner")->addTextElement ("true"); | |||
| bsc->createNewChildElement ("OutputFile")->addTextElement (FileHelpers::windowsStylePath (intermediatesPath + "/" + binaryName + ".bsc")); | |||
| } | |||
| if (msvcPostBuildCommand.isNotEmpty()) | |||
| { | |||
| XmlElement* bsc = group->createNewChildElement ("PostBuildEvent"); | |||
| bsc->createNewChildElement ("Command")->addTextElement (msvcPostBuildCommand); | |||
| } | |||
| //xxx | |||
| // <PreBuildEvent> | |||
| // <Command>asd</Command> | |||
| // </PreBuildEvent> | |||
| // <PreLinkEvent> | |||
| // <Command>dfg</Command> | |||
| // </PreLinkEvent> | |||
| // <CustomBuildStep> | |||
| // <Command>abc</Command> | |||
| // </CustomBuildStep> | |||
| // <CustomBuildStep> | |||
| // <Outputs>xyz</Outputs> | |||
| // </CustomBuildStep> | |||
| } | |||
| { | |||
| @@ -285,9 +285,8 @@ private: | |||
| << "DEPFLAGS := $(if $(word 2, $(TARGET_ARCH)), , -MMD)" << newLine | |||
| << newLine; | |||
| int i; | |||
| for (i = 0; i < getNumConfigurations(); ++i) | |||
| writeConfig (out, *getConfiguration(i)); | |||
| for (ConfigIterator config (*this); config.next();) | |||
| writeConfig (out, *config); | |||
| writeObjects (out, files); | |||
| @@ -309,7 +308,7 @@ private: | |||
| << "\t-@rm -rf $(OBJDIR)" << newLine | |||
| << newLine; | |||
| for (i = 0; i < files.size(); ++i) | |||
| for (int i = 0; i < files.size(); ++i) | |||
| { | |||
| if (shouldFileBeCompiledByDefault (files.getReference(i))) | |||
| { | |||
| @@ -277,10 +277,8 @@ private: | |||
| addGroup (createID ("__mainsourcegroup"), "Source", topLevelGroupIDs); | |||
| } | |||
| for (int i = 0; i < getNumConfigurations(); ++i) | |||
| for (ConfigIterator config (*this); config.next();) | |||
| { | |||
| const BuildConfiguration::Ptr config (getConfiguration (i)); | |||
| addProjectConfig (config->getName().getValue(), getProjectSettings (*config)); | |||
| addTargetConfig (config->getName().getValue(), getTargetSettings (dynamic_cast <XcodeBuildConfiguration&> (*config))); | |||
| } | |||
| @@ -114,15 +114,14 @@ ProjectExporter* ProjectExporter::createPlatformDefaultExporter (Project& projec | |||
| ScopedPointer <ProjectExporter> best; | |||
| int bestPref = 0; | |||
| for (int i = 0; i < project.getNumExporters(); ++i) | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| ScopedPointer <ProjectExporter> exp (project.createExporter (i)); | |||
| const int pref = exp->getLaunchPreferenceOrderForCurrentOS(); | |||
| const int pref = exporter->getLaunchPreferenceOrderForCurrentOS(); | |||
| if (pref > bestPref) | |||
| { | |||
| bestPref = pref; | |||
| best = exp; | |||
| best = exporter.exporter; | |||
| } | |||
| } | |||
| @@ -180,13 +180,39 @@ public: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BuildConfiguration); | |||
| }; | |||
| int getNumConfigurations() const; | |||
| BuildConfiguration::Ptr getConfiguration (int index) const; | |||
| void addNewConfiguration (const BuildConfiguration* configToCopy); | |||
| void deleteConfiguration (int index); | |||
| bool hasConfigurationNamed (const String& name) const; | |||
| String getUniqueConfigName (String name) const; | |||
| //============================================================================== | |||
| struct ConfigIterator | |||
| { | |||
| ConfigIterator (ProjectExporter& exporter_) : index (-1), exporter (exporter_) {} | |||
| bool next() | |||
| { | |||
| if (++index >= exporter.getNumConfigurations()) | |||
| return false; | |||
| config = exporter.getConfiguration (index); | |||
| return true; | |||
| } | |||
| BuildConfiguration& operator*() const { return *config; } | |||
| BuildConfiguration* operator->() const { return config; } | |||
| BuildConfiguration::Ptr config; | |||
| int index; | |||
| private: | |||
| ProjectExporter& exporter; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConfigIterator); | |||
| }; | |||
| int getNumConfigurations() const; | |||
| BuildConfiguration::Ptr getConfiguration (int index) const; | |||
| ValueTree getConfigurations() const; | |||
| void createDefaultConfigs(); | |||
| @@ -413,9 +413,8 @@ private: | |||
| // keep a copy of the basic generated files group, as each exporter may modify it. | |||
| const ValueTree originalGeneratedGroup (generatedFilesGroup.state.createCopy()); | |||
| for (int i = project.getNumExporters(); --i >= 0;) | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| ScopedPointer <ProjectExporter> exporter (project.createExporter (i)); | |||
| std::cout << "Writing files for: " << exporter->getName() << std::endl; | |||
| if (exporter->getTargetFolder().createDirectory()) | |||
| @@ -456,21 +456,17 @@ void LibraryModule::createLocalHeaderWrapper (ProjectSaver& projectSaver, const | |||
| << newLine; | |||
| StringArray paths, guards; | |||
| for (int i = project.getNumExporters(); --i >= 0;) | |||
| { | |||
| ScopedPointer <ProjectExporter> exporter (project.createExporter (i)); | |||
| if (exporter != nullptr) | |||
| { | |||
| const RelativePath headerFromProject (getModuleRelativeToProject (*exporter) | |||
| .getChildFile (originalHeader.getFileName())); | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| const RelativePath headerFromProject (getModuleRelativeToProject (*exporter) | |||
| .getChildFile (originalHeader.getFileName())); | |||
| const RelativePath fileFromHere (headerFromProject.rebased (project.getFile().getParentDirectory(), | |||
| localHeader.getParentDirectory(), RelativePath::unknown)); | |||
| const RelativePath fileFromHere (headerFromProject.rebased (project.getFile().getParentDirectory(), | |||
| localHeader.getParentDirectory(), RelativePath::unknown)); | |||
| paths.add (fileFromHere.toUnixStyle().quoted()); | |||
| guards.add ("defined (" + exporter->getExporterIdentifierMacro() + ")"); | |||
| } | |||
| paths.add (fileFromHere.toUnixStyle().quoted()); | |||
| guards.add ("defined (" + exporter->getExporterIdentifierMacro() + ")"); | |||
| } | |||
| writeGuardedInclude (out, paths, guards); | |||
| @@ -54,16 +54,9 @@ static void createFileCreationOptionComboBox (Component& setupComp, | |||
| static void setExecutableNameForAllTargets (Project& project, const String& exeName) | |||
| { | |||
| for (int j = project.getNumExporters(); --j >= 0;) | |||
| { | |||
| ScopedPointer<ProjectExporter> exporter (project.createExporter(j)); | |||
| if (exporter != nullptr) | |||
| { | |||
| for (int i = exporter->getNumConfigurations(); --i >= 0;) | |||
| exporter->getConfiguration(i)->getTargetBinaryName() = exeName; | |||
| } | |||
| } | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| for (ProjectExporter::ConfigIterator config (*exporter); config.next();) | |||
| config->getTargetBinaryName() = exeName; | |||
| } | |||
| //============================================================================== | |||
| @@ -112,13 +112,9 @@ void Project::setMissingDefaultValues() | |||
| updateOldStyleConfigList(); | |||
| for (int i = 0; i < getNumExporters(); ++i) | |||
| { | |||
| ScopedPointer<ProjectExporter> exporter (createExporter(i)); | |||
| if (exporter != nullptr && exporter->getNumConfigurations() == 0) | |||
| for (Project::ExporterIterator exporter (*this); exporter.next();) | |||
| if (exporter->getNumConfigurations() == 0) | |||
| exporter->createDefaultConfigs(); | |||
| } | |||
| if (! projectRoot.getChildWithName (Tags::exporters).isValid()) | |||
| createDefaultExporters(); | |||
| @@ -140,11 +136,9 @@ void Project::updateOldStyleConfigList() | |||
| { | |||
| projectRoot.removeChild (deprecatedConfigsList, nullptr); | |||
| for (int i = 0; i < getNumExporters(); ++i) | |||
| for (Project::ExporterIterator exporter (*this); exporter.next();) | |||
| { | |||
| ScopedPointer<ProjectExporter> exporter (createExporter(i)); | |||
| if (exporter != nullptr && exporter->getNumConfigurations() == 0) | |||
| if (exporter->getNumConfigurations() == 0) | |||
| { | |||
| ValueTree newConfigs (deprecatedConfigsList.createCopy()); | |||
| @@ -961,3 +955,23 @@ String Project::getFileTemplate (const String& templateName) | |||
| return String::fromUTF8 (data, dataSize); | |||
| } | |||
| //============================================================================== | |||
| Project::ExporterIterator::ExporterIterator (Project& project_) : index (-1), project (project_) {} | |||
| Project::ExporterIterator::~ExporterIterator() {} | |||
| bool Project::ExporterIterator::next() | |||
| { | |||
| if (++index >= project.getNumExporters()) | |||
| return false; | |||
| exporter = project.createExporter (index); | |||
| if (exporter == nullptr) | |||
| { | |||
| jassertfalse; // corrupted project file? | |||
| return next(); | |||
| } | |||
| return true; | |||
| } | |||
| @@ -194,6 +194,24 @@ public: | |||
| void deleteExporter (int index); | |||
| void createDefaultExporters(); | |||
| struct ExporterIterator | |||
| { | |||
| ExporterIterator (Project& project); | |||
| ~ExporterIterator(); | |||
| bool next(); | |||
| ProjectExporter& operator*() const { return *exporter; } | |||
| ProjectExporter* operator->() const { return exporter; } | |||
| ScopedPointer<ProjectExporter> exporter; | |||
| int index; | |||
| private: | |||
| Project& project; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ExporterIterator); | |||
| }; | |||
| //============================================================================== | |||
| struct ConfigFlag | |||
| { | |||
| @@ -519,37 +519,31 @@ public: | |||
| { | |||
| exporters.clear(); | |||
| for (int i = 0; i < project.getNumExporters(); ++i) | |||
| for (Project::ExporterIterator exporter (project); exporter.next();) | |||
| { | |||
| PropertyGroup* exporterGroup = exporters.createGroup(); | |||
| exporterGroup->backgroundColour = Colours::white.withAlpha (0.3f); | |||
| exporterGroup->addDeleteButton ("exporter " + String (i), "Deletes this export target."); | |||
| exporterGroup->addDeleteButton ("exporter " + String (exporter.index), "Deletes this export target."); | |||
| ScopedPointer <ProjectExporter> exp (project.createExporter (i)); | |||
| jassert (exp != nullptr); | |||
| if (exp != nullptr) | |||
| { | |||
| PropertyListBuilder props; | |||
| exp->createPropertyEditors (props); | |||
| PropertyListBuilder props; | |||
| exporter->createPropertyEditors (props); | |||
| PropertyGroupList* configList = new PropertyGroupList ("Configurations", "Add a New Configuration", false, true); | |||
| props.add (configList); | |||
| exporterGroup->setProperties (props); | |||
| PropertyGroupList* configList = new PropertyGroupList ("Configurations", "Add a New Configuration", false, true); | |||
| props.add (configList); | |||
| exporterGroup->setProperties (props); | |||
| configList->createNewButton.setName ("newconfig " + String (i)); | |||
| configList->createNewButton.setName ("newconfig " + String (exporter.index)); | |||
| for (int j = 0; j < exp->getNumConfigurations(); ++j) | |||
| { | |||
| PropertyGroup* configGroup = configList->createGroup(); | |||
| for (ProjectExporter::ConfigIterator config (*exporter); config.next();) | |||
| { | |||
| PropertyGroup* configGroup = configList->createGroup(); | |||
| if (exp->getNumConfigurations() > 1) | |||
| configGroup->addDeleteButton ("config " + String (i) + "/" + String (j), "Deletes this configuration."); | |||
| if (exporter->getNumConfigurations() > 1) | |||
| configGroup->addDeleteButton ("config " + String (exporter.index) + "/" + String (config.index), "Deletes this configuration."); | |||
| PropertyListBuilder configProps; | |||
| exp->getConfiguration(j)->createPropertyEditors (configProps); | |||
| configGroup->setProperties (configProps); | |||
| } | |||
| PropertyListBuilder configProps; | |||
| config->createPropertyEditors (configProps); | |||
| configGroup->setProperties (configProps); | |||
| } | |||
| } | |||
| } | |||
| @@ -507,8 +507,8 @@ public: | |||
| /** Repaints one of the rows. | |||
| This is a lightweight alternative to calling updateContent, and just causes a | |||
| repaint of the row's area. | |||
| This does not invoke updateContent(), it just invokes a straightforward repaint | |||
| for the area covered by this row. | |||
| */ | |||
| void repaintRow (int rowNumber) noexcept; | |||