cmTestGenerator.cxx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmTestGenerator.h"
  11. #include "cmGeneratorExpression.h"
  12. #include "cmLocalGenerator.h"
  13. #include "cmMakefile.h"
  14. #include "cmSystemTools.h"
  15. #include "cmTarget.h"
  16. #include "cmTest.h"
  17. //----------------------------------------------------------------------------
  18. cmTestGenerator
  19. ::cmTestGenerator(cmTest* test,
  20. std::vector<std::string> const& configurations):
  21. cmScriptGenerator("CTEST_CONFIGURATION_TYPE", configurations),
  22. Test(test)
  23. {
  24. this->ActionsPerConfig = !test->GetOldStyle();
  25. this->TestGenerated = false;
  26. }
  27. //----------------------------------------------------------------------------
  28. cmTestGenerator
  29. ::~cmTestGenerator()
  30. {
  31. }
  32. //----------------------------------------------------------------------------
  33. void cmTestGenerator::GenerateScriptConfigs(std::ostream& os,
  34. Indent const& indent)
  35. {
  36. // Create the tests.
  37. this->cmScriptGenerator::GenerateScriptConfigs(os, indent);
  38. }
  39. //----------------------------------------------------------------------------
  40. void cmTestGenerator::GenerateScriptActions(std::ostream& os,
  41. Indent const& indent)
  42. {
  43. if(this->ActionsPerConfig)
  44. {
  45. // This is the per-config generation in a single-configuration
  46. // build generator case. The superclass will call our per-config
  47. // method.
  48. this->cmScriptGenerator::GenerateScriptActions(os, indent);
  49. }
  50. else
  51. {
  52. // This is an old-style test, so there is only one config.
  53. //assert(this->Test->GetOldStyle());
  54. this->GenerateOldStyle(os, indent);
  55. }
  56. }
  57. //----------------------------------------------------------------------------
  58. void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
  59. const char* config,
  60. Indent const& indent)
  61. {
  62. this->TestGenerated = true;
  63. // Set up generator expression evaluation context.
  64. cmGeneratorExpression ge(this->Test->GetBacktrace());
  65. // Start the test command.
  66. os << indent << "add_test(" << this->Test->GetName() << " ";
  67. // Get the test command line to be executed.
  68. std::vector<std::string> const& command = this->Test->GetCommand();
  69. // Check whether the command executable is a target whose name is to
  70. // be translated.
  71. std::string exe = command[0];
  72. cmMakefile* mf = this->Test->GetMakefile();
  73. cmTarget* target = mf->FindTargetToUse(exe);
  74. if(target && target->GetType() == cmTarget::EXECUTABLE)
  75. {
  76. // Use the target file on disk.
  77. exe = target->GetFullPath(config);
  78. }
  79. else
  80. {
  81. // Use the command name given.
  82. exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
  83. cmSystemTools::ConvertToUnixSlashes(exe);
  84. }
  85. // Generate the command line with full escapes.
  86. cmLocalGenerator* lg = mf->GetLocalGenerator();
  87. os << lg->EscapeForCMake(exe.c_str());
  88. for(std::vector<std::string>::const_iterator ci = command.begin()+1;
  89. ci != command.end(); ++ci)
  90. {
  91. os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
  92. }
  93. // Finish the test command.
  94. os << ")\n";
  95. // Output properties for the test.
  96. cmPropertyMap& pm = this->Test->GetProperties();
  97. if(!pm.empty())
  98. {
  99. os << indent << "set_tests_properties(" << this->Test->GetName()
  100. << " PROPERTIES ";
  101. for(cmPropertyMap::const_iterator i = pm.begin();
  102. i != pm.end(); ++i)
  103. {
  104. os << " " << i->first
  105. << " " << lg->EscapeForCMake(
  106. ge.Parse(i->second.GetValue())->Evaluate(mf, config));
  107. }
  108. os << ")" << std::endl;
  109. }
  110. }
  111. //----------------------------------------------------------------------------
  112. void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os,
  113. Indent const& indent)
  114. {
  115. os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
  116. }
  117. //----------------------------------------------------------------------------
  118. bool cmTestGenerator::NeedsScriptNoConfig() const
  119. {
  120. return (this->TestGenerated && // test generated for at least one config
  121. this->ActionsPerConfig && // test is config-aware
  122. this->Configurations.empty() && // test runs in all configs
  123. !this->ConfigurationTypes->empty()); // config-dependent command
  124. }
  125. //----------------------------------------------------------------------------
  126. void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
  127. Indent const& indent)
  128. {
  129. this->TestGenerated = true;
  130. // Get the test command line to be executed.
  131. std::vector<std::string> const& command = this->Test->GetCommand();
  132. std::string exe = command[0];
  133. cmSystemTools::ConvertToUnixSlashes(exe);
  134. fout << indent;
  135. fout << "add_test(";
  136. fout << this->Test->GetName() << " \"" << exe << "\"";
  137. for(std::vector<std::string>::const_iterator argit = command.begin()+1;
  138. argit != command.end(); ++argit)
  139. {
  140. // Just double-quote all arguments so they are re-parsed
  141. // correctly by the test system.
  142. fout << " \"";
  143. for(std::string::const_iterator c = argit->begin();
  144. c != argit->end(); ++c)
  145. {
  146. // Escape quotes within arguments. We should escape
  147. // backslashes too but we cannot because it makes the result
  148. // inconsistent with previous behavior of this command.
  149. if((*c == '"'))
  150. {
  151. fout << '\\';
  152. }
  153. fout << *c;
  154. }
  155. fout << "\"";
  156. }
  157. fout << ")" << std::endl;
  158. // Output properties for the test.
  159. cmMakefile* mf = this->Test->GetMakefile();
  160. cmLocalGenerator* lg = mf->GetLocalGenerator();
  161. cmPropertyMap& pm = this->Test->GetProperties();
  162. if(!pm.empty())
  163. {
  164. fout << indent << "set_tests_properties(" << this->Test->GetName()
  165. << " PROPERTIES ";
  166. for(cmPropertyMap::const_iterator i = pm.begin();
  167. i != pm.end(); ++i)
  168. {
  169. fout << " " << i->first
  170. << " " << lg->EscapeForCMake(i->second.GetValue());
  171. }
  172. fout << ")" << std::endl;
  173. }
  174. }