Browse Source

Xcode: Add XCTest support to schema generator

Closes: #16961
Gregor Jasny 8 years ago
parent
commit
fe34a5c82b
3 changed files with 62 additions and 7 deletions
  1. 28 2
      Source/cmGlobalXCodeGenerator.cxx
  2. 24 3
      Source/cmXCodeScheme.cxx
  3. 10 2
      Source/cmXCodeScheme.h

+ 28 - 2
Source/cmGlobalXCodeGenerator.cxx

@@ -3298,6 +3298,31 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
 void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
   const std::string& xcProjDir)
 {
+  // collect all tests for the targets
+  std::map<std::string, cmXCodeScheme::TestObjects> testables;
+
+  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) {
+      continue;
+    }
+
+    if (!obj->GetTarget()->IsXCTestOnApple()) {
+      continue;
+    }
+
+    const char* testee = obj->GetTarget()->GetProperty("XCTEST_TESTEE");
+    if (!testee) {
+      continue;
+    }
+
+    testables[testee].push_back(obj);
+  }
+
+  // generate scheme
   for (std::vector<cmXCodeObject*>::const_iterator i =
          this->XCodeObjects.begin();
        i != this->XCodeObjects.end(); ++i) {
@@ -3305,8 +3330,9 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
     if (obj->GetType() == cmXCodeObject::OBJECT &&
         (obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
          obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
-      cmXCodeScheme schm(obj, this->CurrentConfigurationTypes,
-                         this->XcodeVersion);
+      const std::string& targetName = obj->GetTarget()->GetName();
+      cmXCodeScheme schm(obj, testables[targetName],
+                         this->CurrentConfigurationTypes, this->XcodeVersion);
       schm.WriteXCodeSharedScheme(xcProjDir,
                                   this->RelativeToSource(xcProjDir.c_str()));
     }

+ 24 - 3
Source/cmXCodeScheme.cxx

@@ -10,10 +10,11 @@
 #include "cmGeneratorTarget.h"
 #include "cmXMLSafe.h"
 
-cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj,
+cmXCodeScheme::cmXCodeScheme(cmXCodeObject* xcObj, const TestObjects& tests,
                              const std::vector<std::string>& configList,
                              unsigned int xcVersion)
   : Target(xcObj)
+  , Tests(tests)
   , TargetName(xcObj->GetTarget()->GetName())
   , ConfigList(configList)
   , XcodeVersion(xcVersion)
@@ -56,7 +57,7 @@ void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout,
   xout.Attribute("version", "1.3");
 
   WriteBuildAction(xout, container);
-  WriteTestAction(xout, FindConfiguration("Debug"));
+  WriteTestAction(xout, FindConfiguration("Debug"), container);
   WriteLaunchAction(xout, FindConfiguration("Debug"), container);
   WriteProfileAction(xout, FindConfiguration("Release"));
   WriteAnalyzeAction(xout, FindConfiguration("Debug"));
@@ -90,7 +91,8 @@ void cmXCodeScheme::WriteBuildAction(cmXMLWriter& xout,
 }
 
 void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
-                                    std::string configuration)
+                                    std::string configuration,
+                                    const std::string& container)
 {
   xout.StartElement("TestAction");
   xout.BreakAttributes();
@@ -102,8 +104,22 @@ void cmXCodeScheme::WriteTestAction(cmXMLWriter& xout,
   xout.Attribute("shouldUseLaunchSchemeArgsEnv", "YES");
 
   xout.StartElement("Testables");
+  for (TestObjects::const_iterator it = this->Tests.begin();
+       it != this->Tests.end(); ++it) {
+    xout.StartElement("TestableReference");
+    xout.BreakAttributes();
+    xout.Attribute("skipped", "NO");
+    WriteBuildableReference(xout, *it, container);
+    xout.EndElement(); // TestableReference
+  }
   xout.EndElement();
 
+  if (IsTestable()) {
+    xout.StartElement("MacroExpansion");
+    WriteBuildableReference(xout, this->Target, container);
+    xout.EndElement(); // MacroExpansion
+  }
+
   xout.StartElement("AdditionalOptions");
   xout.EndElement();
 
@@ -213,6 +229,11 @@ std::string cmXCodeScheme::FindConfiguration(const std::string& name)
   return name;
 }
 
+bool cmXCodeScheme::IsTestable() const
+{
+  return !this->Tests.empty() || IsExecutable(this->Target);
+}
+
 bool cmXCodeScheme::IsExecutable(const cmXCodeObject* target)
 {
   cmGeneratorTarget* gt = target->GetTarget();

+ 10 - 2
Source/cmXCodeScheme.h

@@ -5,6 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <vector>
+
 #include "cmGlobalXCodeGenerator.h"
 #include "cmSystemTools.h"
 #include "cmXCodeObject.h"
@@ -16,7 +18,9 @@
 class cmXCodeScheme
 {
 public:
-  cmXCodeScheme(cmXCodeObject* xcObj,
+  typedef std::vector<const cmXCodeObject*> TestObjects;
+
+  cmXCodeScheme(cmXCodeObject* xcObj, const TestObjects& tests,
                 const std::vector<std::string>& configList,
                 unsigned int xcVersion);
 
@@ -25,6 +29,7 @@ public:
 
 private:
   const cmXCodeObject* const Target;
+  const TestObjects Tests;
   const std::string& TargetName;
   const std::vector<std::string>& ConfigList;
   const unsigned int XcodeVersion;
@@ -32,7 +37,8 @@ private:
   void WriteXCodeXCScheme(std::ostream& fout, const std::string& container);
 
   void WriteBuildAction(cmXMLWriter& xout, const std::string& container);
-  void WriteTestAction(cmXMLWriter& xout, std::string configuration);
+  void WriteTestAction(cmXMLWriter& xout, std::string configuration,
+                       const std::string& container);
   void WriteLaunchAction(cmXMLWriter& xout, std::string configuration,
                          const std::string& container);
   void WriteProfileAction(cmXMLWriter& xout, std::string configuration);
@@ -45,6 +51,8 @@ private:
   std::string WriteVersionString();
   std::string FindConfiguration(const std::string& name);
 
+  bool IsTestable() const;
+
   static bool IsExecutable(const cmXCodeObject* target);
 };