cmCreateTestSourceList.cxx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmCreateTestSourceList.h"
  4. #include <algorithm>
  5. #include "cmMakefile.h"
  6. #include "cmSourceFile.h"
  7. #include "cmSystemTools.h"
  8. class cmExecutionStatus;
  9. // cmCreateTestSourceList
  10. bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
  11. cmExecutionStatus&)
  12. {
  13. if (args.size() < 3) {
  14. this->SetError("called with wrong number of arguments.");
  15. return false;
  16. }
  17. std::vector<std::string>::const_iterator i = args.begin();
  18. std::string extraInclude;
  19. std::string function;
  20. std::vector<std::string> tests;
  21. // extract extra include and function ot
  22. for (; i != args.end(); i++) {
  23. if (*i == "EXTRA_INCLUDE") {
  24. ++i;
  25. if (i == args.end()) {
  26. this->SetError("incorrect arguments to EXTRA_INCLUDE");
  27. return false;
  28. }
  29. extraInclude = "#include \"";
  30. extraInclude += *i;
  31. extraInclude += "\"\n";
  32. } else if (*i == "FUNCTION") {
  33. ++i;
  34. if (i == args.end()) {
  35. this->SetError("incorrect arguments to FUNCTION");
  36. return false;
  37. }
  38. function = *i;
  39. function += "(&ac, &av);\n";
  40. } else {
  41. tests.push_back(*i);
  42. }
  43. }
  44. i = tests.begin();
  45. // Name of the source list
  46. const char* sourceList = i->c_str();
  47. ++i;
  48. // Name of the test driver
  49. // make sure they specified an extension
  50. if (cmSystemTools::GetFilenameExtension(*i).size() < 2) {
  51. this->SetError(
  52. "You must specify a file extension for the test driver file.");
  53. return false;
  54. }
  55. std::string driver = this->Makefile->GetCurrentBinaryDirectory();
  56. driver += "/";
  57. driver += *i;
  58. ++i;
  59. std::string configFile = cmSystemTools::GetCMakeRoot();
  60. configFile += "/Templates/TestDriver.cxx.in";
  61. // Create the test driver file
  62. std::vector<std::string>::const_iterator testsBegin = i;
  63. std::vector<std::string> tests_func_name;
  64. // The rest of the arguments consist of a list of test source files.
  65. // Sadly, they can be in directories. Let's find a unique function
  66. // name for the corresponding test, and push it to the tests_func_name
  67. // list.
  68. // For the moment:
  69. // - replace spaces ' ', ':' and '/' with underscores '_'
  70. std::string forwardDeclareCode;
  71. for (i = testsBegin; i != tests.end(); ++i) {
  72. if (*i == "EXTRA_INCLUDE") {
  73. break;
  74. }
  75. std::string func_name;
  76. if (!cmSystemTools::GetFilenamePath(*i).empty()) {
  77. func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
  78. cmSystemTools::GetFilenameWithoutLastExtension(*i);
  79. } else {
  80. func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
  81. }
  82. cmSystemTools::ConvertToUnixSlashes(func_name);
  83. std::replace(func_name.begin(), func_name.end(), ' ', '_');
  84. std::replace(func_name.begin(), func_name.end(), '/', '_');
  85. std::replace(func_name.begin(), func_name.end(), ':', '_');
  86. tests_func_name.push_back(func_name);
  87. forwardDeclareCode += "int ";
  88. forwardDeclareCode += func_name;
  89. forwardDeclareCode += "(int, char*[]);\n";
  90. }
  91. std::string functionMapCode;
  92. int numTests = 0;
  93. std::vector<std::string>::iterator j;
  94. for (i = testsBegin, j = tests_func_name.begin(); i != tests.end();
  95. ++i, ++j) {
  96. std::string func_name;
  97. if (!cmSystemTools::GetFilenamePath(*i).empty()) {
  98. func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
  99. cmSystemTools::GetFilenameWithoutLastExtension(*i);
  100. } else {
  101. func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
  102. }
  103. functionMapCode += " {\n"
  104. " \"";
  105. functionMapCode += func_name;
  106. functionMapCode += "\",\n"
  107. " ";
  108. functionMapCode += *j;
  109. functionMapCode += "\n"
  110. " },\n";
  111. numTests++;
  112. }
  113. if (!extraInclude.empty()) {
  114. this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
  115. extraInclude.c_str());
  116. }
  117. if (!function.empty()) {
  118. this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
  119. function.c_str());
  120. }
  121. this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
  122. forwardDeclareCode.c_str());
  123. this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
  124. functionMapCode.c_str());
  125. bool res = true;
  126. if (!this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(), false,
  127. true, false)) {
  128. res = false;
  129. }
  130. // Construct the source list.
  131. std::string sourceListValue;
  132. {
  133. cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver);
  134. sf->SetProperty("ABSTRACT", "0");
  135. sourceListValue = args[1];
  136. }
  137. for (i = testsBegin; i != tests.end(); ++i) {
  138. cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
  139. sf->SetProperty("ABSTRACT", "0");
  140. sourceListValue += ";";
  141. sourceListValue += *i;
  142. }
  143. this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
  144. return res;
  145. }