mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-27 03:08:35 -06:00
ninja: make dyndep generation language aware
A target may have multiple languages with dyndep rules, separate `.dd` files should be generated.
This commit is contained in:
@@ -1593,7 +1593,7 @@ Compilation of source files within a target is split into the following steps:
|
||||
|
||||
rule Fortran_DYNDEP
|
||||
command = cmake -E cmake_ninja_dyndep \
|
||||
--tdi=FortranDependInfo.json --dd=$out $in
|
||||
--tdi=FortranDependInfo.json --lang=Fortran --dd=$out $in
|
||||
|
||||
build Fortran.dd: Fortran_DYNDEP src1.f90-pp.f90.ddi src2.f90-pp.f90.ddi
|
||||
|
||||
@@ -1755,7 +1755,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct cmFortranObjectInfo
|
||||
struct cmDyndepObjectInfo
|
||||
{
|
||||
std::string Object;
|
||||
std::vector<std::string> Provides;
|
||||
@@ -1767,7 +1767,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
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::vector<std::string> const& linked_target_dirs,
|
||||
std::string const& arg_lang)
|
||||
{
|
||||
// Setup path conversions.
|
||||
{
|
||||
@@ -1784,7 +1785,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
this->LocalGenerators.push_back(lgd.release());
|
||||
}
|
||||
|
||||
std::vector<cmFortranObjectInfo> objects;
|
||||
std::vector<cmDyndepObjectInfo> objects;
|
||||
for (std::string const& arg_ddi : arg_ddis) {
|
||||
// Load the ddi file and compute the module file paths it provides.
|
||||
Json::Value ddio;
|
||||
@@ -1797,7 +1798,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
return false;
|
||||
}
|
||||
|
||||
cmFortranObjectInfo info;
|
||||
cmDyndepObjectInfo info;
|
||||
info.Object = ddi["object"].asString();
|
||||
Json::Value const& ddi_provides = ddi["provides"];
|
||||
if (ddi_provides.isArray()) {
|
||||
@@ -1819,7 +1820,8 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
|
||||
// Populate the module map with those provided by linked targets first.
|
||||
for (std::string const& linked_target_dir : linked_target_dirs) {
|
||||
std::string const ltmn = linked_target_dir + "/FortranModules.json";
|
||||
std::string const ltmn =
|
||||
linked_target_dir + "/" + arg_lang + "Modules.json";
|
||||
Json::Value ltm;
|
||||
cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary);
|
||||
Json::Reader reader;
|
||||
@@ -1840,7 +1842,7 @@ 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 (cmFortranObjectInfo const& object : objects) {
|
||||
for (cmDyndepObjectInfo const& object : objects) {
|
||||
for (std::string const& p : object.Provides) {
|
||||
std::string const mod = module_dir + p;
|
||||
mod_files[p] = mod;
|
||||
@@ -1851,7 +1853,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
cmGeneratedFileStream ddf(arg_dd);
|
||||
ddf << "ninja_dyndep_version = 1.0\n";
|
||||
|
||||
for (cmFortranObjectInfo const& object : objects) {
|
||||
for (cmDyndepObjectInfo const& object : objects) {
|
||||
std::string const ddComment;
|
||||
std::string const ddRule = "dyndep";
|
||||
cmNinjaDeps ddOutputs;
|
||||
@@ -1882,7 +1884,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
|
||||
// Store the map of modules provided by this target in a file for
|
||||
// use by dependents that reference this target in linked-target-dirs.
|
||||
std::string const target_mods_file =
|
||||
cmSystemTools::GetFilenamePath(arg_dd) + "/FortranModules.json";
|
||||
cmSystemTools::GetFilenamePath(arg_dd) + "/" + arg_lang + "Modules.json";
|
||||
cmGeneratedFileStream tmf(target_mods_file);
|
||||
tmf << tm;
|
||||
|
||||
@@ -1896,11 +1898,14 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
cmSystemTools::HandleResponseFile(argBeg, argEnd);
|
||||
|
||||
std::string arg_dd;
|
||||
std::string arg_lang;
|
||||
std::string arg_tdi;
|
||||
std::vector<std::string> arg_ddis;
|
||||
for (std::string const& arg : arg_full) {
|
||||
if (cmHasLiteralPrefix(arg, "--tdi=")) {
|
||||
arg_tdi = arg.substr(6);
|
||||
} else if (cmHasLiteralPrefix(arg, "--lang=")) {
|
||||
arg_lang = arg.substr(7);
|
||||
} else if (cmHasLiteralPrefix(arg, "--dd=")) {
|
||||
arg_dd = arg.substr(5);
|
||||
} else if (!cmHasLiteralPrefix(arg, "--") &&
|
||||
@@ -1915,6 +1920,10 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --tdi=");
|
||||
return 1;
|
||||
}
|
||||
if (arg_lang.empty()) {
|
||||
cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --lang=");
|
||||
return 1;
|
||||
}
|
||||
if (arg_dd.empty()) {
|
||||
cmSystemTools::Error("-E cmake_ninja_dyndep requires value for --dd=");
|
||||
return 1;
|
||||
@@ -1955,8 +1964,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
static_cast<cmGlobalNinjaGenerator*>(cm.CreateGlobalGenerator("Ninja")));
|
||||
if (!ggd ||
|
||||
!ggd->WriteDyndepFile(dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld,
|
||||
arg_dd, arg_ddis, module_dir,
|
||||
linked_target_dirs)) {
|
||||
arg_dd, arg_ddis, module_dir, linked_target_dirs,
|
||||
arg_lang)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -365,7 +365,8 @@ public:
|
||||
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::vector<std::string> const& linked_target_dirs,
|
||||
std::string const& arg_lang);
|
||||
|
||||
protected:
|
||||
void Generate() override;
|
||||
|
||||
@@ -594,7 +594,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
|
||||
ddCmds.push_back(cmake +
|
||||
" -E cmake_ninja_dyndep"
|
||||
" --tdi=" +
|
||||
tdi +
|
||||
tdi + " --lang=" + lang +
|
||||
" --dd=$out"
|
||||
" " +
|
||||
ddInput);
|
||||
@@ -868,24 +868,27 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
|
||||
this->WriteObjectBuildStatement(sf);
|
||||
}
|
||||
|
||||
if (!this->DDIFiles.empty()) {
|
||||
for (auto const& langDDIFiles : this->DDIFiles) {
|
||||
std::string const& language = langDDIFiles.first;
|
||||
cmNinjaDeps const& ddiFiles = langDDIFiles.second;
|
||||
|
||||
std::string const ddComment;
|
||||
std::string const ddRule = this->LanguageDyndepRule("Fortran");
|
||||
std::string const ddRule = this->LanguageDyndepRule(language);
|
||||
cmNinjaDeps ddOutputs;
|
||||
cmNinjaDeps ddImplicitOuts;
|
||||
cmNinjaDeps const& ddExplicitDeps = this->DDIFiles;
|
||||
cmNinjaDeps const& ddExplicitDeps = ddiFiles;
|
||||
cmNinjaDeps ddImplicitDeps;
|
||||
cmNinjaDeps ddOrderOnlyDeps;
|
||||
cmNinjaVars ddVars;
|
||||
|
||||
this->WriteTargetDependInfo("Fortran");
|
||||
this->WriteTargetDependInfo(language);
|
||||
|
||||
ddOutputs.push_back(this->GetDyndepFilePath("Fortran"));
|
||||
ddOutputs.push_back(this->GetDyndepFilePath(language));
|
||||
|
||||
// Make sure dyndep files for all our dependencies have already
|
||||
// been generated so that the 'FortranModules.json' files they
|
||||
// been generated so that the '<LANG>Modules.json' files they
|
||||
// produced as side-effects are available for us to read.
|
||||
// Ideally we should depend on the 'FortranModules.json' files
|
||||
// Ideally we should depend on the '<LANG>Modules.json' files
|
||||
// from our dependencies directly, but we don't know which of
|
||||
// our dependencies produces them. Fixing this will require
|
||||
// refactoring the Ninja generator to generate targets in
|
||||
@@ -1099,7 +1102,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
|
||||
std::string const ddiFile = ppFileName + ".ddi";
|
||||
ppVars["DYNDEP_INTERMEDIATE_FILE"] = ddiFile;
|
||||
ppImplicitOuts.push_back(ddiFile);
|
||||
this->DDIFiles.push_back(ddiFile);
|
||||
this->DDIFiles[language].push_back(ddiFile);
|
||||
}
|
||||
|
||||
this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(),
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "cmNinjaTypes.h"
|
||||
#include "cmOSXBundleGenerator.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -165,7 +166,7 @@ private:
|
||||
cmLocalNinjaGenerator* LocalGenerator;
|
||||
/// List of object files for this target.
|
||||
cmNinjaDeps Objects;
|
||||
cmNinjaDeps DDIFiles; // TODO: Make per-language.
|
||||
std::map<std::string, cmNinjaDeps> DDIFiles;
|
||||
std::vector<cmCustomCommand const*> CustomCommands;
|
||||
cmNinjaDeps ExtraFiles;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user