|
|
@@ -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(
|
|
|
@@ -531,6 +549,7 @@ cmNinjaRule GetScanRule(
|
|
|
scanVars.Language = vars.Language;
|
|
|
scanVars.Object = "$OBJ_FILE";
|
|
|
scanVars.PreprocessedSource = "$out";
|
|
|
+ scanVars.DynDepFile = "$DYNDEP_INTERMEDIATE_FILE";
|
|
|
scanVars.DependencyFile = rule.DepFile.c_str();
|
|
|
scanVars.DependencyTarget = "$out";
|
|
|
|
|
|
@@ -585,7 +604,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";
|
|
|
@@ -623,16 +642,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(),
|
|
|
@@ -640,12 +669,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)) {
|
|
|
@@ -1258,7 +1293,7 @@ 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);
|
|
|
|
|
|
@@ -1440,17 +1475,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();
|