cmCreateTestSourceList.cxx 5.0 KB

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