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"
7 #include "cmExecutionStatus.h"
8 #include "cmMakefile.h"
9 #include "cmSourceFile.h"
10 #include "cmStringAlgorithms.h"
11 #include "cmSystemTools.h"
13 bool cmCreateTestSourceList(std::vector<std::string> const& args,
14 cmExecutionStatus& status)
16 if (args.size() < 3) {
17 status.SetError("called with wrong number of arguments.");
21 auto i = args.begin();
22 std::string extraInclude;
24 std::vector<std::string> tests;
25 // extract extra include and function ot
26 for (; i != args.end(); i++) {
27 if (*i == "EXTRA_INCLUDE") {
29 if (i == args.end()) {
30 status.SetError("incorrect arguments to EXTRA_INCLUDE");
33 extraInclude = cmStrCat("#include \"", *i, "\"\n");
34 } else if (*i == "FUNCTION") {
36 if (i == args.end()) {
37 status.SetError("incorrect arguments to FUNCTION");
40 function = cmStrCat(*i, "(&ac, &av);\n");
47 // Name of the source list
49 const char* sourceList = i->c_str();
52 // Name of the test driver
53 // make sure they specified an extension
54 if (cmSystemTools::GetFilenameExtension(*i).size() < 2) {
56 "You must specify a file extension for the test driver file.");
59 cmMakefile& mf = status.GetMakefile();
60 std::string driver = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', *i);
63 std::string configFile = cmSystemTools::GetCMakeRoot();
65 configFile += "/Templates/TestDriver.cxx.in";
66 // Create the test driver file
69 std::vector<std::string> tests_func_name;
71 // The rest of the arguments consist of a list of test source files.
72 // Sadly, they can be in directories. Let's find a unique function
73 // name for the corresponding test, and push it to the tests_func_name
76 // - replace spaces ' ', ':' and '/' with underscores '_'
77 std::string forwardDeclareCode;
78 for (i = testsBegin; i != tests.end(); ++i) {
79 if (*i == "EXTRA_INCLUDE") {
82 std::string func_name;
83 if (!cmSystemTools::GetFilenamePath(*i).empty()) {
84 func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
85 cmSystemTools::GetFilenameWithoutLastExtension(*i);
87 func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
89 cmSystemTools::ConvertToUnixSlashes(func_name);
90 std::replace(func_name.begin(), func_name.end(), ' ', '_');
91 std::replace(func_name.begin(), func_name.end(), '/', '_');
92 std::replace(func_name.begin(), func_name.end(), ':', '_');
93 bool already_declared =
94 std::find(tests_func_name.begin(), tests_func_name.end(), func_name) !=
95 tests_func_name.end();
96 tests_func_name.push_back(func_name);
97 if (!already_declared) {
98 forwardDeclareCode += "int ";
99 forwardDeclareCode += func_name;
100 forwardDeclareCode += "(int, char*[]);\n";
104 std::string functionMapCode;
105 std::vector<std::string>::iterator j;
106 for (i = testsBegin, j = tests_func_name.begin(); i != tests.end();
108 std::string func_name;
109 if (!cmSystemTools::GetFilenamePath(*i).empty()) {
110 func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
111 cmSystemTools::GetFilenameWithoutLastExtension(*i);
113 func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
115 functionMapCode += " {\n"
117 functionMapCode += func_name;
118 functionMapCode += "\",\n"
120 functionMapCode += *j;
121 functionMapCode += "\n"
124 if (!extraInclude.empty()) {
125 mf.AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES", extraInclude);
127 if (!function.empty()) {
128 mf.AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function);
130 mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
131 mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTRIES", functionMapCode);
133 if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
137 // Construct the source list.
138 std::string sourceListValue;
140 cmSourceFile* sf = mf.GetOrCreateSource(driver);
141 sf->SetProperty("ABSTRACT", "0");
142 sourceListValue = args[1];
144 for (i = testsBegin; i != tests.end(); ++i) {
145 cmSourceFile* sf = mf.GetOrCreateSource(*i);
146 sf->SetProperty("ABSTRACT", "0");
147 sourceListValue += ";";
148 sourceListValue += *i;
151 mf.AddDefinition(sourceList, sourceListValue);