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