cmTestGenerator.cxx 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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 "cmOutputConverter.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 std::string& 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. // Prepend with the emulator when cross compiling if required.
  79. const char * emulator =
  80. target->GetProperty("CROSSCOMPILING_EMULATOR");
  81. if (emulator != 0)
  82. {
  83. std::vector<std::string> emulatorWithArgs;
  84. cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
  85. std::string emulatorExe(emulatorWithArgs[0]);
  86. cmSystemTools::ConvertToUnixSlashes(emulatorExe);
  87. os << cmOutputConverter::EscapeForCMake(emulatorExe) << " ";
  88. for(std::vector<std::string>::const_iterator ei =
  89. emulatorWithArgs.begin()+1;
  90. ei != emulatorWithArgs.end();
  91. ++ei)
  92. {
  93. os << cmOutputConverter::EscapeForCMake(*ei) << " ";
  94. }
  95. }
  96. }
  97. else
  98. {
  99. // Use the command name given.
  100. exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
  101. cmSystemTools::ConvertToUnixSlashes(exe);
  102. }
  103. // Generate the command line with full escapes.
  104. os << cmOutputConverter::EscapeForCMake(exe);
  105. for(std::vector<std::string>::const_iterator ci = command.begin()+1;
  106. ci != command.end(); ++ci)
  107. {
  108. os << " " << cmOutputConverter::EscapeForCMake(
  109. ge.Parse(*ci)->Evaluate(mf, config));
  110. }
  111. // Finish the test command.
  112. os << ")\n";
  113. // Output properties for the test.
  114. cmPropertyMap& pm = this->Test->GetProperties();
  115. if(!pm.empty())
  116. {
  117. os << indent << "set_tests_properties(" << this->Test->GetName()
  118. << " PROPERTIES ";
  119. for(cmPropertyMap::const_iterator i = pm.begin();
  120. i != pm.end(); ++i)
  121. {
  122. os << " " << i->first
  123. << " " << cmOutputConverter::EscapeForCMake(
  124. ge.Parse(i->second.GetValue())->Evaluate(mf, config));
  125. }
  126. os << ")" << std::endl;
  127. }
  128. }
  129. //----------------------------------------------------------------------------
  130. void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os,
  131. Indent const& indent)
  132. {
  133. os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n";
  134. }
  135. //----------------------------------------------------------------------------
  136. bool cmTestGenerator::NeedsScriptNoConfig() const
  137. {
  138. return (this->TestGenerated && // test generated for at least one config
  139. this->ActionsPerConfig && // test is config-aware
  140. this->Configurations.empty() && // test runs in all configs
  141. !this->ConfigurationTypes->empty()); // config-dependent command
  142. }
  143. //----------------------------------------------------------------------------
  144. void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
  145. Indent const& indent)
  146. {
  147. this->TestGenerated = true;
  148. // Get the test command line to be executed.
  149. std::vector<std::string> const& command = this->Test->GetCommand();
  150. std::string exe = command[0];
  151. cmSystemTools::ConvertToUnixSlashes(exe);
  152. fout << indent;
  153. fout << "add_test(";
  154. fout << this->Test->GetName() << " \"" << exe << "\"";
  155. for(std::vector<std::string>::const_iterator argit = command.begin()+1;
  156. argit != command.end(); ++argit)
  157. {
  158. // Just double-quote all arguments so they are re-parsed
  159. // correctly by the test system.
  160. fout << " \"";
  161. for(std::string::const_iterator c = argit->begin();
  162. c != argit->end(); ++c)
  163. {
  164. // Escape quotes within arguments. We should escape
  165. // backslashes too but we cannot because it makes the result
  166. // inconsistent with previous behavior of this command.
  167. if((*c == '"'))
  168. {
  169. fout << '\\';
  170. }
  171. fout << *c;
  172. }
  173. fout << "\"";
  174. }
  175. fout << ")" << std::endl;
  176. // Output properties for the test.
  177. cmPropertyMap& pm = this->Test->GetProperties();
  178. if(!pm.empty())
  179. {
  180. fout << indent << "set_tests_properties(" << this->Test->GetName()
  181. << " PROPERTIES ";
  182. for(cmPropertyMap::const_iterator i = pm.begin();
  183. i != pm.end(); ++i)
  184. {
  185. fout << " " << i->first
  186. << " " << cmOutputConverter::EscapeForCMake(i->second.GetValue());
  187. }
  188. fout << ")" << std::endl;
  189. }
  190. }