summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-properties.7.rst1
-rw-r--r--Help/prop_gbl/XCODE_GENERATE_SCHEME.rst11
-rw-r--r--Help/release/dev/cmake-xcode-schemes.rst6
-rw-r--r--Source/CMakeLists.txt1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx28
-rw-r--r--Source/cmGlobalXCodeGenerator.h3
-rw-r--r--Source/cmXCodeScheme.cxx206
-rw-r--r--Source/cmXCodeScheme.h46
8 files changed, 302 insertions, 0 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index a3b6e6b..f31b0f8 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -45,6 +45,7 @@ Properties of Global Scope
/prop_gbl/TARGET_SUPPORTS_SHARED_LIBS
/prop_gbl/USE_FOLDERS
/prop_gbl/XCODE_EMIT_EFFECTIVE_PLATFORM_NAME
+ /prop_gbl/XCODE_GENERATE_SCHEME
.. _`Directory Properties`:
diff --git a/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst
new file mode 100644
index 0000000..be8b5b0
--- /dev/null
+++ b/Help/prop_gbl/XCODE_GENERATE_SCHEME.rst
@@ -0,0 +1,11 @@
+XCODE_GENERATE_SCHEME
+---------------------
+
+If enabled, the Xcode generator will generate schema files. Those are
+are useful to invoke analyze, archive, build-for-testing and test
+actions from the command line.
+
+.. note::
+
+ The Xcode Schema Generator is still experimental and subject to
+ change.
diff --git a/Help/release/dev/cmake-xcode-schemes.rst b/Help/release/dev/cmake-xcode-schemes.rst
new file mode 100644
index 0000000..27c19d7
--- /dev/null
+++ b/Help/release/dev/cmake-xcode-schemes.rst
@@ -0,0 +1,6 @@
+cmake-xcode-schemes
+-------------------
+
+* The :generator:`Xcode` generator got the ability to create schema files.
+ This is still an experimental feature and can be activated by setting the
+ :prop_gbl:`XCODE_GENERATE_SCHEME` global property to a ``TRUE`` value.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 3b49f72..76b98fc 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -639,6 +639,7 @@ if(APPLE)
set(SRCS ${SRCS}
cmXCodeObject.cxx
cmXCode21Object.cxx
+ cmXCodeScheme.cxx
cmGlobalXCodeGenerator.cxx
cmGlobalXCodeGenerator.h
cmLocalXCodeGenerator.cxx
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 5167205..d1b6130 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -28,6 +28,7 @@
#include "cmTarget.h"
#include "cmXCode21Object.h"
#include "cmXCodeObject.h"
+#include "cmXCodeScheme.h"
#include "cm_auto_ptr.hxx"
#include "cmake.h"
@@ -3337,6 +3338,15 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
return;
}
this->WriteXCodePBXProj(fout, root, generators);
+
+ // Since the lowest available Xcode version for testing was 7.0,
+ // I'm setting this as a limit then
+ if (this->GetCMakeInstance()->GetState()->GetGlobalPropertyAsBool(
+ "XCODE_GENERATE_SCHEME") &&
+ this->XcodeVersion >= 70) {
+ this->OutputXCodeSharedSchemes(xcodeDir, root);
+ }
+
this->ClearXCodeObjects();
// Since this call may have created new cache entries, save the cache:
@@ -3345,6 +3355,24 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
root->GetBinaryDirectory());
}
+void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
+ const std::string& xcProjDir, cmLocalGenerator* root)
+{
+ for (std::vector<cmXCodeObject*>::const_iterator i =
+ this->XCodeObjects.begin();
+ i != this->XCodeObjects.end(); ++i) {
+ cmXCodeObject* obj = *i;
+ if (obj->GetType() == cmXCodeObject::OBJECT &&
+ (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
+ obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
+ cmXCodeScheme schm(obj, this->CurrentConfigurationTypes,
+ this->XcodeVersion);
+ schm.WriteXCodeSharedScheme(xcProjDir,
+ root->GetCurrentSourceDirectory());
+ }
+ }
+}
+
void cmGlobalXCodeGenerator::WriteXCodePBXProj(std::ostream& fout,
cmLocalGenerator*,
std::vector<cmLocalGenerator*>&)
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 1aaf9c7..c9157b0 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -165,6 +165,9 @@ private:
std::vector<cmLocalGenerator*>& generators);
void OutputXCodeProject(cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
+ // Write shared scheme files for all the native targets
+ void OutputXCodeSharedSchemes(const std::string& xcProjDir,
+ cmLocalGenerator* root);
void WriteXCodePBXProj(std::ostream& fout, cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators);
cmXCodeObject* CreateXCodeFileReferenceFromPath(const std::string& fullpath,
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
new file mode 100644
index 0000000..3c8c0b7
--- /dev/null
+++ b/Source/cmXCodeScheme.cxx
@@ -0,0 +1,206 @@
+/* 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 <iomanip>
+#include <sstream>
+
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmXMLSafe.h"
+
+cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
+ const std::vector<std::string>& configList,
+ unsigned int xcVersion)
+ : TargetName(xcObj->GetTarget()->GetName())
+ , TargetId(xcObj->GetId())
+ , ConfigList(configList)
+ , XcodeVersion(xcVersion)
+{
+}
+
+void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
+ const std::string sourceRoot)
+{
+ // 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;
+ }
+
+ std::string xcProjRelDir = xcProjDir.substr(sourceRoot.size() + 1);
+ WriteXCodeXCScheme(fout, xcProjRelDir);
+}
+
+void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
+ const std::string& xcProjDir)
+{
+ cmXMLWriter xout(fout);
+ xout.StartDocument();
+
+ xout.StartElement("Scheme");
+ xout.BreakAttributes();
+ xout.Attribute("LastUpgradeVersion", WriteVersionString());
+ xout.Attribute("version", "1.3");
+
+ WriteBuildAction(xout, xcProjDir);
+ WriteTestAction(xout, FindConfiguration("Debug"));
+ WriteLaunchAction(xout, FindConfiguration("Debug"), xcProjDir);
+ WriteProfileAction(xout, FindConfiguration("Release"));
+ WriteAnalyzeAction(xout, FindConfiguration("Debug"));
+ WriteArchiveAction(xout, FindConfiguration("Release"));
+
+ xout.EndElement();
+}
+
+void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
+ const std::string& xcProjDir)
+{
+ 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");
+
+ xout.StartElement("BuildableReference");
+ xout.BreakAttributes();
+ xout.Attribute("BuildableIdentifier", "primary");
+ xout.Attribute("BlueprintIdentifier", this->TargetId);
+ xout.Attribute("BuildableName", this->TargetName);
+ xout.Attribute("BlueprintName", this->TargetName);
+ xout.Attribute("ReferencedContainer", "container:" + xcProjDir);
+ xout.EndElement();
+
+ xout.EndElement(); // BuildActionEntry
+ xout.EndElement(); // BuildActionEntries
+ xout.EndElement(); // BuildAction
+}
+
+void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ 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");
+ xout.EndElement();
+
+ xout.StartElement("AdditionalOptions");
+ xout.EndElement();
+
+ xout.EndElement(); // TestAction
+}
+
+void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout,
+ std::string configuration,
+ const std::string& xcProjDir)
+{
+ 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");
+
+ xout.StartElement("MacroExpansion");
+
+ xout.StartElement("BuildableReference");
+ xout.BreakAttributes();
+ xout.Attribute("BuildableIdentifier", "primary");
+ xout.Attribute("BlueprintIdentifier", this->TargetId);
+ xout.Attribute("BuildableName", this->TargetName);
+ xout.Attribute("BlueprintName", this->TargetName);
+ xout.Attribute("ReferencedContainer", "container:" + xcProjDir);
+ xout.EndElement();
+
+ xout.EndElement(); // MacroExpansion
+
+ xout.StartElement("AdditionalOptions");
+ xout.EndElement();
+
+ xout.EndElement(); // LaunchAction
+}
+
+void cmXCodeScheme::WriteProfileAction(cmXMLWriter& xout,
+ 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,
+ std::string configuration)
+{
+ xout.StartElement("AnalyzeAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.EndElement();
+}
+
+void cmXCodeScheme::WriteArchiveAction(cmXMLWriter& xout,
+ std::string configuration)
+{
+ xout.StartElement("ArchiveAction");
+ xout.BreakAttributes();
+ xout.Attribute("buildConfiguration", configuration);
+ xout.Attribute("revealArchiveInOrganizer", "YES");
+ 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.size() > 0)
+ return this->ConfigList[0];
+
+ return name;
+}
diff --git a/Source/cmXCodeScheme.h b/Source/cmXCodeScheme.h
new file mode 100644
index 0000000..b174c51
--- /dev/null
+++ b/Source/cmXCodeScheme.h
@@ -0,0 +1,46 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmXCodeScheme_h
+#define cmXCodeScheme_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include "cmGlobalXCodeGenerator.h"
+#include "cmSystemTools.h"
+#include "cmXCodeObject.h"
+#include "cmXMLWriter.h"
+
+/** \class cmXCodeScheme
+ * \brief Write shared schemes for native targets in Xcode project.
+ */
+class cmXCodeScheme
+{
+public:
+ cmXCodeScheme(cmXCodeObject* xcObj,
+ const std::vector<std::string>& configList,
+ unsigned int xcVersion);
+
+ void WriteXCodeSharedScheme(const std::string& xcProjDir,
+ const std::string sourceRoot);
+
+private:
+ const std::string& TargetName;
+ const std::string& TargetId;
+ const std::vector<std::string>& ConfigList;
+ const unsigned int XcodeVersion;
+
+ void WriteXCodeXCScheme(std::ostream& fout, const std::string& xcProjDir);
+
+ void WriteBuildAction(cmXMLWriter& xout, const std::string& xcProjDir);
+ void WriteTestAction(cmXMLWriter& xout, std::string configuration);
+ void WriteLaunchAction(cmXMLWriter& xout, std::string configuration,
+ const std::string& xcProjDir);
+ void WriteProfileAction(cmXMLWriter& xout, std::string configuration);
+ void WriteAnalyzeAction(cmXMLWriter& xout, std::string configuration);
+ void WriteArchiveAction(cmXMLWriter& xout, std::string configuration);
+
+ std::string WriteVersionString();
+ std::string FindConfiguration(const std::string& name);
+};
+
+#endif