summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-server.7.rst73
-rw-r--r--Source/cmLocalGenerator.cxx11
-rw-r--r--Source/cmMakefile.cxx7
-rw-r--r--Source/cmMakefile.h5
-rw-r--r--Source/cmServerDictionary.h5
-rw-r--r--Source/cmServerProtocol.cxx165
-rw-r--r--Source/cmServerProtocol.h1
7 files changed, 263 insertions, 4 deletions
diff --git a/Help/manual/cmake-server.7.rst b/Help/manual/cmake-server.7.rst
index 389a6d5..a2fd961 100644
--- a/Help/manual/cmake-server.7.rst
+++ b/Help/manual/cmake-server.7.rst
@@ -628,6 +628,79 @@ CMake will reply::
]== "CMake Server" ==]
+Type "ctestInfo"
+^^^^^^^^^^^^^^^^
+
+The "ctestInfo" request can be used after a project was "compute"d successfully.
+
+It will list the complete project test structure as it is known to cmake.
+
+The reply will contain a key "configurations", which will contain a list of
+configuration objects. Configuration objects are used to destinquish between
+different configurations the build directory might have enabled. While most
+generators only support one configuration, others might support several.
+
+Each configuration object can have the following keys:
+
+"name"
+ contains the name of the configuration. The name may be empty.
+"projects"
+ contains a list of project objects, one for each build project.
+
+Project objects define one (sub-)project defined in the cmake build system.
+
+Each project object can have the following keys:
+
+"name"
+ contains the (sub-)projects name.
+"targets"
+ contains a list of build system target objects.
+
+Target objects define individual build targets for a certain configuration.
+
+Each target object can have the following keys:
+
+"name"
+ contains the name of the target.
+"type"
+ defines the type of build of the target. Possible values are
+ "STATIC_LIBRARY", "MODULE_LIBRARY", "SHARED_LIBRARY", "OBJECT_LIBRARY",
+ "EXECUTABLE", "UTILITY" and "INTERFACE_LIBRARY".
+"fullName"
+ contains the full name of the build result (incl. extensions, etc.).
+"hasEnabledTests"
+ true if testing is enabled for this target.
+"ctestInfo"
+ contains a list of test objects for this target.
+
+Each test object can have the following keys:
+
+"ctestName"
+ contains the name of the test.
+"ctestCommand"
+ contains the test command.
+"properties"
+ contains a list of test property objects.
+"backtrace"
+ contains a list of backtrace objects that specify where the test was defined.
+
+Each backtrace object can have the following keys:
+
+"path"
+ contains the full path to the file containing the statement.
+"line"
+ contains the line number in the file where the statement was defined.
+"name"
+ contains the name of the statement that added the test.
+
+Each test property object can have the following keys:
+
+"key"
+ contains the test property key.
+"value"
+ contains the test property value.
+
+
Type "cmakeInputs"
^^^^^^^^^^^^^^^^^^
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 1a088ea..f47c2d4 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -222,7 +222,14 @@ void cmLocalGenerator::TraceDependencies()
void cmLocalGenerator::GenerateTestFiles()
{
+ std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
+ file += "/";
+ file += "CTestTestfile.cmake";
+
if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) {
+ if (cmSystemTools::FileExists(file)) {
+ cmSystemTools::RemoveFile(file);
+ }
return;
}
@@ -231,10 +238,6 @@ void cmLocalGenerator::GenerateTestFiles()
const std::string& config =
this->Makefile->GetConfigurations(configurationTypes, false);
- std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
- file += "/";
- file += "CTestTestfile.cmake";
-
cmGeneratedFileStream fout(file.c_str());
fout.SetCopyIfDifferent(true);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index b2641d2..90e0a0d 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -3282,6 +3282,13 @@ cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const
return this->GlobalGenerator;
}
+void cmMakefile::GetTestNames(std::vector<std::string>& testNames)
+{
+ for (const auto& iter : Tests) {
+ testNames.push_back(iter.first);
+ }
+}
+
#ifdef CMAKE_BUILD_WITH_CMAKE
cmVariableWatch* cmMakefile::GetVariableWatch() const
{
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 7c6cca5..01a9fb7 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -617,6 +617,11 @@ public:
cmGlobalGenerator* GetGlobalGenerator() const;
/**
+ * Get all the test names this makefile knows about
+ */
+ void GetTestNames(std::vector<std::string>& testNames);
+
+ /**
* Get all the source files this makefile knows about
*/
const std::vector<cmSourceFile*>& GetSourceFiles() const
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
index 03f1cc1..040c1fd 100644
--- a/Source/cmServerDictionary.h
+++ b/Source/cmServerDictionary.h
@@ -23,6 +23,7 @@ static const std::string kPROGRESS_TYPE = "progress";
static const std::string kREPLY_TYPE = "reply";
static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
static const std::string kSIGNAL_TYPE = "signal";
+static const std::string kCTEST_INFO_TYPE = "ctestInfo";
static const std::string kARTIFACTS_KEY = "artifacts";
static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
@@ -90,6 +91,10 @@ static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
static const std::string kWATCHED_FILES_KEY = "watchedFiles";
static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
static const std::string kINSTALL_PATHS = "installPaths";
+static const std::string kHAS_ENABLED_TESTS = "hasEnabledTests";
+static const std::string kCTEST_NAME = "ctestName";
+static const std::string kCTEST_COMMAND = "ctestCommand";
+static const std::string kCTEST_INFO = "ctestInfo";
static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences";
static const std::string kLINE_NUMBER_KEY = "line";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index fc06fed..0cb906b 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -14,6 +14,7 @@
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmServer.h"
#include "cmServerDictionary.h"
#include "cmSourceFile.h"
@@ -23,6 +24,7 @@
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTest.h"
#include "cm_uv.h"
#include "cmake.h"
@@ -479,6 +481,9 @@ const cmServerResponse cmServerProtocol1::Process(
if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
return this->ProcessSetGlobalSettings(request);
}
+ if (request.Type == kCTEST_INFO_TYPE) {
+ return this->ProcessCTests(request);
+ }
return request.ReportError("Unknown command!");
}
@@ -766,6 +771,153 @@ static void DumpBacktraceRange(Json::Value& result, const std::string& type,
}
}
+static Json::Value DumpCTestInfo(const std::string& name, cmTest* testInfo)
+{
+ Json::Value result = Json::objectValue;
+ result[kCTEST_NAME] = name;
+
+ // Concat command entries together. After the first should be the arguments
+ // for the command
+ std::string command;
+ for (auto const& cmd : testInfo->GetCommand()) {
+ command.append(cmd);
+ command.append(" ");
+ }
+ result[kCTEST_COMMAND] = command;
+
+ // Build up the list of properties that may have been specified
+ Json::Value properties = Json::arrayValue;
+ for (auto& prop : testInfo->GetProperties()) {
+ Json::Value entry = Json::objectValue;
+ entry[kKEY_KEY] = prop.first;
+ entry[kVALUE_KEY] = prop.second.GetValue();
+ properties.append(entry);
+ }
+ result[kPROPERTIES_KEY] = properties;
+
+ // Need backtrace to figure out where this test was originally added
+ result[kBACKTRACE_KEY] = DumpBacktrace(testInfo->GetBacktrace());
+
+ return result;
+}
+
+static Json::Value DumpCTestTarget(cmGeneratorTarget* target,
+ const std::string& config)
+{
+ cmLocalGenerator* lg = target->GetLocalGenerator();
+ const cmState* state = lg->GetState();
+
+ const cmStateEnums::TargetType type = target->GetType();
+ const std::string typeName = state->GetTargetTypeName(type);
+
+ Json::Value ttl = Json::arrayValue;
+ ttl.append("EXECUTABLE");
+ ttl.append("STATIC_LIBRARY");
+ ttl.append("SHARED_LIBRARY");
+ ttl.append("MODULE_LIBRARY");
+ ttl.append("OBJECT_LIBRARY");
+ ttl.append("UTILITY");
+ ttl.append("INTERFACE_LIBRARY");
+
+ if (!hasString(ttl, typeName) || target->IsImported()) {
+ return Json::Value();
+ }
+
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = target->GetName();
+ result[kTYPE_KEY] = typeName;
+
+ if (type == cmStateEnums::INTERFACE_LIBRARY) {
+ return result;
+ }
+ result[kFULL_NAME_KEY] = target->GetFullName(config);
+
+ if (target->Makefile->IsOn("CMAKE_TESTING_ENABLED")) {
+ result[kHAS_ENABLED_TESTS] = true;
+ std::vector<std::string> CTestNames;
+
+ Json::Value testInfo = Json::arrayValue;
+ std::vector<std::string> testNames;
+ target->Makefile->GetTestNames(testNames);
+ for (auto& name : testNames) {
+ auto test = target->Makefile->GetTest(name);
+ if (test != nullptr) {
+ testInfo.append(DumpCTestInfo(name, test));
+ }
+ }
+ result[kCTEST_INFO] = testInfo;
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestTargetsList(
+ const std::vector<cmLocalGenerator*>& generators, const std::string& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ std::vector<cmGeneratorTarget*> targetList;
+ for (const auto& lgIt : generators) {
+ auto list = lgIt->GetGeneratorTargets();
+ targetList.insert(targetList.end(), list.begin(), list.end());
+ }
+ std::sort(targetList.begin(), targetList.end());
+
+ for (cmGeneratorTarget* target : targetList) {
+ Json::Value tmp = DumpCTestTarget(target, config);
+ if (!tmp.isNull()) {
+ result.append(tmp);
+ }
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestProjectList(const cmake* cm,
+ std::string const& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ auto globalGen = cm->GetGlobalGenerator();
+
+ for (const auto& projectIt : globalGen->GetProjectMap()) {
+ Json::Value pObj = Json::objectValue;
+ pObj[kNAME_KEY] = projectIt.first;
+
+ // All Projects must have at least one local generator
+ assert(!projectIt.second.empty());
+
+ // Project structure information:
+ pObj[kTARGETS_KEY] = DumpCTestTargetsList(projectIt.second, config);
+
+ result.append(pObj);
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestConfiguration(const cmake* cm,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = config;
+
+ result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
+
+ return result;
+}
+
+static Json::Value DumpCTestConfigurationsList(const cmake* cm)
+{
+ Json::Value result = Json::arrayValue;
+
+ for (const std::string& c : getConfigurations(cm)) {
+ result.append(DumpCTestConfiguration(cm, c));
+ }
+
+ return result;
+}
+
static Json::Value DumpTarget(cmGeneratorTarget* target,
const std::string& config)
{
@@ -1222,6 +1374,19 @@ cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers(
return request.Reply(result);
}
+cmServerResponse cmServerProtocol1::ProcessCTests(
+ const cmServerRequest& request)
+{
+ if (this->m_State < STATE_COMPUTED) {
+ return request.ReportError("This instance was not yet computed.");
+ }
+
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] =
+ DumpCTestConfigurationsList(this->CMakeInstance());
+ return request.Reply(result);
+}
+
cmServerProtocol1::GeneratorInformation::GeneratorInformation(
const std::string& generatorName, const std::string& extraGeneratorName,
const std::string& toolset, const std::string& platform,
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 124ac7f..df71cff 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -123,6 +123,7 @@ private:
cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
+ cmServerResponse ProcessCTests(const cmServerRequest& request);
enum State
{