Ver código fonte

ENH: Refactor generation of CTestTestfile content

This moves code which generates ADD_TEST and SET_TESTS_PROPERTIES calls
into CTestTestfile.cmake files out of cmLocalGenerator and into a
cmTestGenerator class.  This will allow more advanced generation without
cluttering cmLocalGenerator.  The cmTestGenerator class derives from
cmScriptGenerator to get support for per-configuration script
generation (not yet enabled).
Brad King 16 anos atrás
pai
commit
66d69f864a

+ 2 - 0
Source/CMakeLists.txt

@@ -215,6 +215,8 @@ SET(SRCS
   cmTarget.h
   cmTest.cxx
   cmTest.h
+  cmTestGenerator.cxx
+  cmTestGenerator.h
   cmVariableWatch.cxx
   cmVariableWatch.h
   cmVersion.cxx

+ 10 - 1
Source/cmAddTestCommand.cxx

@@ -16,6 +16,8 @@
 =========================================================================*/
 #include "cmAddTestCommand.h"
 
+#include "cmTestGenerator.h"
+
 #include "cmTest.h"
 
 
@@ -42,7 +44,14 @@ bool cmAddTestCommand
     arguments.push_back(*it);
     }
 
-  cmTest* test = this->Makefile->CreateTest(args[0].c_str());
+  // Create the test but add a generator only the first time it is
+  // seen.  This preserves behavior from before test generators.
+  cmTest* test = this->Makefile->GetTest(args[0].c_str());
+  if(!test)
+    {
+    test = this->Makefile->CreateTest(args[0].c_str());
+    this->Makefile->AddTestGenerator(new cmTestGenerator(test));
+    }
   test->SetCommand(args[1].c_str());
   test->SetArguments(arguments);
 

+ 22 - 70
Source/cmLocalGenerator.cxx

@@ -26,6 +26,7 @@
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmTest.h"
+#include "cmTestGenerator.h"
 #include "cmVersion.h"
 #include "cmake.h"
 
@@ -212,6 +213,20 @@ void cmLocalGenerator::GenerateTestFiles()
     {
     return;
     }
