summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBen Boeckel <ben.boeckel@kitware.com>2023-02-01 15:40:19 (GMT)
committerBen Boeckel <ben.boeckel@kitware.com>2023-08-17 18:42:54 (GMT)
commit9b9ec70b5421e8cf91e000d8b6636d7b0b721d1a (patch)
treeaa5bea33938b0edb179ebdab0bcae0290ab3dcd2 /Source
parent80ef50a1919d62acb82a6423c40042a94edeac60 (diff)
downloadCMake-9b9ec70b5421e8cf91e000d8b6636d7b0b721d1a.zip
CMake-9b9ec70b5421e8cf91e000d8b6636d7b0b721d1a.tar.gz
CMake-9b9ec70b5421e8cf91e000d8b6636d7b0b721d1a.tar.bz2
Ninja: generate scanning and build rules for C++20 module synthetic targets
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx12
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx97
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h3
-rw-r--r--Source/cmNinjaTargetGenerator.cxx222
-rw-r--r--Source/cmNinjaTargetGenerator.h12
5 files changed, 322 insertions, 24 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 9ca1b2e..54c3737 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -2643,7 +2643,9 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
for (cmScanDepInfo const& object : objects) {
for (auto const& p : object.Provides) {
std::string mod;
- if (!p.CompiledModulePath.empty()) {
+ if (cmDyndepCollation::IsBmiOnly(export_info, object.PrimaryOutput)) {
+ mod = object.PrimaryOutput;
+ } else if (!p.CompiledModulePath.empty()) {
// The scanner provided the path to the module file.
mod = p.CompiledModulePath;
if (!cmSystemTools::FileIsFullPath(mod)) {
@@ -2714,8 +2716,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput);
build.ImplicitOuts.clear();
for (auto const& p : object.Provides) {
- build.ImplicitOuts.push_back(
- this->ConvertToNinjaPath(mod_files[p.LogicalName].BmiPath));
+ auto const implicitOut =
+ this->ConvertToNinjaPath(mod_files[p.LogicalName].BmiPath);
+ // Ignore the `provides` when the BMI is the output.
+ if (implicitOut != build.Outputs[0]) {
+ build.ImplicitOuts.emplace_back(implicitOut);
+ }
}
build.ImplicitDeps.clear();
for (auto const& r : object.Requires) {
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 089498b..48c30b6 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -62,12 +62,15 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator() = default;
void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
{
- std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
- if (this->TargetLinkLanguage(config).empty()) {
- cmSystemTools::Error(
- cmStrCat("CMake can not determine linker language for target: ",
- this->GetGeneratorTarget()->GetName()));
- return;
+ if (this->GetGeneratorTarget()->GetType() !=
+ cmStateEnums::INTERFACE_LIBRARY) {
+ std::string lang = this->GeneratorTarget->GetLinkerLanguage(config);
+ if (this->TargetLinkLanguage(config).empty()) {
+ cmSystemTools::Error(
+ cmStrCat("CMake can not determine linker language for target: ",
+ this->GetGeneratorTarget()->GetName()));
+ return;
+ }
}
// Write the rules for each language.
@@ -87,6 +90,34 @@ void cmNinjaNormalTargetGenerator::Generate(const std::string& config)
if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
this->WriteObjectLibStatement(config);
+ } else if (this->GetGeneratorTarget()->GetType() ==
+ cmStateEnums::INTERFACE_LIBRARY) {
+ bool haveCxxModuleSources = false;
+ if (this->GetGeneratorTarget()->HaveCxx20ModuleSources()) {
+ haveCxxModuleSources = true;
+ }
+
+ if (!haveCxxModuleSources) {
+ cmSystemTools::Error(cmStrCat(
+ "Ninja does not support INTERFACE libraries without C++ module "
+ "sources as a normal target: ",
+ this->GetGeneratorTarget()->GetName()));
+ return;
+ }
+
+ firstForConfig = true;
+ for (auto const& fileConfig : this->GetConfigNames()) {
+ if (!this->GetGlobalGenerator()
+ ->GetCrossConfigs(fileConfig)
+ .count(config)) {
+ continue;
+ }
+ if (haveCxxModuleSources) {
+ this->WriteCxxModuleLibraryStatement(config, fileConfig,
+ firstForConfig);
+ }
+ firstForConfig = false;
+ }
} else {
firstForConfig = true;
for (auto const& fileConfig : this->GetConfigNames()) {
@@ -123,12 +154,26 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules(
#endif
// Write rules for languages compiled in this target.
- std::set<std::string> languages;
- std::vector<cmSourceFile const*> sourceFiles;
- this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
- if (this->HaveRequiredLanguages(sourceFiles, languages)) {
- for (std::string const& language : languages) {
- this->WriteLanguageRules(language, config);
+ {
+ std::set<std::string> languages;
+ std::vector<cmSourceFile const*> sourceFiles;
+ this->GetGeneratorTarget()->GetObjectSources(sourceFiles, config);
+ if (this->HaveRequiredLanguages(sourceFiles, languages)) {
+ for (std::string const& language : languages) {
+ this->WriteLanguageRules(language, config);
+ }
+ }
+ }
+
+ // Write rules for languages in BMI-only rules.
+ {
+ std::set<std::string> languages;
+ std::vector<cmSourceFile const*> sourceFiles;
+ this->GetGeneratorTarget()->GetCxxModuleSources(sourceFiles, config);
+ if (this->HaveRequiredLanguages(sourceFiles, languages)) {
+ for (std::string const& language : languages) {
+ this->WriteLanguageRules(language, config);
+ }
}
}
}
@@ -1637,6 +1682,34 @@ void cmNinjaNormalTargetGenerator::WriteObjectLibStatement(
this->GetTargetName(), this->GetGeneratorTarget(), config);
}
+void cmNinjaNormalTargetGenerator::WriteCxxModuleLibraryStatement(
+ const std::string& config, const std::string& /*fileConfig*/,
+ bool firstForConfig)
+{
+ // TODO: How to use `fileConfig` properly?
+
+ // Write a phony output that depends on the scanning output.
+ {
+ cmNinjaBuild build("phony");
+ build.Comment =
+ cmStrCat("Imported C++ module library ", this->GetTargetName());
+ this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
+ build.Outputs, config);
+ if (firstForConfig) {
+ this->GetLocalGenerator()->AppendTargetOutputs(
+ this->GetGeneratorTarget(),
+ this->GetGlobalGenerator()->GetByproductsForCleanTarget(config),
+ config);
+ }
+ build.ExplicitDeps.emplace_back(this->GetDyndepFilePath("CXX", config));
+ this->GetGlobalGenerator()->WriteBuild(this->GetCommonFileStream(), build);
+ }
+
+ // Add aliases for the target name.
+ this->GetGlobalGenerator()->AddTargetAlias(
+ this->GetTargetName(), this->GetGeneratorTarget(), config);
+}
+
cmGeneratorTarget::Names cmNinjaNormalTargetGenerator::TargetNames(
const std::string& config) const
{
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 187ea46..3ef0230 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -49,6 +49,9 @@ private:
const std::string& output);
void WriteObjectLibStatement(const std::string& config);
+ void WriteCxxModuleLibraryStatement(const std::string& config,
+ const std::string& fileConfig,
+ bool firstForConfig);
std::vector<std::string> ComputeLinkCmd(const std::string& config);
std::vector<std::string> ComputeDeviceLinkCmd();
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 6792cd7..09f8495 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -28,6 +28,7 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
+#include "cmGlobalCommonGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmList.h"
#include "cmLocalGenerator.h"
@@ -59,8 +60,13 @@ std::unique_ptr<cmNinjaTargetGenerator> cmNinjaTargetGenerator::New(
case cmStateEnums::OBJECT_LIBRARY:
return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
- case cmStateEnums::UTILITY:
case cmStateEnums::INTERFACE_LIBRARY:
+ if (target->HaveCxx20ModuleSources()) {
+ return cm::make_unique<cmNinjaNormalTargetGenerator>(target);
+ }
+ CM_FALLTHROUGH;
+
+ case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
return cm::make_unique<cmNinjaUtilityTargetGenerator>(target);
@@ -167,7 +173,7 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget(
// Refactor it.
std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
cmSourceFile const* source, const std::string& language,
- const std::string& config)
+ const std::string& config, const std::string& objectFileName)
{
std::unordered_map<std::string, std::string> pchSources;
std::vector<std::string> architectures =
@@ -247,6 +253,18 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
"\nin a file set of type \"", fs->GetType(),
R"(" but the source is not classified as a "CXX" source.)"));
}
+
+ if (!this->GeneratorTarget->Target->IsNormal()) {
+ auto flag = this->GetMakefile()->GetSafeDefinition(
+ "CMAKE_EXPERIMENTAL_CXX_MODULE_BMI_ONLY_FLAG");
+ cmRulePlaceholderExpander::RuleVariables compileObjectVars;
+ compileObjectVars.Object = objectFileName.c_str();
+ auto rulePlaceholderExpander =
+ this->GetLocalGenerator()->CreateRulePlaceholderExpander();
+ rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
+ flag, compileObjectVars);
+ this->LocalGenerator->AppendCompileOptions(flags, flag);
+ }
}
return flags;
@@ -394,6 +412,31 @@ std::string cmNinjaTargetGenerator::GetObjectFilePath(
return path;
}
+std::string cmNinjaTargetGenerator::GetBmiFilePath(
+ cmSourceFile const* source, const std::string& config) const
+{
+ std::string path = this->LocalGenerator->GetHomeRelativeOutputPath();
+ if (!path.empty()) {
+ path += '/';
+ }
+
+ auto& importedConfigInfo = this->Configs.at(config).ImportedCxxModules;
+ if (!importedConfigInfo.Initialized()) {
+ std::string configUpper = cmSystemTools::UpperCase(config);
+ std::string propName = cmStrCat("IMPORTED_CXX_MODULES_", configUpper);
+ auto value = this->GeneratorTarget->GetSafeProperty(propName);
+ importedConfigInfo.Initialize(value);
+ }
+
+ std::string bmiName =
+ importedConfigInfo.BmiNameForSource(source->GetFullPath());
+
+ path += cmStrCat(
+ this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+ this->GetGlobalGenerator()->ConfigDirectory(config), '/', bmiName);
+ return path;
+}
+
std::string cmNinjaTargetGenerator::GetClangTidyReplacementsFilePath(
std::string const& directory, cmSourceFile const& source,
std::string const& config) const
@@ -1027,6 +1070,16 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
}
}
+ {
+ std::vector<cmSourceFile const*> bmiOnlySources;
+ this->GeneratorTarget->GetCxxModuleSources(bmiOnlySources, config);
+
+ for (cmSourceFile const* sf : bmiOnlySources) {
+ this->WriteCxxModuleBmiBuildStatement(sf, config, fileConfig,
+ firstForConfig);
+ }
+ }
+
for (auto const& langScanningFiles : this->Configs[config].ScanningInfo) {
std::string const& language = langScanningFiles.first;
std::vector<ScanningFiles> const& scanningFiles = langScanningFiles.second;
@@ -1149,22 +1202,22 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
scanBuild.Variables["OBJ_FILE"] = objectFileName;
// Tell dependency scanner where to store dyndep intermediate results.
- std::string const& ddiFile = cmStrCat(objectFileName, ".ddi");
- scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
+ std::string ddiFileName = cmStrCat(objectFileName, ".ddi");
+ scanBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFileName;
// Outputs of the scan/preprocessor build statement.
if (compilePP) {
scanBuild.Outputs.push_back(ppFileName);
- scanBuild.ImplicitOuts.push_back(ddiFile);
+ scanBuild.ImplicitOuts.push_back(ddiFileName);
} else {
- scanBuild.Outputs.push_back(ddiFile);
+ scanBuild.Outputs.push_back(ddiFileName);
scanBuild.Variables["PREPROCESSED_OUTPUT_FILE"] = ppFileName;
if (!compilationPreprocesses) {
// Compilation does not preprocess and we are not compiling an
// already-preprocessed source. Make compilation depend on the scan
// results to honor implicit dependencies discovered during scanning
// (such as Fortran INCLUDE directives).
- objBuild.ImplicitDeps.emplace_back(ddiFile);
+ objBuild.ImplicitDeps.emplace_back(ddiFileName);
}
}
@@ -1214,7 +1267,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmNinjaBuild objBuild(this->LanguageCompilerRule(
language, config, needDyndep ? WithScanning::Yes : WithScanning::No));
cmNinjaVars& vars = objBuild.Variables;
- vars["FLAGS"] = this->ComputeFlagsForObject(source, language, config);
+ vars["FLAGS"] =
+ this->ComputeFlagsForObject(source, language, config, objectFileName);
vars["DEFINES"] = this->ComputeDefines(source, language, config);
vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
@@ -1545,6 +1599,155 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
}
+void cmNinjaTargetGenerator::WriteCxxModuleBmiBuildStatement(
+ cmSourceFile const* source, const std::string& config,
+ const std::string& fileConfig, bool firstForConfig)
+{
+ std::string const language = source->GetLanguage();
+ if (language != "CXX"_s) {
+ this->GetMakefile()->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("Source file '", source->GetFullPath(), "' of target '",
+ this->GetTargetName(), "' is a '", language,
+ "' source but must be 'CXX' in order to have a BMI build "
+ "statement generated."));
+ return;
+ }
+
+ std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(source);
+ std::string const bmiDir = this->ConvertToNinjaPath(
+ cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
+ this->GetGlobalGenerator()->ConfigDirectory(config)));
+ std::string const bmiFileName =
+ this->ConvertToNinjaPath(this->GetBmiFilePath(source, config));
+ std::string const bmiFileDir = cmSystemTools::GetFilenamePath(bmiFileName);
+
+ int const commandLineLengthLimit = this->ForceResponseFile() ? -1 : 0;
+
+ cmNinjaBuild bmiBuild(
+ this->LanguageCompilerRule(language, config, WithScanning::Yes));
+ cmNinjaVars& vars = bmiBuild.Variables;
+ vars["FLAGS"] =
+ this->ComputeFlagsForObject(source, language, config, bmiFileName);
+ vars["DEFINES"] = this->ComputeDefines(source, language, config);
+ vars["INCLUDES"] = this->ComputeIncludes(source, language, config);
+
+ if (this->GetMakefile()->GetSafeDefinition(
+ cmStrCat("CMAKE_", language, "_DEPFILE_FORMAT")) != "msvc"_s) {
+ bool replaceExt(false);
+ if (!language.empty()) {
+ std::string repVar =
+ cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE");
+ replaceExt = this->Makefile->IsOn(repVar);
+ }
+ if (!replaceExt) {
+ // use original code
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmStrCat(bmiFileName, ".d"), cmOutputConverter::SHELL);
+ } else {
+ // Replace the original source file extension with the
+ // depend file extension.
+ std::string dependFileName = cmStrCat(
+ cmSystemTools::GetFilenameWithoutLastExtension(bmiFileName), ".d");
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ cmStrCat(bmiFileDir, '/', dependFileName), cmOutputConverter::SHELL);
+ }
+ }
+
+ std::string d =
+ this->GeneratorTarget->GetClangTidyExportFixesDirectory(language);
+ if (!d.empty()) {
+ this->GlobalCommonGenerator->AddClangTidyExportFixesDir(d);
+ std::string fixesFile =
+ this->GetClangTidyReplacementsFilePath(d, *source, config);
+ this->GlobalCommonGenerator->AddClangTidyExportFixesFile(fixesFile);
+ cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(fixesFile));
+ fixesFile = this->ConvertToNinjaPath(fixesFile);
+ vars["CLANG_TIDY_EXPORT_FIXES"] = fixesFile;
+ }
+
+ if (firstForConfig) {
+ this->ExportObjectCompileCommand(
+ language, sourceFilePath, bmiDir, bmiFileName, bmiFileDir, vars["FLAGS"],
+ vars["DEFINES"], vars["INCLUDES"], config);
+ }
+
+ bmiBuild.Outputs.push_back(bmiFileName);
+ bmiBuild.ExplicitDeps.push_back(sourceFilePath);
+
+ std::vector<std::string> depList;
+
+ std::vector<std::string> architectures =
+ this->GeneratorTarget->GetAppleArchs(config, language);
+ if (architectures.empty()) {
+ architectures.emplace_back();
+ }
+
+ bmiBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config));
+
+ // For some cases we scan to dynamically discover dependencies.
+ std::string modmapFormat;
+ if (true) {
+ std::string const modmapFormatVar =
+ cmStrCat("CMAKE_EXPERIMENTAL_", language, "_MODULE_MAP_FORMAT");
+ modmapFormat = this->Makefile->GetSafeDefinition(modmapFormatVar);
+ }
+
+ {
+ bool const compilePPWithDefines = this->CompileWithDefines(language);
+
+ std::string scanRuleName = this->LanguageScanRule(language, config);
+ std::string ppFileName = cmStrCat(bmiFileName, ".ddi.i");
+
+ cmNinjaBuild ppBuild = GetScanBuildStatement(
+ scanRuleName, ppFileName, false, compilePPWithDefines, true, bmiBuild,
+ vars, bmiFileName, this->LocalGenerator);
+
+ ScanningFiles scanningFiles;
+
+ if (firstForConfig) {
+ scanningFiles.ScanningOutput = cmStrCat(bmiFileName, ".ddi");
+ }
+
+ this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
+ ppBuild.Variables);
+
+ this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
+ ppBuild, commandLineLengthLimit);
+
+ std::string const dyndep = this->GetDyndepFilePath(language, config);
+ bmiBuild.OrderOnlyDeps.push_back(dyndep);
+ vars["dyndep"] = dyndep;
+
+ if (!modmapFormat.empty()) {
+ std::string ddModmapFile = cmStrCat(bmiFileName, ".modmap");
+ vars["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
+ scanningFiles.ModuleMapFile = std::move(ddModmapFile);
+ }
+
+ if (!scanningFiles.IsEmpty()) {
+ this->Configs[config].ScanningInfo[language].emplace_back(scanningFiles);
+ }
+ }
+
+ this->EnsureParentDirectoryExists(bmiFileName);
+
+ vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ bmiDir, cmOutputConverter::SHELL);
+ vars["OBJECT_FILE_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ bmiFileDir, cmOutputConverter::SHELL);
+
+ this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
+ vars);
+
+ this->SetMsvcTargetPdbVariable(vars, config);
+
+ bmiBuild.RspFile = cmStrCat(bmiFileName, ".rsp");
+
+ this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
+ bmiBuild, commandLineLengthLimit);
+}
+
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
const std::string& config)
{
@@ -1605,6 +1808,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
cb.ObjectFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
return this->GetObjectFilePath(sf, cnf);
};
+ cb.BmiFilePath = [this](cmSourceFile const* sf, std::string const& cnf) {
+ return this->GetBmiFilePath(sf, cnf);
+ };
#if !defined(CMAKE_BOOTSTRAP)
cmDyndepCollation::AddCollationInformation(tdi, this->GeneratorTarget,
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 8c38499..49e7018 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -15,6 +15,7 @@
#include "cmCommonTargetGenerator.h"
#include "cmGlobalNinjaGenerator.h"
+#include "cmImportedCxxModuleInfo.h"
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
@@ -91,7 +92,8 @@ protected:
*/
std::string ComputeFlagsForObject(cmSourceFile const* source,
const std::string& language,
- const std::string& config);
+ const std::string& config,
+ const std::string& objectFileName);
void AddIncludeFlags(std::string& flags, std::string const& lang,
const std::string& config) override;
@@ -129,6 +131,8 @@ protected:
/// @return the object file path for the given @a source.
std::string GetObjectFilePath(cmSourceFile const* source,
const std::string& config) const;
+ std::string GetBmiFilePath(cmSourceFile const* source,
+ const std::string& config) const;
/// @return the preprocessed source file path for the given @a source.
std::string GetPreprocessedFilePath(cmSourceFile const* source,
@@ -163,6 +167,10 @@ protected:
void WriteObjectBuildStatements(const std::string& config,
const std::string& fileConfig,
bool firstForConfig);
+ void WriteCxxModuleBmiBuildStatement(cmSourceFile const* source,
+ const std::string& config,
+ const std::string& fileConfig,
+ bool firstForConfig);
void WriteObjectBuildStatement(cmSourceFile const* source,
const std::string& config,
const std::string& fileConfig,
@@ -239,6 +247,8 @@ private:
cmNinjaDeps Objects;
// Dyndep Support
std::map<std::string, std::vector<ScanningFiles>> ScanningInfo;
+ // Imported C++ module info.
+ mutable ImportedCxxModuleLookup ImportedCxxModules;
// Swift Support
Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;