summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalNinjaGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalNinjaGenerator.cxx')
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx431
1 files changed, 276 insertions, 155 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 02ffaf7..4f17408 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -34,6 +34,7 @@
#include "cmOutputConverter.h"
#include "cmProperty.h"
#include "cmRange.h"
+#include "cmScanDepFormat.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
@@ -55,6 +56,52 @@ std::string const cmGlobalNinjaGenerator::SHELL_NOOP = "cd .";
std::string const cmGlobalNinjaGenerator::SHELL_NOOP = ":";
#endif
+bool operator==(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return lhs.Target == rhs.Target && lhs.Config == rhs.Config &&
+ lhs.GenexOutput == rhs.GenexOutput;
+}
+
+bool operator!=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool operator<(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return lhs.Target < rhs.Target ||
+ (lhs.Target == rhs.Target &&
+ (lhs.Config < rhs.Config ||
+ (lhs.Config == rhs.Config && lhs.GenexOutput < rhs.GenexOutput)));
+}
+
+bool operator>(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return rhs < lhs;
+}
+
+bool operator<=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return !(lhs > rhs);
+}
+
+bool operator>=(
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& lhs,
+ const cmGlobalNinjaGenerator::ByConfig::TargetDependsClosureKey& rhs)
+{
+ return rhs <= lhs;
+}
+
void cmGlobalNinjaGenerator::Indent(std::ostream& os, int count)
{
for (int i = 0; i < count; ++i) {
@@ -135,7 +182,7 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string& path)
else
std::replace(result.begin(), result.end(), '/', '\\');
#endif
- result = EncodeLiteral(result);
+ result = this->EncodeLiteral(result);
cmSystemTools::ReplaceString(result, " ", "$ ");
cmSystemTools::ReplaceString(result, ":", "$:");
return result;
@@ -167,7 +214,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
{
// Write explicit outputs
for (std::string const& output : build.Outputs) {
- buildStr += cmStrCat(' ', EncodePath(output));
+ buildStr += cmStrCat(' ', this->EncodePath(output));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
@@ -176,7 +223,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
if (!build.ImplicitOuts.empty()) {
buildStr += " |";
for (std::string const& implicitOut : build.ImplicitOuts) {
- buildStr += cmStrCat(' ', EncodePath(implicitOut));
+ buildStr += cmStrCat(' ', this->EncodePath(implicitOut));
}
}
buildStr += ':';
@@ -191,14 +238,14 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
// Write explicit dependencies.
for (std::string const& explicitDep : build.ExplicitDeps) {
- arguments += cmStrCat(' ', EncodePath(explicitDep));
+ arguments += cmStrCat(' ', this->EncodePath(explicitDep));
}
// Write implicit dependencies.
if (!build.ImplicitDeps.empty()) {
arguments += " |";
for (std::string const& implicitDep : build.ImplicitDeps) {
- arguments += cmStrCat(' ', EncodePath(implicitDep));
+ arguments += cmStrCat(' ', this->EncodePath(implicitDep));
}
}
@@ -206,7 +253,7 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
if (!build.OrderOnlyDeps.empty()) {
arguments += " ||";
for (std::string const& orderOnlyDep : build.OrderOnlyDeps) {
- arguments += cmStrCat(' ', EncodePath(orderOnlyDep));
+ arguments += cmStrCat(' ', this->EncodePath(orderOnlyDep));
}
}
@@ -284,11 +331,11 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
#endif
vars["COMMAND"] = std::move(cmd);
}
- vars["DESC"] = EncodeLiteral(description);
+ vars["DESC"] = this->EncodeLiteral(description);
if (restat) {
vars["restat"] = "1";
}
- if (uses_terminal && SupportsConsolePool()) {
+ if (uses_terminal && this->SupportsConsolePool()) {
vars["pool"] = "console";
} else if (!job_pool.empty()) {
vars["pool"] = job_pool;
@@ -315,7 +362,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
void cmGlobalNinjaGenerator::AddMacOSXContentRule()
{
cmNinjaRule rule("COPY_OSX_CONTENT");
- rule.Command = cmStrCat(CMakeCmd(), " -E copy $in $out");
+ rule.Command = cmStrCat(this->CMakeCmd(), " -E copy $in $out");
rule.Description = "Copying OS X Content $out";
rule.Comment = "Rule for copying OS X bundle content file.";
this->AddRule(rule);
@@ -508,6 +555,7 @@ void cmGlobalNinjaGenerator::Generate()
this->TargetAll = this->NinjaOutputPath("all");
this->CMakeCacheFile = this->NinjaOutputPath("CMakeCache.txt");
this->DisableCleandead = false;
+ this->DiagnosedCxxModuleSupport = false;
this->PolicyCMP0058 =
this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
@@ -708,6 +756,37 @@ bool cmGlobalNinjaGenerator::CheckLanguages(
return true;
}
+bool cmGlobalNinjaGenerator::CheckCxxModuleSupport()
+{
+ bool const diagnose = !this->DiagnosedCxxModuleSupport &&
+ !this->CMakeInstance->GetIsInTryCompile();
+ if (diagnose) {
+ this->DiagnosedCxxModuleSupport = true;
+ this->GetCMakeInstance()->IssueMessage(
+ MessageType::AUTHOR_WARNING,
+ "C++20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP "
+ "is experimental. It is meant only for compiler developers to try.");
+ }
+ if (this->NinjaSupportsDyndeps) {
+ return true;
+ }
+ if (diagnose) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "The Ninja generator does not support C++20 modules "
+ "using Ninja version \n"
+ " " << this->NinjaVersion << "\n"
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForDyndeps() << " or higher is required."
+ ;
+ /* clang-format on */
+ this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e.str());
+ cmSystemTools::SetFatalErrorOccured();
+ }
+ return false;
+}
+
bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
{
if (this->NinjaSupportsDyndeps) {
@@ -719,7 +798,8 @@ bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const
e <<
"The Ninja generator does not support Fortran using Ninja version\n"
" " << this->NinjaVersion << "\n"
- "due to lack of required features. Ninja 1.10 or higher is required."
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForDyndeps() << " or higher is required."
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
@@ -738,7 +818,9 @@ bool cmGlobalNinjaGenerator::CheckISPC(cmMakefile* mf) const
e <<
"The Ninja generator does not support ISPC using Ninja version\n"
" " << this->NinjaVersion << "\n"
- "due to lack of required features. Ninja 1.10 or higher is required."
+ "due to lack of required features. "
+ "Ninja " << RequiredNinjaVersionForMultipleOutputs() <<
+ " or higher is required."
;
/* clang-format on */
mf->IssueMessage(MessageType::FATAL_ERROR, e.str());
@@ -985,8 +1067,8 @@ static void EnsureTrailingSlash(std::string& path)
std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
const std::string& path) const
{
- auto const f = ConvertToNinjaPathCache.find(path);
- if (f != ConvertToNinjaPathCache.end()) {
+ auto const f = this->ConvertToNinjaPathCache.find(path);
+ if (f != this->ConvertToNinjaPathCache.end()) {
return f->second;
}
@@ -998,7 +1080,7 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
#ifdef _WIN32
std::replace(convPath.begin(), convPath.end(), '/', '\\');
#endif
- return ConvertToNinjaPathCache.emplace(path, std::move(convPath))
+ return this->ConvertToNinjaPathCache.emplace(path, std::move(convPath))
.first->second;
}
@@ -1056,7 +1138,7 @@ void cmGlobalNinjaGenerator::CloseCompileCommandsStream()
}
}
-void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os)
+void cmGlobalNinjaGenerator::WriteDisclaimer(std::ostream& os) const
{
os << "# CMAKE generated file: DO NOT EDIT!\n"
<< "# Generated by \"" << this->GetName() << "\""
@@ -1070,12 +1152,13 @@ void cmGlobalNinjaGenerator::WriteAssumedSourceDependencies()
cmNinjaDeps orderOnlyDeps;
std::copy(asd.second.begin(), asd.second.end(),
std::back_inserter(orderOnlyDeps));
- WriteCustomCommandBuild(/*command=*/"", /*description=*/"",
- "Assume dependencies for generated source file.",
- /*depfile*/ "", /*job_pool*/ "",
- /*uses_terminal*/ false,
- /*restat*/ true, cmNinjaDeps(1, asd.first), "",
- cmNinjaDeps(), orderOnlyDeps);
+ this->WriteCustomCommandBuild(
+ /*command=*/"", /*description=*/"",
+ "Assume dependencies for generated source file.",
+ /*depfile*/ "", /*job_pool*/ "",
+ /*uses_terminal*/ false,
+ /*restat*/ true, cmNinjaDeps(1, asd.first), "", cmNinjaDeps(),
+ orderOnlyDeps);
}
}
@@ -1087,7 +1170,7 @@ std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget(
void cmGlobalNinjaGenerator::AppendTargetOutputs(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config, cmNinjaTargetDepends depends)
+ const std::string& config, cmNinjaTargetDepends depends) const
{
// for frameworks, we want the real name, not smple name
// frameworks always appear versioned, and the build.ninja
@@ -1100,7 +1183,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
case cmStateEnums::STATIC_LIBRARY:
case cmStateEnums::MODULE_LIBRARY: {
if (depends == DependOnTargetOrdering) {
- outputs.push_back(OrderDependsTargetForTarget(target, config));
+ outputs.push_back(this->OrderDependsTargetForTarget(target, config));
break;
}
}
@@ -1112,7 +1195,7 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
}
case cmStateEnums::OBJECT_LIBRARY: {
if (depends == DependOnTargetOrdering) {
- outputs.push_back(OrderDependsTargetForTarget(target, config));
+ outputs.push_back(this->OrderDependsTargetForTarget(target, config));
break;
}
}
@@ -1193,23 +1276,30 @@ void cmGlobalNinjaGenerator::AppendTargetDepends(
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaDeps& outputs,
- const std::string& config)
+ const std::string& config, const std::string& fileConfig, bool genexOutput)
{
cmNinjaOuts outs;
- this->AppendTargetDependsClosure(target, outs, config, true);
+ this->AppendTargetDependsClosure(target, outs, config, fileConfig,
+ genexOutput, true);
cm::append(outputs, outs);
}
void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmGeneratorTarget const* target, cmNinjaOuts& outputs,
- const std::string& config, bool omit_self)
+ const std::string& config, const std::string& fileConfig, bool genexOutput,
+ bool omit_self)
{
// try to locate the target in the cache
- auto find = this->Configs[config].TargetDependsClosures.lower_bound(target);
+ ByConfig::TargetDependsClosureKey key{
+ target,
+ config,
+ genexOutput,
+ };
+ auto find = this->Configs[fileConfig].TargetDependsClosures.lower_bound(key);
- if (find == this->Configs[config].TargetDependsClosures.end() ||
- find->first != target) {
+ if (find == this->Configs[fileConfig].TargetDependsClosures.end() ||
+ find->first != key) {
// We now calculate the closure outputs by inspecting the dependent
// targets recursively.
// For that we have to distinguish between a local result set that is only
@@ -1219,18 +1309,27 @@ void cmGlobalNinjaGenerator::AppendTargetDependsClosure(
cmNinjaOuts this_outs; // this will be the new cache entry
for (auto const& dep_target : this->GetTargetDirectDepends(target)) {
- if (!dep_target->IsInBuildSystem() ||
- (target->GetType() != cmStateEnums::UTILITY &&
- dep_target->GetType() != cmStateEnums::UTILITY &&
- this->EnableCrossConfigBuild() && !dep_target.IsCross())) {
+ if (!dep_target->IsInBuildSystem()) {
continue;
}
- // Collect the dependent targets for _this_ target
- this->AppendTargetDependsClosure(dep_target, this_outs, config, false);
+ if (!this->IsSingleConfigUtility(target) &&
+ !this->IsSingleConfigUtility(dep_target) &&
+ this->EnableCrossConfigBuild() && !dep_target.IsCross() &&
+ !genexOutput) {
+ continue;
+ }
+
+ if (dep_target.IsCross()) {
+ this->AppendTargetDependsClosure(dep_target, this_outs, fileConfig,
+ fileConfig, genexOutput, false);
+ } else {
+ this->AppendTargetDependsClosure(dep_target, this_outs, config,
+ fileConfig, genexOutput, false);
+ }
}
- find = this->Configs[config].TargetDependsClosures.emplace_hint(
- find, target, std::move(this_outs));
+ find = this->Configs[fileConfig].TargetDependsClosures.emplace_hint(
+ find, key, std::move(this_outs));
}
// now fill the outputs of the final result from the newly generated cache
@@ -1413,7 +1512,7 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
build.Outputs.front() = this->BuildAlias(buildDirAllTarget, config);
configDeps.emplace_back(build.Outputs.front());
for (DirectoryTarget::Target const& t : dt.Targets) {
- if (!IsExcludedFromAllInConfig(t, config)) {
+ if (!this->IsExcludedFromAllInConfig(t, config)) {
this->AppendTargetOutputs(t.GT, build.ExplicitDeps, config,
DependOnTargetArtifact);
}
@@ -1626,7 +1725,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
cmNinjaRule rule("RERUN_CMAKE");
rule.Command =
- cmStrCat(CMakeCmd(), " --regenerate-during-build -S",
+ cmStrCat(this->CMakeCmd(), " --regenerate-during-build -S",
lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
cmOutputConverter::SHELL),
" -B",
@@ -1651,7 +1750,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
// Use 'console' pool to get non buffered output of the CMake re-run call
// Available since Ninja 1.5
- if (SupportsConsolePool()) {
+ if (this->SupportsConsolePool()) {
reBuild.Variables["pool"] = "console";
}
@@ -1660,7 +1759,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
{
cmNinjaRule rule("VERIFY_GLOBS");
rule.Command =
- cmStrCat(CMakeCmd(), " -P ",
+ cmStrCat(this->CMakeCmd(), " -P ",
lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
cmOutputConverter::SHELL));
rule.Description = "Re-checking globbed directories...";
@@ -1721,8 +1820,8 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
build.Comment = "A missing CMake input file is not an error.";
std::set_difference(std::make_move_iterator(reBuild.ImplicitDeps.begin()),
std::make_move_iterator(reBuild.ImplicitDeps.end()),
- CustomCommandOutputs.begin(),
- CustomCommandOutputs.end(),
+ this->CustomCommandOutputs.begin(),
+ this->CustomCommandOutputs.end(),
std::back_inserter(build.Outputs));
this->WriteBuild(os, build);
}
@@ -1806,7 +1905,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
fout << " file(REMOVE_RECURSE\n";
for (std::string const& acf : it->second.AdditionalCleanFiles) {
fout << " "
- << cmOutputConverter::EscapeForCMake(ConvertToNinjaPath(acf))
+ << cmOutputConverter::EscapeForCMake(
+ this->ConvertToNinjaPath(acf))
<< '\n';
}
fout << " )\n";
@@ -1821,7 +1921,7 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
{
cmNinjaRule rule("CLEAN_ADDITIONAL");
rule.Command = cmStrCat(
- CMakeCmd(), " -DCONFIG=$CONFIG -P ",
+ this->CMakeCmd(), " -DCONFIG=$CONFIG -P ",
lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
cmOutputConverter::SHELL));
rule.Description = "Cleaning additional files...";
@@ -1838,13 +1938,13 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
build.Outputs.front() = this->BuildAlias(
this->NinjaOutputPath(this->GetAdditionalCleanTargetName()), config);
build.Variables["CONFIG"] = config;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
if (this->IsMultiConfig()) {
build.Outputs.front() =
this->NinjaOutputPath(this->GetAdditionalCleanTargetName());
build.Variables["CONFIG"] = "";
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
// Return success
@@ -1854,13 +1954,13 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
{
// -- Additional clean target
- bool additionalFiles = WriteTargetCleanAdditional(os);
+ bool additionalFiles = this->WriteTargetCleanAdditional(os);
// -- Default clean target
// Write rule
{
cmNinjaRule rule("CLEAN");
- rule.Command = cmStrCat(NinjaCmd(), " $FILE_ARG -t clean $TARGETS");
+ rule.Command = cmStrCat(this->NinjaCmd(), " $FILE_ARG -t clean $TARGETS");
rule.Description = "Cleaning all built files...";
rule.Comment = "Rule for cleaning all built files.";
WriteRule(*this->RulesFileStream, rule);
@@ -1961,13 +2061,13 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
build.Outputs.emplace_back(
this->ConvertToNinjaPath(GetByproductsForCleanTargetName()));
build.ExplicitDeps = this->ByproductsForCleanTarget;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
for (auto const& config : configs) {
build.Outputs.front() = this->BuildAlias(
this->ConvertToNinjaPath(GetByproductsForCleanTargetName()), config);
build.ExplicitDeps = this->Configs[config].ByproductsForCleanTarget;
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
}
@@ -1976,7 +2076,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
{
{
cmNinjaRule rule("HELP");
- rule.Command = cmStrCat(NinjaCmd(), " -t targets");
+ rule.Command = cmStrCat(this->NinjaCmd(), " -t targets");
rule.Description = "All primary targets available:";
rule.Comment = "Rule for printing all primary targets available.";
WriteRule(*this->RulesFileStream, rule);
@@ -1985,7 +2085,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os)
cmNinjaBuild build("HELP");
build.Comment = "Print all primary targets available.";
build.Outputs.push_back(this->NinjaOutputPath("help"));
- WriteBuild(os, build);
+ this->WriteBuild(os, build);
}
}
@@ -2016,6 +2116,8 @@ void cmGlobalNinjaGenerator::StripNinjaOutputPathPrefixAsSuffix(
cmStripSuffixIfExists(path, this->OutputPathPrefix);
}
+#if !defined(CMAKE_BOOTSTRAP)
+
/*
We use the following approach to support Fortran. Each target already
@@ -2095,16 +2197,6 @@ Compilation of source files within a target is split into the following steps:
(because the latter consumes the module).
*/
-struct cmSourceInfo
-{
- // Set of provided and required modules.
- std::set<std::string> Provides;
- std::set<std::string> Requires;
-
- // Set of files included in the translation unit.
- std::set<std::string> Includes;
-};
-
static std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
std::string const& arg_tdi, std::string const& arg_pp);
@@ -2112,6 +2204,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
std::string arg_tdi;
+ std::string arg_src;
std::string arg_pp;
std::string arg_dep;
std::string arg_obj;
@@ -2120,6 +2213,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
arg_tdi = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--src=")) {
+ arg_src = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--pp=")) {
arg_pp = arg.substr(5);
} else if (cmHasLiteralPrefix(arg, "--dep=")) {
@@ -2160,6 +2255,9 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang=");
return 1;
}
+ if (arg_src.empty()) {
+ arg_src = cmStrCat("<", arg_obj, " input file>");
+ }
std::unique_ptr<cmSourceInfo> info;
if (arg_lang == "Fortran") {
@@ -2176,6 +2274,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
return 1;
}
+ info->PrimaryOutput = arg_obj;
+
{
cmGeneratedFileStream depfile(arg_dep);
depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
@@ -2185,24 +2285,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
depfile << "\n";
}
- Json::Value ddi(Json::objectValue);
- ddi["object"] = arg_obj;
-
- Json::Value& ddi_provides = ddi["provides"] = Json::arrayValue;
- for (std::string const& provide : info->Provides) {
- ddi_provides.append(provide);
- }
- Json::Value& ddi_requires = ddi["requires"] = Json::arrayValue;
- for (std::string const& r : info->Requires) {
- // Require modules not provided in the same source.
- if (!info->Provides.count(r)) {
- ddi_requires.append(r);
- }
- }
-
- cmGeneratedFileStream ddif(arg_ddi);
- ddif << ddi;
- if (!ddif) {
+ if (!cmScanDepFormat_P1689_Write(arg_ddi, arg_src, *info)) {
cmSystemTools::Error(
cmStrCat("-E cmake_ninja_depends failed to write ", arg_ddi));
return 1;
@@ -2260,26 +2343,35 @@ std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
}
auto info = cm::make_unique<cmSourceInfo>();
- info->Provides = finfo.Provides;
- info->Requires = finfo.Requires;
- info->Includes = finfo.Includes;
+ for (std::string const& provide : finfo.Provides) {
+ cmSourceReqInfo src_info;
+ src_info.LogicalName = provide;
+ src_info.CompiledModulePath = provide;
+ info->Provides.emplace_back(src_info);
+ }
+ for (std::string const& require : finfo.Requires) {
+ // Require modules not provided in the same source.
+ if (finfo.Provides.count(require)) {
+ continue;
+ }
+ cmSourceReqInfo src_info;
+ src_info.LogicalName = require;
+ src_info.CompiledModulePath = require;
+ info->Requires.emplace_back(src_info);
+ }
+ for (std::string const& include : finfo.Includes) {
+ info->Includes.push_back(include);
+ }
return info;
}
-struct cmDyndepObjectInfo
-{
- std::string Object;
- std::vector<std::string> Provides;
- std::vector<std::string> Requires;
-};
-
bool cmGlobalNinjaGenerator::WriteDyndepFile(
std::string const& dir_top_src, std::string const& dir_top_bld,
std::string const& dir_cur_src, std::string const& dir_cur_bld,
std::string const& arg_dd, std::vector<std::string> const& arg_ddis,
std::string const& module_dir,
std::vector<std::string> const& linked_target_dirs,
- std::string const& arg_lang)
+ std::string const& arg_lang, std::string const& arg_modmapfmt)
{
// Setup path conversions.
{
@@ -2294,34 +2386,14 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
this->LocalGenerators.push_back(std::move(lgd));
}
- std::vector<cmDyndepObjectInfo> objects;
+ std::vector<cmSourceInfo> objects;
for (std::string const& arg_ddi : arg_ddis) {
- // Load the ddi file and compute the module file paths it provides.
- Json::Value ddio;
- Json::Value const& ddi = ddio;
- cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary);
- Json::Reader reader;
- if (!reader.parse(ddif, ddio, false)) {
- cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ",
- arg_ddi,
- reader.getFormattedErrorMessages()));
+ cmSourceInfo info;
+ if (!cmScanDepFormat_P1689_Parse(arg_ddi, &info)) {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep failed to parse ddi file ", arg_ddi));
return false;
}
-
- cmDyndepObjectInfo info;
- info.Object = ddi["object"].asString();
- Json::Value const& ddi_provides = ddi["provides"];
- if (ddi_provides.isArray()) {
- for (auto const& ddi_provide : ddi_provides) {
- info.Provides.push_back(ddi_provide.asString());
- }
- }
- Json::Value const& ddi_requires = ddi["requires"];
- if (ddi_requires.isArray()) {
- for (auto const& ddi_require : ddi_requires) {
- info.Requires.push_back(ddi_require.asString());
- }
- }
objects.push_back(std::move(info));
}
@@ -2352,11 +2424,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
// We do this after loading the modules provided by linked targets
// in case we have one of the same name that must be preferred.
Json::Value tm = Json::objectValue;
- for (cmDyndepObjectInfo const& object : objects) {
- for (std::string const& p : object.Provides) {
- std::string const mod = cmStrCat(module_dir, p);
- mod_files[p] = mod;
- tm[p] = mod;
+ for (cmSourceInfo const& object : objects) {
+ for (auto const& p : object.Provides) {
+ std::string const mod = cmStrCat(
+ module_dir, cmSystemTools::GetFilenameName(p.CompiledModulePath));
+ mod_files[p.LogicalName] = mod;
+ tm[p.LogicalName] = mod;
}
}
@@ -2366,15 +2439,16 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
{
cmNinjaBuild build("dyndep");
build.Outputs.emplace_back("");
- for (cmDyndepObjectInfo const& object : objects) {
- build.Outputs[0] = object.Object;
+ for (cmSourceInfo const& object : objects) {
+ build.Outputs[0] = this->ConvertToNinjaPath(object.PrimaryOutput);
build.ImplicitOuts.clear();
- for (std::string const& p : object.Provides) {
- build.ImplicitOuts.push_back(this->ConvertToNinjaPath(mod_files[p]));
+ for (auto const& p : object.Provides) {
+ build.ImplicitOuts.push_back(
+ this->ConvertToNinjaPath(mod_files[p.LogicalName]));
}
build.ImplicitDeps.clear();
- for (std::string const& r : object.Requires) {
- auto mit = mod_files.find(r);
+ for (auto const& r : object.Requires) {
+ auto mit = mod_files.find(r.LogicalName);
if (mit != mod_files.end()) {
build.ImplicitDeps.push_back(this->ConvertToNinjaPath(mit->second));
}
@@ -2384,6 +2458,48 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
build.Variables.emplace("restat", "1");
}
+ if (arg_modmapfmt.empty()) {
+ // nothing to do.
+ } else {
+ std::stringstream mm;
+ if (arg_modmapfmt == "gcc") {
+ // Documented in GCC's documentation. The format is a series of lines
+ // with a module name and the associated filename separated by
+ // spaces. The first line may use `$root` as the module name to
+ // specify a "repository root". That is used to anchor any relative
+ // paths present in the file (CMake should never generate any).
+
+ // Write the root directory to use for module paths.
+ mm << "$root .\n";
+
+ for (auto const& l : object.Provides) {
+ auto m = mod_files.find(l.LogicalName);
+ if (m != mod_files.end()) {
+ mm << l.LogicalName << " " << this->ConvertToNinjaPath(m->second)
+ << "\n";
+ }
+ }
+ for (auto const& r : object.Requires) {
+ auto m = mod_files.find(r.LogicalName);
+ if (m != mod_files.end()) {
+ mm << r.LogicalName << " " << this->ConvertToNinjaPath(m->second)
+ << "\n";
+ }
+ }
+ } else {
+ cmSystemTools::Error(
+ cmStrCat("-E cmake_ninja_dyndep does not understand the ",
+ arg_modmapfmt, " module map format"));
+ return false;
+ }
+
+ // XXX(modmap): If changing this path construction, change
+ // `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the
+ // corresponding file path.
+ cmGeneratedFileStream mmf(cmStrCat(object.PrimaryOutput, ".modmap"));
+ mmf << mm.str();
+ }
+
this->WriteBuild(ddf, build);
}
}
@@ -2398,11 +2514,6 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
return true;
}
-bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
-{
- return !this->CrossConfigs.empty();
-}
-
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
@@ -2412,6 +2523,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::string arg_dd;
std::string arg_lang;
std::string arg_tdi;
+ std::string arg_modmapfmt;
std::vector<std::string> arg_ddis;
for (std::string const& arg : arg_full) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
@@ -2420,6 +2532,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
arg_lang = arg.substr(7);
} else if (cmHasLiteralPrefix(arg, "--dd=")) {
arg_dd = arg.substr(5);
+ } else if (cmHasLiteralPrefix(arg, "--modmapfmt=")) {
+ arg_modmapfmt = arg.substr(12);
} else if (!cmHasLiteralPrefix(arg, "--") &&
cmHasLiteralSuffix(arg, ".ddi")) {
arg_ddis.push_back(arg);
@@ -2478,12 +2592,19 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
if (!ggd ||
!cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile(
dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis,
- module_dir, linked_target_dirs, arg_lang)) {
+ module_dir, linked_target_dirs, arg_lang, arg_modmapfmt)) {
return 1;
}
return 0;
}
+#endif
+
+bool cmGlobalNinjaGenerator::EnableCrossConfigBuild() const
+{
+ return !this->CrossConfigs.empty();
+}
+
void cmGlobalNinjaGenerator::AppendDirectoryForConfig(
const std::string& prefix, const std::string& config,
const std::string& suffix, std::string& dir)
@@ -2501,6 +2622,13 @@ std::set<std::string> cmGlobalNinjaGenerator::GetCrossConfigs(
return result;
}
+bool cmGlobalNinjaGenerator::IsSingleConfigUtility(
+ cmGeneratorTarget const* target) const
+{
+ return target->GetType() == cmStateEnums::UTILITY &&
+ !this->PerConfigUtilityTargets.count(target->GetName());
+}
+
const char* cmGlobalNinjaMultiGenerator::NINJA_COMMON_FILE =
"CMakeFiles/common.ninja";
const char* cmGlobalNinjaMultiGenerator::NINJA_FILE_EXTENSION = ".ninja";
@@ -2651,30 +2779,17 @@ void cmGlobalNinjaMultiGenerator::GetQtAutoGenConfigs(
bool cmGlobalNinjaMultiGenerator::InspectConfigTypeVariables()
{
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_BUILD_TYPE");
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_CROSS_CONFIGS");
- this->GetCMakeInstance()->MarkCliAsUsed("CMAKE_DEFAULT_CONFIGS");
- return this->ReadCacheEntriesForBuild(*this->Makefiles.front()->GetState());
-}
-
-std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
-{
- return "";
-}
-
-bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
- const cmState& state)
-{
std::vector<std::string> configsVec;
- cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CONFIGURATION_TYPES"),
- configsVec);
+ cmExpandList(
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_CONFIGURATION_TYPES"),
+ configsVec);
if (configsVec.empty()) {
configsVec.emplace_back();
}
std::set<std::string> configs(configsVec.cbegin(), configsVec.cend());
this->DefaultFileConfig =
- state.GetSafeCacheEntryValue("CMAKE_DEFAULT_BUILD_TYPE");
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_BUILD_TYPE");
if (this->DefaultFileConfig.empty()) {
this->DefaultFileConfig = configsVec.front();
}
@@ -2689,8 +2804,9 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
}
std::vector<std::string> crossConfigsVec;
- cmExpandList(state.GetSafeCacheEntryValue("CMAKE_CROSS_CONFIGS"),
- crossConfigsVec);
+ cmExpandList(
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_CROSS_CONFIGS"),
+ crossConfigsVec);
auto crossConfigs = ListSubsetWithAll(configs, configs, crossConfigsVec);
if (!crossConfigs) {
std::ostringstream msg;
@@ -2703,7 +2819,7 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
this->CrossConfigs = *crossConfigs;
auto defaultConfigsString =
- state.GetSafeCacheEntryValue("CMAKE_DEFAULT_CONFIGS");
+ this->Makefiles.front()->GetSafeDefinition("CMAKE_DEFAULT_CONFIGS");
if (defaultConfigsString.empty()) {
defaultConfigsString = this->DefaultFileConfig;
}
@@ -2737,6 +2853,11 @@ bool cmGlobalNinjaMultiGenerator::ReadCacheEntriesForBuild(
return true;
}
+std::string cmGlobalNinjaMultiGenerator::GetDefaultBuildConfig() const
+{
+ return "";
+}
+
std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTarget(
cmGeneratorTarget const* target, const std::string& config) const
{