cmCreateTestSourceList.cxx 5.03 KB
Newer Older
1
2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3
#include "cmCreateTestSourceList.h"
Brad King's avatar
Brad King committed
4

5
6
#include <algorithm>

7
#include "cmMakefile.h"
Ken Martin's avatar
Ken Martin committed
8
#include "cmSourceFile.h"
9
#include "cmSystemTools.h"
10

11
12
class cmExecutionStatus;

13
// cmCreateTestSourceList
14
15
bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
                                         cmExecutionStatus&)
16
{
17
  if (args.size() < 3) {
18
19
    this->SetError("called with wrong number of arguments.");
    return false;
20
  }
Andy Cedilnik's avatar
Andy Cedilnik committed
21

22
  std::vector<std::string>::const_iterator i = args.begin();
23
24
25
26
  std::string extraInclude;
  std::string function;
  std::vector<std::string> tests;
  // extract extra include and function ot
27
28
  for (; i != args.end(); i++) {
    if (*i == "EXTRA_INCLUDE") {
29
      ++i;
30
      if (i == args.end()) {
31
32
        this->SetError("incorrect arguments to EXTRA_INCLUDE");
        return false;
33
      }
34
35
36
      extraInclude = "#include \"";
      extraInclude += *i;
      extraInclude += "\"\n";
37
    } else if (*i == "FUNCTION") {
38
      ++i;
39
      if (i == args.end()) {
40
41
        this->SetError("incorrect arguments to FUNCTION");
        return false;
42
      }
43
      function = *i;
44
      function += "(&ac, &av);\n";
45
    } else {
46
47
      tests.push_back(*i);
    }
48
  }
49
  i = tests.begin();
Andy Cedilnik's avatar
Andy Cedilnik committed
50

51
52
  // Name of the source list

53
54
  const char* sourceList = i->c_str();
  ++i;
55
56

  // Name of the test driver
Ken Martin's avatar
Ken Martin committed
57
  // make sure they specified an extension
58
  if (cmSystemTools::GetFilenameExtension(*i).size() < 2) {
Andy Cedilnik's avatar
Andy Cedilnik committed
59
    this->SetError(
60
      "You must specify a file extension for the test driver file.");
Ken Martin's avatar
Ken Martin committed
61
    return false;
62
  }
63
  std::string driver = this->Makefile->GetCurrentBinaryDirectory();
64
65
66
  driver += "/";
  driver += *i;
  ++i;
67

68
  std::string configFile = cmSystemTools::GetCMakeRoot();
Ken Martin's avatar
Ken Martin committed
69

70
  configFile += "/Templates/TestDriver.cxx.in";
71
  // Create the test driver file
Andy Cedilnik's avatar
Andy Cedilnik committed
72

73
  std::vector<std::string>::const_iterator testsBegin = i;
74
  std::vector<std::string> tests_func_name;
75
76

  // The rest of the arguments consist of a list of test source files.
Andy Cedilnik's avatar
Andy Cedilnik committed
77
  // Sadly, they can be in directories. Let's find a unique function
78
  // name for the corresponding test, and push it to the tests_func_name
Andy Cedilnik's avatar
Andy Cedilnik committed
79
  // list.
80
81
  // For the moment:
  //   - replace spaces ' ', ':' and '/' with underscores '_'
82
  std::string forwardDeclareCode;
83
84
  for (i = testsBegin; i != tests.end(); ++i) {
    if (*i == "EXTRA_INCLUDE") {
85
      break;
86
    }
Ken Martin's avatar
Ken Martin committed
87
    std::string func_name;
88
    if (!cmSystemTools::GetFilenamePath(*i).empty()) {
Andy Cedilnik's avatar
Andy Cedilnik committed
89
      func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
Ken Martin's avatar
Ken Martin committed
90
        cmSystemTools::GetFilenameWithoutLastExtension(*i);
91
    } else {
Ken Martin's avatar
Ken Martin committed
92
      func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
93
    }
94
    cmSystemTools::ConvertToUnixSlashes(func_name);
95
96
97
    std::replace(func_name.begin(), func_name.end(), ' ', '_');
    std::replace(func_name.begin(), func_name.end(), '/', '_');
    std::replace(func_name.begin(), func_name.end(), ':', '_');
98
    tests_func_name.push_back(func_name);
99
100
101
    forwardDeclareCode += "int ";
    forwardDeclareCode += func_name;
    forwardDeclareCode += "(int, char*[]);\n";
102
  }
Andy Cedilnik's avatar
Andy Cedilnik committed
103

104
  std::string functionMapCode;
105
  int numTests = 0;
106
  std::vector<std::string>::iterator j;
107
108
  for (i = testsBegin, j = tests_func_name.begin(); i != tests.end();
       ++i, ++j) {
Ken Martin's avatar
Ken Martin committed
109
    std::string func_name;
110
    if (!cmSystemTools::GetFilenamePath(*i).empty()) {
Andy Cedilnik's avatar
Andy Cedilnik committed
111
      func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
Ken Martin's avatar
Ken Martin committed
112
        cmSystemTools::GetFilenameWithoutLastExtension(*i);
113
    } else {
Ken Martin's avatar
Ken Martin committed
114
      func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
115
    }
116
    functionMapCode += "  {\n"
117
                       "    \"";
118
119
    functionMapCode += func_name;
    functionMapCode += "\",\n"
120
121
                       "    ";
    functionMapCode += *j;
122
    functionMapCode += "\n"
123
                       "  },\n";
124
    numTests++;
125
126
  }
  if (!extraInclude.empty()) {
Ken Martin's avatar
Ken Martin committed
127
128
    this->Makefile->AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES",
                                  extraInclude.c_str());
129
130
  }
  if (!function.empty()) {
Ken Martin's avatar
Ken Martin committed
131
132
    this->Makefile->AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION",
                                  function.c_str());
133
  }
Ken Martin's avatar
Ken Martin committed
134
  this->Makefile->AddDefinition("CMAKE_FORWARD_DECLARE_TESTS",
135
                                forwardDeclareCode.c_str());
Ken Martin's avatar
Ken Martin committed
136
  this->Makefile->AddDefinition("CMAKE_FUNCTION_TABLE_ENTIRES",
137
                                functionMapCode.c_str());
138
  bool res = true;
139
140
  if (!this->Makefile->ConfigureFile(configFile.c_str(), driver.c_str(), false,
                                     true, false)) {
141
    res = false;
142
  }
143

144
  // Construct the source list.
145
  std::string sourceListValue;
146
  {
147
148
149
    cmSourceFile* sf = this->Makefile->GetOrCreateSource(driver);
    sf->SetProperty("ABSTRACT", "0");
    sourceListValue = args[1];
150
  }
151
  for (i = testsBegin; i != tests.end(); ++i) {
Stephen Kelly's avatar
Stephen Kelly committed
152
    cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
153
    sf->SetProperty("ABSTRACT", "0");
154
155
    sourceListValue += ";";
    sourceListValue += *i;
156
  }
157

Ken Martin's avatar
Ken Martin committed
158
  this->Makefile->AddDefinition(sourceList, sourceListValue.c_str());
159
  return res;
160
}