cmCreateTestSourceList.cxx 5.3 KB

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