+
+  // Compute the set of configurations.
+  std::vector<std::string> configurationTypes;
+  if(const char* types =
+     this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
+    {
+    cmSystemTools::ExpandListArgument(types, configurationTypes);
+    }
+  const char* config = 0;
+  if(configurationTypes.empty())
+    {
+    config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+    }
+
   std::string file = this->Makefile->GetStartOutputDirectory();
   file += "/";
   file += "CTestTestfile.cmake";
@@ -238,77 +253,14 @@ void cmLocalGenerator::GenerateTestFiles()
     {
     fout << "INCLUDE(\"" << testIncludeFile << "\")" << std::endl;
     }
-  
-  const std::vector<cmTest*> *tests = this->Makefile->GetTests();
-  std::vector<cmTest*>::const_iterator it;
-  for ( it = tests->begin(); it != tests->end(); ++ it )
+
+  // Ask each test generator to write its code.
+  std::vector<cmTestGenerator*> const&
+    testers = this->Makefile->GetTestGenerators();
+  for(std::vector<cmTestGenerator*>::const_iterator gi = testers.begin();
+      gi != testers.end(); ++gi)
     {
-    cmTest* test = *it;
-    fout << "ADD_TEST(";
-    fout << test->GetName() << " \"" << test->GetCommand() << "\"";
-    
-    std::vector<cmStdString>::const_iterator argit;
-    for (argit = test->GetArguments().begin();
-         argit != test->GetArguments().end(); ++argit)
-      {
-      // Just double-quote all arguments so they are re-parsed
-      // correctly by the test system.
-      fout << " \"";
-      for(std::string::const_iterator c = argit->begin(); 
-          c != argit->end(); ++c)
-        {
-        // Escape quotes within arguments.  We should escape
-        // backslashes too but we cannot because it makes the result
-        // inconsistent with previous behavior of this command.
-        if((*c == '"'))
-          {
-          fout << '\\';
-          }
-        fout << *c;
-        }
-      fout << "\"";
-      }
-    fout << ")" << std::endl;
-    cmPropertyMap::const_iterator pit;
-    cmPropertyMap* mpit = &test->GetProperties();
-    if ( mpit->size() )
-      {
-      fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
-      for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
-        {
-        fout << " " << pit->first.c_str() << " \"";
-        const char* value = pit->second.GetValue();
-        for ( ; *value; ++ value )
-          {
-          switch ( *value )
-            {
-          case '\\':
-          case '"':
-          case ' ':
-          case '#':
-          case '(':
-          case ')':
-          case '$':
-          case '^':
-            fout << "\\" << *value;
-            break;
-          case '\t':
-            fout << "\\t";
-            break;
-          case '\n':
-            fout << "\\n";
-            break;
-          case '\r':
-            fout << "\\r";
-            break;
-          default:
-            fout << *value;
-            }
-          }
-        fout << "\"";
-        }
-      fout << ")" << std::endl;
-      }
+    (*gi)->Generate(fout, config, configurationTypes);
     }
   if ( this->Children.size())
     {

+ 8 - 8
Source/cmMakefile.cxx

@@ -32,6 +32,7 @@
 #  include "cmVariableWatch.h"
 #endif
 #include "cmInstallGenerator.h"
+#include "cmTestGenerator.h"
 #include "cmake.h"
 #include <stdlib.h> // required for atoi
 
@@ -108,7 +109,6 @@ cmMakefile::cmMakefile(const cmMakefile& mf)
   this->Targets = mf.Targets;
   this->SourceFiles = mf.SourceFiles;
   this->Tests = mf.Tests;
-  this->OrderedTests = mf.OrderedTests;
   this->IncludeDirectories = mf.IncludeDirectories;
   this->LinkDirectories = mf.LinkDirectories;
   this->SystemIncludeDirectories = mf.SystemIncludeDirectories;
@@ -116,6 +116,7 @@ cmMakefile::cmMakefile(const cmMakefile& mf)
   this->OutputFiles = mf.OutputFiles;
   this->LinkLibraries = mf.LinkLibraries;
   this->InstallGenerators = mf.InstallGenerators;
+  this->TestGenerators = mf.TestGenerators;
   this->IncludeFileRegularExpression = mf.IncludeFileRegularExpression;
   this->ComplainFileRegularExpression = mf.ComplainFileRegularExpression;
   this->SourceFileExtensions = mf.SourceFileExtensions;
@@ -181,6 +182,12 @@ cmMakefile::~cmMakefile()
     {
     delete *i;
     }
+  for(std::vector<cmTestGenerator*>::iterator
+        i = this->TestGenerators.begin();
+      i != this->TestGenerators.end(); ++i)
+    {
+    delete *i;
+    }
   for(std::vector<cmSourceFile*>::iterator i = this->SourceFiles.begin();
       i != this->SourceFiles.end(); ++i)
     {
@@ -3324,7 +3331,6 @@ cmTest* cmMakefile::CreateTest(const char* testName)
   test->SetName(testName);
   test->SetMakefile(this);
   this->Tests[testName] = test;
-  this->OrderedTests.push_back(test);
   return test;
 }
 
@@ -3343,12 +3349,6 @@ cmTest* cmMakefile::GetTest(const char* testName) const
   return 0;
 }
 
-//----------------------------------------------------------------------------
-const std::vector<cmTest*> *cmMakefile::GetTests() const
-{
-  return &this->OrderedTests;
-}
-
 std::string cmMakefile::GetListFileStack()
 {
   cmOStringStream tmp;

+ 7 - 2
Source/cmMakefile.h

@@ -41,6 +41,7 @@ class cmLocalGenerator;
 class cmMakeDepend;
 class cmSourceFile;
 class cmTest;
+class cmTestGenerator;
 class cmVariableWatch;
 class cmake;
 class cmMakefileCall;
@@ -769,7 +770,6 @@ public:
    *  not found, then a null pointer is returned.
    */
   cmTest* GetTest(const char* testName) const;
-  const std::vector<cmTest*> *GetTests() const;
 
   /**
    * Get a list of macros as a ; separated string
@@ -805,6 +805,11 @@ public:
   std::vector<cmInstallGenerator*>& GetInstallGenerators()
     { return this->InstallGenerators; }
 
+  void AddTestGenerator(cmTestGenerator* g)
+    { if(g) this->TestGenerators.push_back(g); }
+  std::vector<cmTestGenerator*>& GetTestGenerators()
+    { return this->TestGenerators; }
+
   // Define the properties
   static void DefineProperties(cmake *cm);
 
@@ -850,7 +855,6 @@ protected:
 
   // Tests
   std::map<cmStdString, cmTest*> Tests;
-  std::vector<cmTest*> OrderedTests;
   
   // The include and link-library paths.  These may have order
   // dependency, so they must be vectors (not set).
@@ -868,6 +872,7 @@ protected:
   cmTarget::LinkLibraryVectorType LinkLibraries;
 
   std::vector<cmInstallGenerator*> InstallGenerators;
+  std::vector<cmTestGenerator*> TestGenerators;
 
   std::string IncludeFileRegularExpression;
   std::string ComplainFileRegularExpression;

+ 126 - 0
Source/cmTestGenerator.cxx

@@ -0,0 +1,126 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#include "cmTestGenerator.h"
+
+#include "cmTest.h"
+
+//----------------------------------------------------------------------------
+cmTestGenerator
+::cmTestGenerator(cmTest* test,
+                  std::vector<std::string> const& configurations):
+  cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
+  Test(test)
+{
+  this->ActionsPerConfig = false;
+  this->TestGenerated = false;
+}
+
+//----------------------------------------------------------------------------
+cmTestGenerator
+::~cmTestGenerator()
+{
+}
+
+//----------------------------------------------------------------------------
+void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
+                                            Indent const& indent)
+{
+  // First create the tests.
+  this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
+
+  // Now generate the test properties.
+  if(this->TestGenerated)
+    {
+    cmTest* test = this->Test;
+    std::ostream& fout = os;
+    cmPropertyMap::const_iterator pit;
+    cmPropertyMap* mpit = &test->GetProperties();
+    if ( mpit->size() )
+      {
+      fout << "SET_TESTS_PROPERTIES(" << test->GetName() << " PROPERTIES ";
+      for ( pit = mpit->begin(); pit != mpit->end(); ++ pit )
+        {
+        fout << " " << pit->first.c_str() << " \"";
+        const char* value = pit->second.GetValue();
+        for ( ; *value; ++ value )
+          {
+          switch ( *value )
+            {
+            case '\\':
+            case '"':
+            case ' ':
+            case '#':
+            case '(':
+            case ')':
+            case '$':
+            case '^':
+              fout << "\\" << *value;
+              break;
+            case '\t':
+              fout << "\\t";
+              break;
+            case '\n':
+              fout << "\\n";
+              break;
+            case '\r':
+              fout << "\\r";
+              break;
+            default:
+              fout << *value;
+            }
+          }
+        fout << "\"";
+        }
+      fout << ")" << std::endl;
+      }
+    }
+}
+
+//----------------------------------------------------------------------------
+void cmTestGenerator::GenerateScriptActions(std::ostream& fout,
+                                            Indent const& indent)
+{
+  this->TestGenerated = true;
+
+  cmTest* test = this->Test;
+  fout << indent;
+  fout << "ADD_TEST(";
+  fout << test->GetName() << " \"" << test->GetCommand() << "\"";
+
+  std::vector<cmStdString>::const_iterator argit;
+  for (argit = test->GetArguments().begin();
+       argit != test->GetArguments().end(); ++argit)
+    {
+    // Just double-quote all arguments so they are re-parsed
+    // correctly by the test system.
+    fout << " \"";
+    for(std::string::const_iterator c = argit->begin();
+        c != argit->end(); ++c)
+      {
+      // Escape quotes within arguments.  We should escape
+      // backslashes too but we cannot because it makes the result
+      // inconsistent with previous behavior of this command.
+      if((*c == '"'))
+        {
+        fout << '\\';
+        }
+      fout << *c;
+      }
+    fout << "\"";
+    }
+  fout << ")" << std::endl;
+}

+ 44 - 0
Source/cmTestGenerator.h

@@ -0,0 +1,44 @@
+/*=========================================================================
+
+  Program:   CMake - Cross-Platform Makefile Generator
+  Module:    $RCSfile$
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
+  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef cmTestGenerator_h
+#define cmTestGenerator_h
+
+#include "cmScriptGenerator.h"
+
+class cmTest;
+
+/** \class cmTestGenerator
+ * \brief Support class for generating install scripts.
+ *
+ */
+class cmTestGenerator: public cmScriptGenerator
+{
+public:
+  cmTestGenerator(cmTest* test,
+                  std::vector<std::string> const&
+                  configurations = std::vector<std::string>());
+  virtual ~cmTestGenerator();
+
+protected:
+  virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
+  virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+
+  cmTest* Test;
+  bool TestGenerated;
+};
+
+#endif

+ 1 - 0
bootstrap

@@ -171,6 +171,7 @@ CMAKE_CXX_SOURCES="\
   cmSourceFile \
   cmSourceFileLocation \
   cmSystemTools \
+  cmTestGenerator \
   cmVersion \
   cmFileTimeComparison \
   cmGlobalUnixMakefileGenerator3 \