From 791b4d26d6cbcb69615ddfbd1872a34a2e214b39 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Mon, 10 Feb 2020 11:18:46 -0500 Subject: ninja: add experimental infrastructure to generate modmap files with dyndep The scan step may need to output additional information for the compiler, not just the build tool. The modmap is assumed to be beside the object output. Additional refactoring may open up a channel to inform per-source paths to the dyndep rule in the future, but is not done here. --- Source/cmGlobalNinjaGenerator.cxx | 26 ++++++++++++++++++++-- Source/cmGlobalNinjaGenerator.h | 16 ++++++------- Source/cmNinjaTargetGenerator.cxx | 47 +++++++++++++++++++++++++++++++++++---- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 16cdcd3..25d6a56 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2369,7 +2369,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( std::string const& arg_dd, std::vector const& arg_ddis, std::string const& module_dir, std::vector const& linked_target_dirs, - std::string const& arg_lang) + std::string const& arg_lang, std::string const& arg_modmapfmt) { // Setup path conversions. { @@ -2456,6 +2456,25 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( build.Variables.emplace("restat", "1"); } + if (arg_modmapfmt.empty()) { + // nothing to do. + } else { + std::stringstream mm; + if (false) { + } 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); } } @@ -2479,6 +2498,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, std::string arg_dd; std::string arg_lang; std::string arg_tdi; + std::string arg_modmapfmt; std::vector arg_ddis; for (std::string const& arg : arg_full) { if (cmHasLiteralPrefix(arg, "--tdi=")) { @@ -2487,6 +2507,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector::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); @@ -2545,7 +2567,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector::const_iterator argBeg, if (!ggd || !cm::static_reference_cast(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; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index b21586b..96065ed 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -393,15 +393,13 @@ public: bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); } void StripNinjaOutputPathPrefixAsSuffix(std::string& path); - bool 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 const& arg_ddis, - std::string const& module_dir, - std::vector const& linked_target_dirs, - std::string const& arg_lang); + bool 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 const& arg_ddis, + std::string const& module_dir, + std::vector const& linked_target_dirs, + std::string const& arg_lang, std::string const& arg_modmapfmt); virtual std::string BuildAlias(const std::string& alias, const std::string& /*config*/) const diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 124e885..5aaa79e 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -619,6 +619,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 rulePlaceholderExpander( this->GetLocalGenerator()->CreateRulePlaceholderExpander()); @@ -715,12 +719,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 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); @@ -782,6 +790,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, "", + "$DYNDEP_MODULE_MAP_FILE"); + flags += cmStrCat(' ', modmapFlags); + } + vars.Flags = flags.c_str(); vars.DependencyFile = rule.DepFile.c_str(); @@ -1084,6 +1100,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) { @@ -1154,6 +1171,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; } } @@ -1297,6 +1323,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( 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 @@ -1326,7 +1359,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 @@ -1362,6 +1395,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); + } } EnsureParentDirectoryExists(objectFileName); -- cgit v0.12