diff --git a/Help/command/cmake_instrumentation.rst b/Help/command/cmake_instrumentation.rst index 4ad8f1a1e0..0d2cd50330 100644 --- a/Help/command/cmake_instrumentation.rst +++ b/Help/command/cmake_instrumentation.rst @@ -37,15 +37,14 @@ Whenever ``cmake_instrumentation`` is invoked, a query file is generated in ``/.cmake/instrumentation/v1/query/generated`` to enable instrumentation with the provided arguments. -.. _`cmake_instrumentation Configure Content`: +.. _`cmake_instrumentation CUSTOM_CONTENT`: -Custom Configure Content -^^^^^^^^^^^^^^^^^^^^^^^^ +Custom CMake Content +^^^^^^^^^^^^^^^^^^^^ The ``CUSTOM_CONTENT`` argument specifies certain data from configure time to -include in each :ref:`cmake-instrumentation v1 Snippet File` that -corresponds to the configure step associated with the command. This may be used -to associate instrumentation data with certain information about its +include in each :ref:`cmake-instrumentation v1 CMake Content File`. This +may be used to associate instrumentation data with certain information about its configuration, such as the optimization level or whether it is part of a coverage build. @@ -102,12 +101,12 @@ equivalent JSON query file. ] } -This will also result in a configure content JSON being reported in each -:ref:`cmake-instrumentation v1 Snippet File` with the following contents: +This will also result in the following content included in each +:ref:`cmake-instrumentation v1 CMake Content File`: .. code-block:: json - { + "custom": { "myString": "string", "myList": [ "item1", "item2" diff --git a/Help/manual/cmake-instrumentation.7.rst b/Help/manual/cmake-instrumentation.7.rst index b6cee79593..e0d0fc2e2b 100644 --- a/Help/manual/cmake-instrumentation.7.rst +++ b/Help/manual/cmake-instrumentation.7.rst @@ -127,6 +127,10 @@ by setting :envvar:`CTEST_USE_VERBOSE_INSTRUMENTATION` to 1. Alternatively, you can use the `v1 Query Files`_ to enable instrumentation for CDash using the ``cdashSubmit`` and ``cdashVerbose`` options. +In order for the submitted ``Build.xml`` file to group the snippet files +correctly, all configure and build commands should be executed with CTest in +Dashboard Client mode. + .. _`cmake-instrumentation API v1`: API v1 @@ -164,7 +168,7 @@ subdirectories: ``data/content/`` A subset of the collected data, containing any - :ref:`cmake_instrumentation Configure Content` files. + `v1 CMake Content Files `_. ``data/trace/`` A subset of the collected data, containing the `Google Trace File`_ created @@ -302,9 +306,9 @@ Data version specifies the contents of the output files generated by the CMake instrumentation API as part of the `Data Collection`_ and `Indexing`_. A new version number will be created whenever previously included data is removed or reformatted such that scripts written to parse this data may become -incompatible with the new format. There are three types of data files generated: -the `v1 Snippet File`_, the `v1 Index File`_, and the `Google Trace File`_. -When using the `API v1`_, these files live in +incompatible with the new format. There are four types of data files generated: +the `v1 Snippet File`_, `v1 Index File`_, `v1 CMake Content File`_, and the +`Google Trace File`_. When using the `API v1`_, these files live in ``/.cmake/instrumentation/v1/data/`` under the project build tree. .. _`cmake-instrumentation v1 Snippet File`: @@ -359,17 +363,9 @@ and contain the following data: * ``test``: a single test executed by CTest ``target`` - The CMake target associated with the command. Included when ``role`` is - ``compile``, or ``link``, and when ``role`` is ``custom`` and the custom - command is attached to a target with :ref:`add_custom_command(TARGET)`. - - ``targetType`` - The :prop_tgt:`TYPE` of the target. Only included when ``role`` is - ``link``. - - ``targetLabels`` - The :prop_tgt:`LABELS` of the target. Only included when ``role`` is - ``link``. + The CMake target associated with the command. Only included when ``role`` is + ``compile`` or ``link``. In conjunction with ``cmakeContent``, this can + be used to look up the target type and labels. ``timeStart`` Time at which the command started, expressed as the number of milliseconds @@ -422,10 +418,10 @@ and contain the following data: The Average CPU Load at ``timeStart + duration``, or ``null`` if it cannot be determined. - ``configureContent`` - The path to a :ref:`cmake_instrumentation Configure Content` file located - under ``data``, which may contain information about the CMake configure - step corresponding to this data. + ``cmakeContent`` + The path to a `v1 CMake Content` file located under ``data``, which + contains information about the CMake configure and generate steps + responsible for generating the ``command`` in this snippet. Example: @@ -451,7 +447,7 @@ Example: }, "timeStart" : 1737053448177, "duration" : 31, - "configureContent" : "content/configure-2025-07-11T12-46-32-0572.json" + "cmakeContent" : "content/cmake-2025-07-11T12-46-32-0572.json" } v1 Index File @@ -534,6 +530,33 @@ Example: "trace": "trace/trace-.json" } +.. _`cmake-instrumentation v1 CMake Content File`: + +v1 CMake Content File +--------------------- + +CMake content files contain information about the CMake configure and generate +steps. Each `v1 Snippet File`_ provides the path to one of these files +corresponding to the CMake invocation responsible for generating its command. + +Each CMake content file contains the following: + + ``custom`` + An object containing arbitrary JSON data specified by the user with the + :ref:`cmake_instrumentation CUSTOM_CONTENT` functionality of the + :command:`cmake_instrumentation` command. + + ``targets`` + An object containing CMake targets, indexed by name, that have corresponding + instrumentation data. Each target contains the following: + + ``type`` + The target type. One of ``EXECUTABLE``, ``STATIC_LIBRARY``, + ``SHARED_LIBRARY`` or ``OBJECT_LIBRARY``. + + ``labels`` + The :prop_tgt:`LABELS` property of the target. + Google Trace File ----------------- diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 520fa681a7..da63da1d4a 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -626,48 +626,38 @@ void cmCTestBuildHandler::GenerateInstrumentationXML(cmXMLWriter& xml) xml.StartElement("Target"); xml.Attribute("name", target_name); - // Check if we have a link snippet for this target. - cmsys::Directory target_dir; - if (!target_dir.Load(targets_dir.GetFilePath(i))) { - cmSystemTools::Error( - cmStrCat("Error loading directory ", targets_dir.GetFilePath(i))); - } - Json::Value link_item; - for (unsigned int j = 0; j < target_dir.GetNumberOfFiles(); j++) { - std::string fname = target_dir.GetFile(j); - if (fname.rfind("link-", 0) == 0) { - std::string fpath = target_dir.GetFilePath(j); - cmJSONState parseState = cmJSONState(fpath, &link_item); - if (!parseState.errors.empty()) { - cmSystemTools::Error(parseState.GetErrorMessage(true)); - break; - } - - if (!link_item.isObject()) { - std::string error_msg = - cmStrCat("Expected snippet ", fpath, " to contain an object"); - cmSystemTools::Error(error_msg); - break; - } + // Load latest CMake content file + Json::Value target_data; + std::string cmake_content_file = + cmStrCat(CTest->GetInstrumentation().GetDataDir(), "/content/", + this->CTest->GetInstrumentation().GetFileByTimestamp( + cmInstrumentation::LatestOrOldest::Latest, "content")); + if (!cmake_content_file.empty() && + cmSystemTools::FileExists(cmake_content_file)) { + Json::Value cmake_content; + cmJSONState parseState = + cmJSONState(cmake_content_file, &cmake_content); + if (!parseState.errors.empty()) { + cmSystemTools::Error(parseState.GetErrorMessage(true)); break; } - } - - // If so, parse targetType and targetLabels (optional) from it. - if (link_item.isMember("targetType")) { - target_type = link_item["targetType"].asString(); - } - - xml.Attribute("type", target_type); - - if (link_item.isMember("targetLabels") && - !link_item["targetLabels"].empty()) { - xml.StartElement("Labels"); - for (auto const& json_label_item : link_item["targetLabels"]) { - xml.Element("Label", json_label_item.asString()); + if (cmake_content.isMember("targets")) { + target_data = cmake_content["targets"]; } - xml.EndElement(); // Labels } + // Extract targetType and targetLabels + if (target_data.isObject() && target_data.isMember(target_name)) { + target_type = target_data[target_name]["type"].asString(); + if (!target_data[target_name]["labels"].empty()) { + xml.StartElement("Labels"); + for (auto const& json_label_item : + target_data[target_name]["labels"]) { + xml.Element("Label", json_label_item.asString()); + } + xml.EndElement(); // Labels + } + } + xml.Attribute("type", target_type); // Write instrumendation data for this target. std::string target_subdir = cmStrCat("build/targets/", target_name); diff --git a/Source/cmFastbuildNormalTargetGenerator.cxx b/Source/cmFastbuildNormalTargetGenerator.cxx index 6163c70689..1bf934278a 100644 --- a/Source/cmFastbuildNormalTargetGenerator.cxx +++ b/Source/cmFastbuildNormalTargetGenerator.cxx @@ -257,8 +257,6 @@ bool cmFastbuildNormalTargetGenerator::DetectBaseLinkerCommand( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str(); - vars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); vars.Config = Config.c_str(); vars.Language = linkLanguage.c_str(); std::string const manifests = @@ -1133,8 +1131,6 @@ cmFastbuildNormalTargetGenerator::ComputeRuleVariables() const compileObjectVars.CMTargetName = GeneratorTarget->GetName().c_str(); compileObjectVars.CMTargetType = cmState::GetTargetTypeName(GeneratorTarget->GetType()).c_str(); - compileObjectVars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); compileObjectVars.Source = FASTBUILD_1_INPUT_PLACEHOLDER; compileObjectVars.Object = FASTBUILD_2_INPUT_PLACEHOLDER; compileObjectVars.ObjectDir = diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index b74cfcaeac..3564771509 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2095,14 +2095,6 @@ std::vector cmGeneratorTarget::GetAppleArchs( return std::move(archList.data()); } -std::string const& cmGeneratorTarget::GetTargetLabelsString() -{ - this->targetLabelsString = this->GetSafeProperty("LABELS"); - std::replace(this->targetLabelsString.begin(), - this->targetLabelsString.end(), ';', ','); - return this->targetLabelsString; -} - namespace { bool IsSupportedClassifiedFlagsLanguage(std::string const& lang) @@ -2367,7 +2359,6 @@ cmGeneratorTarget::GetClassifiedFlagsForSource(cmSourceFile const* sf, cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GetType()).c_str(); - vars.CMTargetLabels = this->GetTargetLabelsString().c_str(); vars.Language = lang.c_str(); auto const sfPath = this->LocalGenerator->ConvertToOutputFormat( diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index f8116f74e2..e506bbd53d 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -535,8 +535,6 @@ public: std::vector GetAppleArchs(std::string const& config, cm::optional lang) const; - std::string const& GetTargetLabelsString(); - // The classification of the flag. enum class FlagClassification { diff --git a/Source/cmInstrumentation.cxx b/Source/cmInstrumentation.cxx index b3dfa260e9..b7298fce2e 100644 --- a/Source/cmInstrumentation.cxx +++ b/Source/cmInstrumentation.cxx @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -27,8 +28,13 @@ #include "cmExperimental.h" #include "cmFileLock.h" #include "cmFileLockResult.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" #include "cmInstrumentationQuery.h" #include "cmJSONState.h" +#include "cmList.h" +#include "cmLocalGenerator.h" +#include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -94,6 +100,7 @@ cmInstrumentation::cmInstrumentation(std::string const& binary_dir, this->timingDirv1 = cmStrCat(this->binaryDir, "/.cmake/instrumentation-", uuid, "/v1"); this->cdashDir = cmStrCat(this->timingDirv1, "/cdash"); + this->dataDir = cmStrCat(this->timingDirv1, "/data"); if (cm::optional configDir = cmSystemTools::GetCMakeConfigDirectory()) { this->userTimingDirv1 = @@ -221,20 +228,45 @@ void cmInstrumentation::AddCustomContent(std::string const& name, this->customContent[name] = contents; } -void cmInstrumentation::WriteCustomContent() +void cmInstrumentation::WriteCMakeContent( + std::unique_ptr const& gg) { - if (!this->customContent.isNull()) { - this->WriteInstrumentationJson( - this->customContent, "data/content", - cmStrCat("configure-", this->ComputeSuffixTime(), ".json")); + Json::Value root; + root["targets"] = this->DumpTargets(gg); + root["custom"] = this->customContent; + this->WriteInstrumentationJson( + root, "data/content", + cmStrCat("cmake-", this->ComputeSuffixTime(), ".json")); +} + +Json::Value cmInstrumentation::DumpTargets( + std::unique_ptr const& gg) +{ + Json::Value targets = Json::objectValue; + std::vector targetList; + for (auto const& lg : gg->GetLocalGenerators()) { + cm::append(targetList, lg->GetGeneratorTargets()); } + for (cmGeneratorTarget* gt : targetList) { + if (this->IsInstrumentableTargetType(gt->GetType())) { + Json::Value target = Json::objectValue; + auto labels = gt->GetSafeProperty("LABELS"); + target["labels"] = Json::arrayValue; + for (auto const& item : cmList(labels)) { + target["labels"].append(item); + } + target["type"] = cmState::GetTargetTypeName(gt->GetType()).c_str(); + targets[gt->GetName()] = target; + } + } + return targets; } std::string cmInstrumentation::GetFileByTimestamp( cmInstrumentation::LatestOrOldest order, std::string const& dataSubdir, std::string const& exclude) { - std::string fullDir = cmStrCat(this->timingDirv1, "/data/", dataSubdir); + std::string fullDir = cmStrCat(this->dataDir, '/', dataSubdir); std::string result; if (cmSystemTools::FileExists(fullDir)) { cmsys::Directory d; @@ -255,12 +287,11 @@ std::string cmInstrumentation::GetFileByTimestamp( void cmInstrumentation::RemoveOldFiles(std::string const& dataSubdir) { - std::string const dataSubdirPath = - cmStrCat(this->timingDirv1, "/data/", dataSubdir); + std::string const dataSubdirPath = cmStrCat(this->dataDir, '/', dataSubdir); std::string oldIndex = this->GetFileByTimestamp(LatestOrOldest::Oldest, "index"); if (!oldIndex.empty()) { - oldIndex = cmStrCat(this->timingDirv1, "/data/index/", oldIndex); + oldIndex = cmStrCat(this->dataDir, "/index/", oldIndex); } if (cmSystemTools::FileExists(dataSubdirPath)) { std::string latestFile = @@ -316,10 +347,9 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) } // Touch index file immediately to claim snippets - std::string const& directory = cmStrCat(this->timingDirv1, "/data"); std::string suffix_time = ComputeSuffixTime(); std::string const& index_name = cmStrCat("index-", suffix_time, ".json"); - std::string index_path = cmStrCat(directory, "/index/", index_name); + std::string index_path = cmStrCat(this->dataDir, "/index/", index_name); cmSystemTools::Touch(index_path, true); // Gather Snippets @@ -328,7 +358,7 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) cmsys::Directory d; std::string last_index_name = this->GetFileByTimestamp(LatestOrOldest::Latest, "index", index_name); - if (d.Load(directory)) { + if (d.Load(this->dataDir)) { for (unsigned int i = 0; i < d.GetNumberOfFiles(); i++) { std::string fpath = d.GetFilePath(i); std::string fname = d.GetFile(i); @@ -343,7 +373,7 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) Json::Value index(Json::objectValue); index["snippets"] = Json::arrayValue; index["hook"] = cmInstrumentationQuery::HookString[hook]; - index["dataDir"] = directory; + index["dataDir"] = this->dataDir; index["buildDir"] = this->binaryDir; index["version"] = 1; if (this->HasOption( @@ -356,7 +386,7 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) } else { int compare; std::string last_index_path = - cmStrCat(directory, "/index/", last_index_name); + cmStrCat(this->dataDir, "/index/", last_index_name); cmSystemTools::FileTimeCompare(file.second, last_index_path, &compare); if (compare == 1) { index["snippets"].append(file.first); @@ -383,12 +413,12 @@ int cmInstrumentation::CollectTimingData(cmInstrumentationQuery::Hook hook) // Special case for CDash collation if (this->HasOption(cmInstrumentationQuery::Option::CDashSubmit)) { - this->PrepareDataForCDash(directory, index_path); + this->PrepareDataForCDash(this->dataDir, index_path); } // Delete files for (auto const& f : index["snippets"]) { - cmSystemTools::RemoveFile(cmStrCat(directory, '/', f.asString())); + cmSystemTools::RemoveFile(cmStrCat(this->dataDir, '/', f.asString())); } cmSystemTools::RemoveFile(index_path); @@ -605,11 +635,6 @@ int cmInstrumentation::InstrumentCommand( int ret = callback(); root["result"] = ret; - // Write configure content if command was configure - if (command_type == "configure") { - this->WriteCustomContent(); - } - // Exit early if configure didn't generate a query if (reloadQueriesAfterCommand == LoadQueriesAfter::Yes) { this->LoadQueries(); @@ -675,11 +700,16 @@ int cmInstrumentation::InstrumentCommand( root["role"] = command_type; root["workingDir"] = cmSystemTools::GetLogicalWorkingDirectory(); - // Add custom configure content - std::string contentFile = - this->GetFileByTimestamp(LatestOrOldest::Latest, "content"); - if (!contentFile.empty()) { - root["configureContent"] = cmStrCat("content/", contentFile); + auto addCMakeContent = [this](Json::Value& root_) -> void { + std::string contentFile = + this->GetFileByTimestamp(LatestOrOldest::Latest, "content"); + if (!contentFile.empty()) { + root_["cmakeContent"] = cmStrCat("content/", contentFile); + } + }; + // Don't insert path to CMake content until generate time + if (command_type != "configure") { + addCMakeContent(root); } // Write Json @@ -690,7 +720,21 @@ int cmInstrumentation::InstrumentCommand( command_type, '-', this->ComputeSuffixHash(cmStrCat(command_str, info.GetProcessId())), '-', this->ComputeSuffixTime(endTime), ".json"); - this->WriteInstrumentationJson(root, "data", file_name); + + // Don't write configure snippet until generate time + if (command_type == "configure") { + this->configureSnippetData = root; + this->configureSnippetName = file_name; + } else { + // Add reference to CMake content and write out configure snippet after + // generate + if (command_type == "generate") { + addCMakeContent(this->configureSnippetData); + this->WriteInstrumentationJson(this->configureSnippetData, "data", + this->configureSnippetName); + } + this->WriteInstrumentationJson(root, "data", file_name); + } return ret; } @@ -736,6 +780,15 @@ std::string cmInstrumentation::ComputeSuffixTime( return ss.str(); } +bool cmInstrumentation::IsInstrumentableTargetType( + cmStateEnums::TargetType type) +{ + return type == cmStateEnums::TargetType::EXECUTABLE || + type == cmStateEnums::TargetType::SHARED_LIBRARY || + type == cmStateEnums::TargetType::STATIC_LIBRARY || + type == cmStateEnums::TargetType::OBJECT_LIBRARY; +} + /* * Called by ctest --start-instrumentation. * @@ -818,11 +871,16 @@ void cmInstrumentation::AddOption(cmInstrumentationQuery::Option option) this->options.insert(option); } -std::string const& cmInstrumentation::GetCDashDir() +std::string const& cmInstrumentation::GetCDashDir() const { return this->cdashDir; } +std::string const& cmInstrumentation::GetDataDir() const +{ + return this->dataDir; +} + /** Copy the snippets referred to by an index file to a separate * directory where they will be parsed for submission to CDash. **/ diff --git a/Source/cmInstrumentation.h b/Source/cmInstrumentation.h index 4abcbe5a6a..aba0f37935 100644 --- a/Source/cmInstrumentation.h +++ b/Source/cmInstrumentation.h @@ -17,13 +17,16 @@ #include #include -#include "cmFileLock.h" #ifndef CMAKE_BOOTSTRAP # include #endif #include +#include "cmFileLock.h" #include "cmInstrumentationQuery.h" +#include "cmStateTypes.h" + +class cmGlobalGenerator; class cmInstrumentation { @@ -61,7 +64,8 @@ public: std::set const& hooks, std::vector> const& callback); void AddCustomContent(std::string const& name, Json::Value const& contents); - void WriteCustomContent(); + void WriteCMakeContent(std::unique_ptr const& gg); + Json::Value DumpTargets(std::unique_ptr const& gg); void ClearGeneratedQueries(); int CollectTimingData(cmInstrumentationQuery::Hook hook); int SpawnBuildDaemon(); @@ -70,7 +74,16 @@ public: void AddHook(cmInstrumentationQuery::Hook hook); void AddOption(cmInstrumentationQuery::Option option); bool HasErrors() const; - std::string const& GetCDashDir(); + std::string const& GetCDashDir() const; + std::string const& GetDataDir() const; + enum LatestOrOldest + { + Latest, + Oldest + }; + std::string GetFileByTimestamp(LatestOrOldest latestOrOldest, + std::string const& dataSubdir, + std::string const& exclude = ""); private: Json::Value ReadJsonSnippet(std::string const& file_name); @@ -89,6 +102,7 @@ private: static std::string ComputeSuffixHash(std::string const& command_str); static std::string ComputeSuffixTime( cm::optional time = cm::nullopt); + static bool IsInstrumentableTargetType(cmStateEnums::TargetType type); void PrepareDataForCDash(std::string const& data_dir, std::string const& index_path); void RemoveOldFiles(std::string const& dataSubdir); @@ -97,18 +111,11 @@ private: Json::Value const& snippetData); size_t AssignTargetToTraceThread(std::vector& workers, uint64_t timeStart, uint64_t duration); - enum LatestOrOldest - { - Latest, - Oldest - }; - std::string GetFileByTimestamp(LatestOrOldest latestOrOldest, - std::string const& dataSubdir, - std::string const& exclude = ""); std::string binaryDir; std::string timingDirv1; std::string userTimingDirv1; std::string cdashDir; + std::string dataDir; std::set options; std::set hooks; std::vector callbacks; @@ -120,6 +127,8 @@ private: bool ranSystemChecks = false; bool ranOSCheck = false; Json::Value customContent; + Json::Value configureSnippetData; + std::string configureSnippetName; #ifndef CMAKE_BOOTSTRAP std::unique_ptr systemInformation; cmsys::SystemInformation& GetSystemInformation(); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index c370d18150..d9b2c0fc97 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1055,7 +1055,6 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand( vars.CMTargetName = target->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(target->GetType()).c_str(); - vars.CMTargetLabels = target->GetTargetLabelsString().c_str(); std::string output; std::vector const& outputs = ccg.GetOutputs(); for (size_t i = 0; i < outputs.size(); ++i) { diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 30432cc79b..e966f64596 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -545,8 +545,6 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); - vars.CMTargetLabels = - this->GeneratorTarget->GetTargetLabelsString().c_str(); vars.Language = linkLanguage.c_str(); vars.Linker = linker.c_str(); vars.AIXExports = aixExports.c_str(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 6feffbd978..9493dc95d6 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -792,8 +792,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); - vars.CMTargetLabels = - this->GeneratorTarget->GetTargetLabelsString().c_str(); vars.Language = linkLanguage.c_str(); vars.Linker = linker.c_str(); vars.AIXExports = aixExports.c_str(); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 733c549393..ae18f9bbb2 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -932,7 +932,6 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( vars.CMTargetName = this->GeneratorTarget->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str(); - vars.CMTargetLabels = this->GeneratorTarget->GetTargetLabelsString().c_str(); vars.Language = lang.c_str(); vars.Target = targetOutPathReal.c_str(); vars.TargetPDB = targetOutPathPDB.c_str(); @@ -1713,7 +1712,6 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule( vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str(); - vars.CMTargetLabels = this->GeneratorTarget->GetTargetLabelsString().c_str(); vars.Language = "CUDA"; vars.Object = output.c_str(); vars.Fatbinary = fatbinaryOutput.c_str(); diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 153bb4e41e..3b5681ac80 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -294,9 +294,6 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule( vars.CMTargetType = cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) .c_str(); - vars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); - vars.Language = "CUDA"; std::string linker = this->GetGeneratorTarget()->GetLinkerTool("CUDA", config); @@ -404,9 +401,6 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules( vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str(); - vars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); - vars.Language = "CUDA"; vars.Object = "$out"; vars.Fatbinary = "$FATBIN"; @@ -466,9 +460,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule( cmRulePlaceholderExpander::RuleVariables vars; vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str(); - vars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); - std::string linker = this->GetGeneratorTarget()->GetLinkerTool(config); vars.Linker = linker.c_str(); std::string lang = this->TargetLinkLanguage(config); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index c11b693f63..c9cec0d518 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -596,7 +596,6 @@ cmNinjaRule GetScanRule( cmRulePlaceholderExpander::RuleVariables scanVars; scanVars.CMTargetName = vars.CMTargetName; scanVars.CMTargetType = vars.CMTargetType; - scanVars.CMTargetLabels = vars.CMTargetLabels; scanVars.Language = vars.Language; scanVars.Object = "$OBJ_FILE"; scanVars.PreprocessedSource = ppFileName.c_str(); @@ -656,8 +655,6 @@ void cmNinjaTargetGenerator::WriteCompileRule(std::string const& lang, vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str(); vars.CMTargetType = cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()).c_str(); - vars.CMTargetLabels = - this->GetGeneratorTarget()->GetTargetLabelsString().c_str(); vars.Language = lang.c_str(); vars.Source = "$in"; vars.Object = "$out"; diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx index 4892b7c64c..9261007d50 100644 --- a/Source/cmRulePlaceholderExpander.cxx +++ b/Source/cmRulePlaceholderExpander.cxx @@ -266,13 +266,6 @@ std::string cmRulePlaceholderExpander::ExpandVariable( return this->ReplaceValues->CMTargetType; } } - if (variable == "TARGET_LABELS") { - if (this->ReplaceValues->CMTargetLabels) { - return this->ReplaceValues->CMTargetLabels; - } - return ""; - } - if (this->ReplaceValues->Output) { if (variable == "OUTPUT") { return this->ReplaceValues->Output; diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h index d0c3687b6b..bb6250f321 100644 --- a/Source/cmRulePlaceholderExpander.h +++ b/Source/cmRulePlaceholderExpander.h @@ -32,7 +32,6 @@ public: { char const* CMTargetName = nullptr; char const* CMTargetType = nullptr; - char const* CMTargetLabels = nullptr; char const* TargetPDB = nullptr; char const* TargetCompilePDB = nullptr; char const* TargetVersionMajor = nullptr; diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 6a3dd2f582..c15e28856c 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -2761,8 +2761,7 @@ int cmake::ActualConfigure() "RULE_LAUNCH_LINK", cmStrCat( launcher, "--command-type link", common_args, - "--output --target-type " - "--language --target-labels \"\" -- ")); + "--output --config --language -- ")); this->State->SetGlobalProperty( "RULE_LAUNCH_CUSTOM", cmStrCat(launcher, "--command-type custom", common_args, @@ -3116,6 +3115,9 @@ int cmake::Generate() return -1; } this->GlobalGenerator->Generate(); + if (this->Instrumentation->HasQuery()) { + this->Instrumentation->WriteCMakeContent(this->GlobalGenerator); + } return 0; }; diff --git a/Tests/RunCMake/Instrumentation/check-custom-content.cmake b/Tests/RunCMake/Instrumentation/check-custom-content.cmake index 61764f8f23..3912445ca1 100644 --- a/Tests/RunCMake/Instrumentation/check-custom-content.cmake +++ b/Tests/RunCMake/Instrumentation/check-custom-content.cmake @@ -10,25 +10,39 @@ if (NOT ${num} EQUAL 2) add_error("Found ${num} custom content files, expected 2.") endif() -# Check contents of configureContent files +# Check contents of cmakeContent files set(firstFile "") foreach(content_file IN LISTS content_files) read_json("${content_file}" contents) - json_assert_key("${content_file}" "${contents}" myString "string") - json_assert_key("${content_file}" "${contents}" myBool "OFF") - json_assert_key("${content_file}" "${contents}" myInt "1") - json_assert_key("${content_file}" "${contents}" myFloat "2.5") - json_assert_key("${content_file}" "${contents}" myTrue "ON") - json_assert_key("${content_file}" "${contents}" myList "[ \"a\", \"b\", \"c\" ]") - json_assert_key("${content_file}" "${contents}" myObject "{.*\"key\".*:.*\"value\".*}") + + # Check custom content + string(JSON custom GET "${contents}" custom) + json_assert_key("${content_file}" "${custom}" myString "string") + json_assert_key("${content_file}" "${custom}" myBool "OFF") + json_assert_key("${content_file}" "${custom}" myInt "1") + json_assert_key("${content_file}" "${custom}" myFloat "2.5") + json_assert_key("${content_file}" "${custom}" myTrue "ON") + json_assert_key("${content_file}" "${custom}" myList "\\[ \"a\", \"b\", \"c\" \\]") + json_assert_key("${content_file}" "${custom}" myObject "{.*\"key\".*:.*\"value\".*}") if (NOT firstFile) set(firstFile "${content_file}") endif() if ("${content_file}" STREQUAL "${firstFile}") - string(JSON firstN GET "${contents}" nConfigure) + string(JSON firstN GET "${custom}" nConfigure) else() - string(JSON secondN GET "${contents}" nConfigure) + string(JSON secondN GET "${custom}" nConfigure) endif() + + # Check target content + string(JSON targets GET "${contents}" targets) + string(JSON targetData GET "${targets}" lib) + json_assert_key("${content_file}" "${targetData}" labels "\\[ \"label3\" \\]") + json_assert_key("${content_file}" "${targetData}" type "STATIC_LIBRARY") + + string(JSON targetData GET "${targets}" main) + json_assert_key("${content_file}" "${targetData}" labels "\\[ \"label1\", \"label2\" \\]") + json_assert_key("${content_file}" "${targetData}" type "EXECUTABLE") + endforeach() # Ensure provided -DN=* arguments result in differing JSON contents @@ -40,7 +54,7 @@ endif() # Ensure snippets reference valid files foreach(snippet IN LISTS snippets) read_json("${snippet}" contents) - string(JSON filename GET "${contents}" configureContent) + string(JSON filename GET "${contents}" cmakeContent) if (NOT EXISTS "${v1}/data/${filename}") add_error("Reference to content file that does not exist.") endif() diff --git a/Tests/RunCMake/Instrumentation/check-data-dir.cmake b/Tests/RunCMake/Instrumentation/check-data-dir.cmake index 42a3aaf728..5d96b39b04 100644 --- a/Tests/RunCMake/Instrumentation/check-data-dir.cmake +++ b/Tests/RunCMake/Instrumentation/check-data-dir.cmake @@ -51,36 +51,8 @@ foreach(snippet IN LISTS snippets) # Verify contents of link-* Snippets if (filename MATCHES "^link-") string(JSON target GET "${contents}" target) - string(JSON targetType GET "${contents}" targetType) - string(JSON targetLabels GET "${contents}" targetLabels) - if (target MATCHES "main") - if (NOT targetType MATCHES "EXECUTABLE") - json_error("${snippet}" "Expected EXECUTABLE, target type was ${targetType}") - endif() - string(JSON nlabels LENGTH "${targetLabels}") - if (NOT nlabels STREQUAL 2) - json_error("${snippet}" "Missing Target Labels for: ${target}") - else() - string(JSON label1 GET "${contents}" targetLabels 0) - string(JSON label2 GET "${contents}" targetLabels 1) - if (NOT label1 MATCHES "label1" OR NOT label2 MATCHES "label2") - json_error("${snippet}" "Missing Target Labels for: ${target}") - endif() - endif() - endif() - if (target MATCHES "lib") - if (NOT targetType MATCHES "STATIC_LIBRARY") - json_error("${snippet}" "Expected STATIC_LIBRARY, target type was ${targetType}") - endif() - string(JSON nlabels LENGTH "${targetLabels}") - if (NOT nlabels STREQUAL 1) - json_error("${snippet}" "Missing Target Labels for: ${target}") - else() - string(JSON label ERROR_VARIABLE noLabels GET "${contents}" targetLabels 0) - if (NOT label MATCHES "label3") - json_error("${snippet}" "Missing Target Labels for: ${target}") - endif() - endif() + if (NOT target MATCHES "main|lib") + json_error("${snippet}" "Unexpected link target: ${target}") endif() endif() diff --git a/Tests/RunCMake/Instrumentation/verify-snippet.cmake b/Tests/RunCMake/Instrumentation/verify-snippet.cmake index 37913f56e4..fed51383e6 100644 --- a/Tests/RunCMake/Instrumentation/verify-snippet.cmake +++ b/Tests/RunCMake/Instrumentation/verify-snippet.cmake @@ -14,8 +14,6 @@ function(snippet_has_fields snippet contents) json_has_key("${snippet}" "${contents}" target) json_has_key("${snippet}" "${contents}" outputs) json_has_key("${snippet}" "${contents}" outputSizes) - json_has_key("${snippet}" "${contents}" targetType) - json_has_key("${snippet}" "${contents}" targetLabels) json_has_key("${snippet}" "${contents}" config) json_has_key("${snippet}" "${contents}" language) elseif (filename MATCHES "^compile-*")