mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-23 15:38:52 -06:00
cmDyndepCollation: update template module database files if requested
This commit is contained in:
@@ -37,6 +37,40 @@ cmBuildDatabase::cmBuildDatabase() = default;
|
||||
cmBuildDatabase::cmBuildDatabase(cmBuildDatabase const&) = default;
|
||||
cmBuildDatabase::~cmBuildDatabase() = default;
|
||||
|
||||
cmBuildDatabase::LookupTable cmBuildDatabase::GenerateLookupTable()
|
||||
{
|
||||
LookupTable lut;
|
||||
|
||||
for (auto& Set_ : this->Sets) {
|
||||
for (auto& TranslationUnit_ : Set_.TranslationUnits) {
|
||||
// This table is from source path to TU instance. This is fine because a
|
||||
// single target (where this is used) cannot contain the same source file
|
||||
// multiple times.
|
||||
lut[TranslationUnit_.Source] = &TranslationUnit_;
|
||||
}
|
||||
}
|
||||
|
||||
return lut;
|
||||
}
|
||||
|
||||
bool cmBuildDatabase::HasPlaceholderNames() const
|
||||
{
|
||||
for (auto const& Set_ : this->Sets) {
|
||||
for (auto const& TranslationUnit_ : Set_.TranslationUnits) {
|
||||
for (auto const& provide : TranslationUnit_.Provides) {
|
||||
if (provide.first == PlaceholderName) {
|
||||
return true;
|
||||
}
|
||||
if (provide.second == PlaceholderName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void cmBuildDatabase::Write(std::string const& path) const
|
||||
{
|
||||
Json::Value mcdb = Json::objectValue;
|
||||
|
||||
@@ -41,6 +41,14 @@ public:
|
||||
cmBuildDatabase(cmBuildDatabase const&);
|
||||
~cmBuildDatabase();
|
||||
|
||||
using LookupTable = std::map<std::string, TranslationUnit*>;
|
||||
// Generate a lookup table for the database.
|
||||
//
|
||||
// Only use when loading a single target's database in order to populate it.
|
||||
LookupTable GenerateLookupTable();
|
||||
|
||||
bool HasPlaceholderNames() const;
|
||||
|
||||
void Write(std::string const& path) const;
|
||||
|
||||
static std::unique_ptr<cmBuildDatabase> Load(std::string const& path);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <cm3p/json/value.h>
|
||||
|
||||
#include "cmBuildDatabase.h"
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
#include "cmExportSet.h"
|
||||
#include "cmFileSet.h"
|
||||
@@ -344,6 +345,12 @@ struct CxxModuleFileSet
|
||||
cm::optional<std::string> Destination;
|
||||
};
|
||||
|
||||
struct CxxModuleDatabaseInfo
|
||||
{
|
||||
std::string TemplatePath;
|
||||
std::string Output;
|
||||
};
|
||||
|
||||
struct CxxModuleBmiInstall
|
||||
{
|
||||
std::string Component;
|
||||
@@ -370,6 +377,7 @@ struct cmCxxModuleExportInfo
|
||||
{
|
||||
std::map<std::string, SourceInfo> ObjectToSource;
|
||||
std::map<std::string, CxxModuleFileSet> ObjectToFileSet;
|
||||
cm::optional<CxxModuleDatabaseInfo> DatabaseInfo;
|
||||
cm::optional<CxxModuleBmiInstall> BmiInstallation;
|
||||
std::vector<CxxModuleExport> Exports;
|
||||
std::string Config;
|
||||
@@ -494,6 +502,21 @@ bool cmDyndepCollation::WriteDyndepMetadata(
|
||||
exports.emplace_back(std::move(properties), &exp);
|
||||
}
|
||||
|
||||
std::unique_ptr<cmBuildDatabase> module_database;
|
||||
cmBuildDatabase::LookupTable build_database_lookup;
|
||||
if (export_info.DatabaseInfo) {
|
||||
module_database =
|
||||
cmBuildDatabase::Load(export_info.DatabaseInfo->TemplatePath);
|
||||
if (module_database) {
|
||||
build_database_lookup = module_database->GenerateLookupTable();
|
||||
} else {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("Failed to read the template build database ",
|
||||
export_info.DatabaseInfo->TemplatePath));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<cmGeneratedFileStream> bmi_install_script;
|
||||
if (export_info.BmiInstallation) {
|
||||
bmi_install_script = cm::make_unique<cmGeneratedFileStream>(
|
||||
@@ -523,6 +546,25 @@ bool cmDyndepCollation::WriteDyndepMetadata(
|
||||
#ifdef _WIN32
|
||||
cmSystemTools::ConvertToUnixSlashes(output_path);
|
||||
#endif
|
||||
|
||||
auto source_info_itr = export_info.ObjectToSource.find(output_path);
|
||||
|
||||
// Update the module compilation database `requires` field if needed.
|
||||
if (source_info_itr != export_info.ObjectToSource.end()) {
|
||||
auto const& sourcePath = source_info_itr->second.SourcePath;
|
||||
auto bdb_entry = build_database_lookup.find(sourcePath);
|
||||
if (bdb_entry != build_database_lookup.end()) {
|
||||
bdb_entry->second->Requires.clear();
|
||||
for (auto const& req : object.Requires) {
|
||||
bdb_entry->second->Requires.push_back(req.LogicalName);
|
||||
}
|
||||
} else if (export_info.DatabaseInfo) {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("Failed to find module database entry for ", sourcePath));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the fileset for this object.
|
||||
auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path);
|
||||
bool const has_provides = !object.Provides.empty();
|
||||
@@ -547,6 +589,31 @@ bool cmDyndepCollation::WriteDyndepMetadata(
|
||||
|
||||
auto const& file_set = fileset_info_itr->second;
|
||||
|
||||
// Update the module compilation database `provides` field if needed.
|
||||
{
|
||||
auto bdb_entry = build_database_lookup.find(file_set.SourcePath);
|
||||
if (bdb_entry != build_database_lookup.end()) {
|
||||
// Clear the provides mapping; we will re-initialize it here.
|
||||
if (!object.Provides.empty()) {
|
||||
bdb_entry->second->Provides.clear();
|
||||
}
|
||||
for (auto const& prov : object.Provides) {
|
||||
auto bmiName = cb.ModuleFile(prov.LogicalName);
|
||||
if (bmiName) {
|
||||
bdb_entry->second->Provides[prov.LogicalName] = *bmiName;
|
||||
} else {
|
||||
cmSystemTools::Error(
|
||||
cmStrCat("Failed to find BMI location for ", prov.LogicalName));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
} else if (export_info.DatabaseInfo) {
|
||||
cmSystemTools::Error(cmStrCat(
|
||||
"Failed to find module database entry for ", file_set.SourcePath));
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify the fileset type for the object.
|
||||
if (file_set.Type == "CXX_MODULES"_s) {
|
||||
if (!has_provides) {
|
||||
@@ -708,6 +775,16 @@ bool cmDyndepCollation::WriteDyndepMetadata(
|
||||
}
|
||||
}
|
||||
|
||||
if (module_database) {
|
||||
if (module_database->HasPlaceholderNames()) {
|
||||
cmSystemTools::Error(
|
||||
"Module compilation database still contains placeholders");
|
||||
result = false;
|
||||
} else {
|
||||
module_database->Write(export_info.DatabaseInfo->Output);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user