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