diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 89ee0adb2..119336383 100644 --- a/Source/CMakeLists.txt +++ b/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 diff --git a/Source/cmAddTestCommand.cxx b/Source/cmAddTestCommand.cxx index 6124ee2af..0bbf40e39 100644 --- a/Source/cmAddTestCommand.cxx +++ b/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); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e9c44a5b8..835c8868c 100644 --- a/Source/cmLocalGenerator.cxx +++ b/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 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 *tests = this->Makefile->GetTests(); - std::vector::const_iterator it; - for ( it = tests->begin(); it != tests->end(); ++ it ) + + // Ask each test generator to write its code. + std::vector const& + testers = this->Makefile->GetTestGenerators(); + for(std::vector::const_iterator gi = testers.begin(); + gi != testers.end(); ++gi) { - cmTest* test = *it; - fout << "ADD_TEST("; - fout << test->GetName() << " \"" << test->GetCommand() << "\""; - - std::vector::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()) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d22cebd2d..69d58ba46 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -32,6 +32,7 @@ # include "cmVariableWatch.h" #endif #include "cmInstallGenerator.h" +#include "cmTestGenerator.h" #include "cmake.h" #include // 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::iterator + i = this->TestGenerators.begin(); + i != this->TestGenerators.end(); ++i) + { + delete *i; + } for(std::vector::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 *cmMakefile::GetTests() const -{ - return &this->OrderedTests; -} - std::string cmMakefile::GetListFileStack() { cmOStringStream tmp; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 51136f124..5efe2d948 100644 --- a/Source/cmMakefile.h +++ b/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 *GetTests() const; /** * Get a list of macros as a ; separated string @@ -805,6 +805,11 @@ public: std::vector& GetInstallGenerators() { return this->InstallGenerators; } + void AddTestGenerator(cmTestGenerator* g) + { if(g) this->TestGenerators.push_back(g); } + std::vector& GetTestGenerators() + { return this->TestGenerators; } + // Define the properties static void DefineProperties(cmake *cm); @@ -850,7 +855,6 @@ protected: // Tests std::map Tests; - std::vector 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 InstallGenerators; + std::vector TestGenerators; std::string IncludeFileRegularExpression; std::string ComplainFileRegularExpression; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx new file mode 100644 index 000000000..75865a2c6 --- /dev/null +++ b/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 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::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; +} diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h new file mode 100644 index 000000000..021be397c --- /dev/null +++ b/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 const& + configurations = std::vector()); + 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 diff --git a/bootstrap b/bootstrap index 9b279300a..b8dee528f 100755 --- a/bootstrap +++ b/bootstrap @@ -171,6 +171,7 @@ CMAKE_CXX_SOURCES="\ cmSourceFile \ cmSourceFileLocation \ cmSystemTools \ + cmTestGenerator \ cmVersion \ cmFileTimeComparison \ cmGlobalUnixMakefileGenerator3 \