/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmXCodeScheme.h" #include #include #include #include "cmGeneratedFileStream.h" #include "cmGeneratorTarget.h" #include "cmXMLSafe.h" cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, const TestObjects& tests, const std::vector& configList, unsigned int xcVersion) : Target(xcObj) , Tests(tests) , TargetName(xcObj->GetTarget()->GetName()) , ConfigList(configList) , XcodeVersion(xcVersion) { } void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir, const std::string& container) { // Create shared scheme sub-directory tree // std::string xcodeSchemeDir = xcProjDir; xcodeSchemeDir += "/xcshareddata/xcschemes"; cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str()); std::string xcodeSchemeFile = xcodeSchemeDir; xcodeSchemeFile += "/"; xcodeSchemeFile += this->TargetName; xcodeSchemeFile += ".xcscheme"; cmGeneratedFileStream fout(xcodeSchemeFile.c_str()); fout.SetCopyIfDifferent(true); if (!fout) { return; } WriteXCodeXCScheme(fout, container); } void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout, const std::string& container) { cmXMLWriter xout(fout); xout.SetIndentationElement(std::string(3, ' ')); xout.StartDocument(); xout.StartElement("Scheme"); xout.BreakAttributes(); xout.Attribute("LastUpgradeVersion", WriteVersionString()); xout.Attribute("version", "1.3"); WriteBuildAction(xout, container); WriteTestAction(xout, FindConfiguration("Debug"), container); WriteLaunchAction(xout, FindConfiguration("Debug"), container); WriteProfileAction(xout, FindConfiguration("Release")); WriteAnalyzeAction(xout, FindConfiguration("Debug")); WriteArchiveAction(xout, FindConfiguration("Release")); xout.EndElement(); } void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout, const std::string& container) { xout.StartElement("BuildAction"); xout.BreakAttributes(); xout.Attribute("parallelizeBuildables", "YES"); xout.Attribute("buildImplicitDependencies", "YES"); xout.StartElement("BuildActionEntries"); xout.StartElement("BuildActionEntry"); xout.BreakAttributes(); xout.Attribute("buildForTesting", "YES"); xout.Attribute("buildForRunning", "YES"); xout.Attribute("buildForProfiling", "YES"); xout.Attribute("buildForArchiving", "YES"); xout.Attribute("buildForAnalyzing", "YES"); WriteBuildableReference(xout, this->Target, container); xout.EndElement(); // BuildActionEntry xout.EndElement(); // BuildActionEntries xout.EndElement(); // BuildAction } void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout, const std::string& configuration, const std::string& container) { xout.StartElement("TestAction"); xout.BreakAttributes(); xout.Attribute("buildConfiguration", configuration); xout.Attribute("selectedDebuggerIdentifier", "Xcode.DebuggerFoundation.Debugger.LLDB"); xout.Attribute("selectedLauncherIdentifier", "Xcode.DebuggerFoundation.Launcher.LLDB"); xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); xout.StartElement("Testables"); for (auto test : this->Tests) { xout.StartElement("TestableReference"); xout.BreakAttributes(); xout.Attribute("skipped", "NO"); WriteBuildableReference(xout, test, container); xout.EndElement(); // TestableReference } xout.EndElement(); if (IsTestable()) { xout.StartElement("MacroExpansion"); WriteBuildableReference(xout, this->Target, container); xout.EndElement(); // MacroExpansion } xout.StartElement("AdditionalOptions"); xout.EndElement(); xout.EndElement(); // TestAction } void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, const std::string& configuration, const std::string& container) { xout.StartElement("LaunchAction"); xout.BreakAttributes(); xout.Attribute("buildConfiguration", configuration); xout.Attribute("selectedDebuggerIdentifier", "Xcode.DebuggerFoundation.Debugger.LLDB"); xout.Attribute("selectedLauncherIdentifier", "Xcode.DebuggerFoundation.Launcher.LLDB"); xout.Attribute("launchStyle", "0"); xout.Attribute("useCustomWorkingDirectory", "NO"); xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); xout.Attribute("debugDocumentVersioning", "YES"); xout.Attribute("debugServiceExtension", "internal"); xout.Attribute("allowLocationSimulation", "YES"); if (IsExecutable(this->Target)) { xout.StartElement("BuildableProductRunnable"); xout.BreakAttributes(); xout.Attribute("runnableDebuggingMode", "0"); } else { xout.StartElement("MacroExpansion"); } WriteBuildableReference(xout, this->Target, container); xout.EndElement(); // MacroExpansion xout.StartElement("AdditionalOptions"); xout.EndElement(); xout.EndElement(); // LaunchAction } void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout, const std::string& configuration) { xout.StartElement("ProfileAction"); xout.BreakAttributes(); xout.Attribute("buildConfiguration", configuration); xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES"); xout.Attribute("savedToolIdentifier", ""); xout.Attribute("useCustomWorkingDirectory", "NO"); xout.Attribute("debugDocumentVersioning", "YES"); xout.EndElement(); } void cmXCodeScheme::WriteAnalyzeAction(cmXMLWriter& xout, const std::string& configuration) { xout.StartElement("AnalyzeAction"); xout.BreakAttributes(); xout.Attribute("buildConfiguration", configuration); xout.EndElement(); } void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout, const std::string& configuration) { xout.StartElement("ArchiveAction"); xout.BreakAttributes(); xout.Attribute("buildConfiguration", configuration); xout.Attribute("revealArchiveInOrganizer", "YES"); xout.EndElement(); } void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout, const cmXCodeObject* xcObj, const std::string& container) { xout.StartElement("BuildableReference"); xout.BreakAttributes(); xout.Attribute("BuildableIdentifier", "primary"); xout.Attribute("BlueprintIdentifier", xcObj->GetId()); xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName()); xout.Attribute("BlueprintName", xcObj->GetTarget()->GetName()); xout.Attribute("ReferencedContainer", "container:" + container); xout.EndElement(); } std::string cmXCodeScheme::WriteVersionString() { std::ostringstream v; v << std::setfill('0') << std::setw(4) << this->XcodeVersion * 10; return v.str(); } std::string cmXCodeScheme::FindConfiguration(const std::string& name) { // Try to find the desired configuration by name, // and if it's not found return first from the list // if (std::find(this->ConfigList.begin(), this->ConfigList.end(), name) == this->ConfigList.end() && !this->ConfigList.empty()) { return this->ConfigList[0]; } return name; } bool cmXCodeScheme::IsTestable() const { return !this->Tests.empty() || IsExecutable(this->Target); } bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target) { cmGeneratorTarget* gt = target->GetTarget(); if (!gt) { cmSystemTools::Error("Error no target on xobject\n"); return false; } return gt->GetType() == cmStateEnums::EXECUTABLE; }