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 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";
102 std::string functionMapCode;
103 std::vector<std::string>::iterator j;
104 for (i = testsBegin, j = tests_func_name.begin(); i != tests.end();
106 std::string func_name;
107 if (!cmSystemTools::GetFilenamePath(*i).empty()) {
108 func_name = cmSystemTools::GetFilenamePath(*i) + "/" +
109 cmSystemTools::GetFilenameWithoutLastExtension(*i);
111 func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i);
113 functionMapCode += " {\n"
115 functionMapCode += func_name;
116 functionMapCode += "\",\n"
118 functionMapCode += *j;
119 functionMapCode += "\n"
122 if (!extraInclude.empty()) {
123 mf.AddDefinition("CMAKE_TESTDRIVER_EXTRA_INCLUDES", extraInclude);
125 if (!function.empty()) {
126 mf.AddDefinition("CMAKE_TESTDRIVER_ARGVC_FUNCTION", function);
128 mf.AddDefinition("CMAKE_FORWARD_DECLARE_TESTS", forwardDeclareCode);
129 mf.AddDefinition("CMAKE_FUNCTION_TABLE_ENTRIES", functionMapCode);
131 if (!mf.ConfigureFile(configFile, driver, false, true, false)) {
135 // Construct the source list.
136 std::string sourceListValue;
138 cmSourceFile* sf = mf.GetOrCreateSource(driver);
139 sf->SetProperty("ABSTRACT", "0");
140 sourceListValue = args[1];
142 for (i = testsBegin; i != tests.end(); ++i) {
143 cmSourceFile* sf = mf.GetOrCreateSource(*i);
144 sf->SetProperty("ABSTRACT", "0");
145 sourceListValue += ";";
146 sourceListValue += *i;
149 mf.AddDefinition(sourceList, sourceListValue);