diff options
Diffstat (limited to 'Source/cmCreateTestSourceList.cxx')
-rw-r--r-- | Source/cmCreateTestSourceList.cxx | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx new file mode 100644 index 0000000..a2fac73 --- /dev/null +++ b/Source/cmCreateTestSourceList.cxx @@ -0,0 +1,155 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt 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 ot + 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 + + const char* 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 = cmSystemTools::GetFilenamePath(*i) + "/" + + cmSystemTools::GetFilenameWithoutLastExtension(*i); + } else { + func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i); + } + cmSystemTools::ConvertToUnixSlashes(func_name); + std::replace(func_name.begin(), func_name.end(), ' ', '_'); + std::replace(func_name.begin(), func_name.end(), '/', '_'); + std::replace(func_name.begin(), func_name.end(), ':', '_'); + 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 += "int "; + forwardDeclareCode += func_name; + forwardDeclareCode += "(int, char*[]);\n"; + } + } + + std::string functionMapCode; + int numTests = 0; + 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 = cmSystemTools::GetFilenamePath(*i) + "/" + + cmSystemTools::GetFilenameWithoutLastExtension(*i); + } else { + func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i); + } + functionMapCode += " {\n" + " \""; + functionMapCode += func_name; + functionMapCode += "\",\n" + " "; + functionMapCode += *j; + functionMapCode += "\n" + " },\n"; + numTests++; + } + 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 = args[1]; + } + 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; +} |