summaryrefslogtreecommitdiffstats
path: root/Source/cmNinjaTargetGenerator.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-01-07 13:26:21 (GMT)
committerKitware Robot <kwrobot@kitware.com>2021-01-07 13:26:28 (GMT)
commit05f4248e3d89bf9d779140cf60f511126756ab02 (patch)
tree89ecb61830144a8885b2d7e79841d3d6784a6e23 /Source/cmNinjaTargetGenerator.cxx
parent520df2880b7f172371de5a6adc6d6ada0e45ac8d (diff)
parent39cbbb59a52c63cd90eebaecea64fd42c3fad1d8 (diff)
downloadCMake-05f4248e3d89bf9d779140cf60f511126756ab02.zip
CMake-05f4248e3d89bf9d779140cf60f511126756ab02.tar.gz
CMake-05f4248e3d89bf9d779140cf60f511126756ab02.tar.bz2
Merge topic 'cpp-modules'
39cbbb59a5 ninja: add experimental infrastructure to generate gcc-format modmap files 791b4d26d6 ninja: add experimental infrastructure to generate modmap files with dyndep 4b23359117 ninja: Add experimental infrastructure for C++20 module dependency scanning f814d3b3c6 cmNinjaTargetGenerator: use $OBJ_FILE for the object b0fc2993e1 Treat the '.mpp' file extension as C++ code 988f997100 cmScanDepFormat: Fix name of our internal tool in parse errors dacd93a2db ninja: De-duplicate version numbers required for ninja features 533386ca29 cmStandardLevelResolver: Factor out helper to capture stoi exceptions Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Ben Boeckel <ben.boeckel@kitware.com> Acked-by: Robert Maynard <robert.maynard@kitware.com> Acked-by: Shannon Booth <shannon.ml.booth@gmail.com> Merge-request: !5562
Diffstat (limited to 'Source/cmNinjaTargetGenerator.cxx')
-rw-r--r--Source/cmNinjaTargetGenerator.cxx133
1 files changed, 108 insertions, 25 deletions
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index f1bd760..672b579 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -35,6 +35,7 @@
#include "cmRange.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
+#include "cmStandardLevelResolver.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -146,9 +147,26 @@ std::string cmNinjaTargetGenerator::LanguageDyndepRule(
'_', config);
}
-bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang) const
+bool cmNinjaTargetGenerator::NeedCxxModuleSupport(
+ std::string const& lang, std::string const& config) const
{
- return lang == "Fortran";
+ if (lang != "CXX") {
+ return false;
+ }
+ if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) {
+ return false;
+ }
+ cmGeneratorTarget const* tgt = this->GetGeneratorTarget();
+ cmStandardLevelResolver standardResolver(this->Makefile);
+ bool const uses_cxx20 =
+ standardResolver.HaveStandardAvailable(tgt, "CXX", config, "cxx_std_20");
+ return uses_cxx20 && this->GetGlobalGenerator()->CheckCxxModuleSupport();
+}
+
+bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang,
+ std::string const& config) const
+{
+ return lang == "Fortran" || this->NeedCxxModuleSupport(lang, config);
}
std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget(
@@ -530,8 +548,9 @@ cmNinjaRule GetScanRule(
scanVars.CMTargetName = vars.CMTargetName;
scanVars.CMTargetType = vars.CMTargetType;
scanVars.Language = vars.Language;
- scanVars.Object = "$out"; // for RULE_LAUNCH_COMPILE
+ scanVars.Object = "$OBJ_FILE";
scanVars.PreprocessedSource = "$out";
+ scanVars.DynDepFile = "$DYNDEP_INTERMEDIATE_FILE";
scanVars.DependencyFile = rule.DepFile.c_str();
scanVars.DependencyTarget = "$out";
@@ -586,7 +605,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
cmMakefile* mf = this->GetMakefile();
// For some cases we scan to dynamically discover dependencies.
- bool const needDyndep = this->NeedDyndep(lang);
+ bool const needDyndep = this->NeedDyndep(lang, config);
bool const compilationPreprocesses = !this->NeedExplicitPreprocessing(lang);
std::string flags = "$FLAGS";
@@ -601,6 +620,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
responseFlag = "@";
}
}
+ std::string const modmapFormatVar =
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_MODULE_MAP_FORMAT");
+ std::string const modmapFormat =
+ this->Makefile->GetSafeDefinition(modmapFormatVar);
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
@@ -624,16 +647,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
// Rule to scan dependencies of sources that need preprocessing.
{
std::vector<std::string> scanCommands;
- std::string const& scanRuleName =
- this->LanguagePreprocessAndScanRule(lang, config);
- std::string const& ppCommmand = mf->GetRequiredDefinition(
- cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"));
- cmExpandList(ppCommmand, scanCommands);
- for (std::string& i : scanCommands) {
- i = cmStrCat(launcher, i);
+ std::string scanRuleName;
+ if (compilationPreprocesses) {
+ scanRuleName = this->LanguageScanRule(lang, config);
+ std::string const& scanCommand = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_SCANDEP_SOURCE"));
+ cmExpandList(scanCommand, scanCommands);
+ for (std::string& i : scanCommands) {
+ i = cmStrCat(launcher, i);
+ }
+ } else {
+ scanRuleName = this->LanguagePreprocessAndScanRule(lang, config);
+ std::string const& ppCommmand = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"));
+ cmExpandList(ppCommmand, scanCommands);
+ for (std::string& i : scanCommands) {
+ i = cmStrCat(launcher, i);
+ }
+ scanCommands.emplace_back(GetScanCommand(cmakeCmd, tdi, lang, "$out",
+ "$DYNDEP_INTERMEDIATE_FILE"));
}
- scanCommands.emplace_back(GetScanCommand(cmakeCmd, tdi, lang, "$out",
- "$DYNDEP_INTERMEDIATE_FILE"));
auto scanRule = GetScanRule(
scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(),
@@ -641,12 +674,18 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
scanRule.Comment =
cmStrCat("Rule for generating ", lang, " dependencies.");
- scanRule.Description = cmStrCat("Building ", lang, " preprocessed $out");
+ if (compilationPreprocesses) {
+ scanRule.Description =
+ cmStrCat("Scanning $in for ", lang, " dependencies");
+ } else {
+ scanRule.Description =
+ cmStrCat("Building ", lang, " preprocessed $out");
+ }
this->GetGlobalGenerator()->AddRule(scanRule);
}
- {
+ if (!compilationPreprocesses) {
// Compilation will not preprocess, so it does not need the defines
// unless the compiler wants them for some other purpose.
if (!this->CompileWithDefines(lang)) {
@@ -681,12 +720,16 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
// Run CMake dependency scanner on the source file (using the preprocessed
// source if that was performed).
+ std::string ddModmapArg;
+ if (!modmapFormat.empty()) {
+ ddModmapArg += cmStrCat(" --modmapfmt=", modmapFormat);
+ }
{
std::vector<std::string> ddCmds;
{
- std::string ccmd =
- cmStrCat(cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi,
- " --lang=", lang, " --dd=$out @", rule.RspFile);
+ std::string ccmd = cmStrCat(
+ cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi, " --lang=", lang,
+ ddModmapArg, " --dd=$out @", rule.RspFile);
ddCmds.emplace_back(std::move(ccmd));
}
rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds);
@@ -748,6 +791,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
}
}
+ if (needDyndep && !modmapFormat.empty()) {
+ std::string modmapFlags = mf->GetRequiredDefinition(
+ cmStrCat("CMAKE_EXPERIMENTAL_", lang, "_MODULE_MAP_FLAG"));
+ cmSystemTools::ReplaceString(modmapFlags, "<MODULE_MAP_FILE>",
+ "$DYNDEP_MODULE_MAP_FILE");
+ flags += cmStrCat(' ', modmapFlags);
+ }
+
vars.Flags = flags.c_str();
vars.DependencyFile = rule.DepFile.c_str();
@@ -1053,6 +1104,7 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
const std::string& ppFileName,
bool compilePP, bool compilePPWithDefines,
cmNinjaBuild& objBuild, cmNinjaVars& vars,
+ std::string const& modmapFormat,
const std::string& objectFileName,
cmLocalGenerator* lg)
{
@@ -1123,6 +1175,15 @@ cmNinjaBuild GetScanBuildStatement(const std::string& ruleName,
vars.erase("DEP_FILE");
}
+ if (!modmapFormat.empty()) {
+ // XXX(modmap): If changing this path construction, change
+ // `cmGlobalNinjaGenerator::WriteDyndep` to expect the corresponding
+ // file path.
+ std::string const ddModmapFile = cmStrCat(objectFileName, ".modmap");
+ scanBuild.Variables["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
+ scanBuild.ImplicitOuts.push_back(ddModmapFile);
+ }
+
return scanBuild;
}
}
@@ -1262,10 +1323,17 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
}
// For some cases we scan to dynamically discover dependencies.
- bool const needDyndep = this->NeedDyndep(language);
+ bool const needDyndep = this->NeedDyndep(language, config);
bool const compilationPreprocesses =
!this->NeedExplicitPreprocessing(language);
+ std::string modmapFormat;
+ if (needDyndep) {
+ std::string const modmapFormatVar =
+ cmStrCat("CMAKE_EXPERIMENTAL_", language, "_MODULE_MAP_FORMAT");
+ modmapFormat = this->Makefile->GetSafeDefinition(modmapFormatVar);
+ }
+
if (needDyndep) {
// If source/target has preprocessing turned off, we still need to
// generate an explicit dependency step
@@ -1295,7 +1363,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmNinjaBuild ppBuild = GetScanBuildStatement(
scanRuleName, ppFileName, compilePP, compilePPWithDefines, objBuild,
- vars, objectFileName, this->LocalGenerator);
+ vars, modmapFormat, objectFileName, this->LocalGenerator);
if (compilePP) {
// In case compilation requires flags that are incompatible with
@@ -1331,6 +1399,12 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string const dyndep = this->GetDyndepFilePath(language, config);
objBuild.OrderOnlyDeps.push_back(dyndep);
vars["dyndep"] = dyndep;
+
+ if (!modmapFormat.empty()) {
+ std::string const ddModmapFile = cmStrCat(objectFileName, ".modmap");
+ vars["DYNDEP_MODULE_MAP_FILE"] = ddModmapFile;
+ objBuild.OrderOnlyDeps.push_back(ddModmapFile);
+ }
}
this->EnsureParentDirectoryExists(objectFileName);
@@ -1444,17 +1518,26 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
tdi["compiler-id"] = this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_COMPILER_ID"));
+ std::string mod_dir;
if (lang == "Fortran") {
- std::string mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
+ mod_dir = this->GeneratorTarget->GetFortranModuleDirectory(
this->Makefile->GetHomeOutputDirectory());
- if (mod_dir.empty()) {
- mod_dir = this->Makefile->GetCurrentBinaryDirectory();
- }
- tdi["module-dir"] = mod_dir;
+ } else if (lang == "CXX") {
+ mod_dir =
+ cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory);
+ }
+ if (mod_dir.empty()) {
+ mod_dir = this->Makefile->GetCurrentBinaryDirectory();
+ }
+ tdi["module-dir"] = mod_dir;
+
+ if (lang == "Fortran") {
tdi["submodule-sep"] =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
tdi["submodule-ext"] =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
+ } else if (lang == "CXX") {
+ // No extra information necessary.
}
tdi["dir-cur-bld"] = this->Makefile->GetCurrentBinaryDirectory();