summaryrefslogtreecommitdiffstats
path: root/Source/cmGlobalNinjaGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmGlobalNinjaGenerator.cxx')
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx251
1 files changed, 152 insertions, 99 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 920f639..e443678 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -26,6 +26,7 @@
#include "cmMessageType.h"
#include "cmNinjaLinkLineComputer.h"
#include "cmOutputConverter.h"
+#include "cmRange.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
@@ -136,16 +137,16 @@ void cmGlobalNinjaGenerator::WriteBuild(
// Make sure there is a rule.
if (rule.empty()) {
cmSystemTools::Error("No rule for WriteBuildStatement! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
// Make sure there is at least one output file.
if (outputs.empty()) {
cmSystemTools::Error("No output files for WriteBuildStatement! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
@@ -334,16 +335,16 @@ void cmGlobalNinjaGenerator::WriteRule(
// Make sure the rule has a name.
if (name.empty()) {
cmSystemTools::Error("No name given for WriteRuleStatement! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
// Make sure a command is given.
if (command.empty()) {
cmSystemTools::Error("No command given for WriteRuleStatement! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
@@ -376,7 +377,7 @@ void cmGlobalNinjaGenerator::WriteRule(
if (!rspfile.empty()) {
if (rspcontent.empty()) {
- cmSystemTools::Error("No rspfile_content given!", comment.c_str());
+ cmSystemTools::Error("No rspfile_content given!" + comment);
return;
}
cmGlobalNinjaGenerator::Indent(os, 1);
@@ -407,8 +408,8 @@ void cmGlobalNinjaGenerator::WriteVariable(std::ostream& os,
// Make sure we have a name.
if (name.empty()) {
cmSystemTools::Error("No name given for WriteVariable! called "
- "with comment: ",
- comment.c_str());
+ "with comment: " +
+ comment);
return;
}
@@ -676,31 +677,37 @@ void cmGlobalNinjaGenerator::EnableLanguage(
// cmGlobalXCodeGenerator
// Called by:
// cmGlobalGenerator::Build()
-void cmGlobalNinjaGenerator::GenerateBuildCommand(
- GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
- const std::string& /*projectName*/, const std::string& /*projectDir*/,
- const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
- int jobs, bool verbose, std::vector<std::string> const& makeOptions)
+std::vector<cmGlobalGenerator::GeneratedMakeCommand>
+cmGlobalNinjaGenerator::GenerateBuildCommand(
+ const std::string& makeProgram, const std::string& /*projectName*/,
+ const std::string& /*projectDir*/,
+ std::vector<std::string> const& targetNames, const std::string& /*config*/,
+ bool /*fast*/, int jobs, bool verbose,
+ std::vector<std::string> const& makeOptions)
{
- makeCommand.add(this->SelectMakeProgram(makeProgram));
+ GeneratedMakeCommand makeCommand;
+ makeCommand.Add(this->SelectMakeProgram(makeProgram));
if (verbose) {
- makeCommand.add("-v");
+ makeCommand.Add("-v");
}
if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
(jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
- makeCommand.add("-j", std::to_string(jobs));
+ makeCommand.Add("-j", std::to_string(jobs));
}
- makeCommand.add(makeOptions.begin(), makeOptions.end());
- if (!targetName.empty()) {
- if (targetName == "clean") {
- makeCommand.add("-t", "clean");
- } else {
- makeCommand.add(targetName);
+ makeCommand.Add(makeOptions.begin(), makeOptions.end());
+ for (const auto& tname : targetNames) {
+ if (!tname.empty()) {
+ if (tname == "clean") {
+ makeCommand.Add("-t", "clean");
+ } else {
+ makeCommand.Add(tname);
+ }
}
}
+ return { std::move(makeCommand) };
}
// Non-virtual public methods.
@@ -1573,12 +1580,13 @@ Compilation of source files within a target is split into the following steps:
command = gfortran -cpp $DEFINES $INCLUDES $FLAGS -E $in -o $out &&
cmake -E cmake_ninja_depends \
--tdi=FortranDependInfo.json --pp=$out --dep=$DEP_FILE \
- --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE
+ --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE \
+ --lang=Fortran
- build src.f90-pp.f90 | src.f90-pp.f90.ddi: Fortran_PREPROCESS src.f90
+ build src.f90-pp.f90 | src.f90.o.ddi: Fortran_PREPROCESS src.f90
OBJ_FILE = src.f90.o
- DEP_FILE = src.f90-pp.f90.d
- DYNDEP_INTERMEDIATE_FILE = src.f90-pp.f90.ddi
+ DEP_FILE = src.f90.o.d
+ DYNDEP_INTERMEDIATE_FILE = src.f90.o.ddi
The ``cmake -E cmake_ninja_depends`` tool reads the preprocessed output
and generates the ninja depfile for preprocessor dependencies. It also
@@ -1592,9 +1600,9 @@ 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
+ build Fortran.dd: Fortran_DYNDEP src1.f90.o.ddi src2.f90.o.ddi
The ``cmake -E cmake_ninja_dyndep`` tool reads the "ddi" files from all
sources in the target and the ``FortranModules.json`` files from targets
@@ -1632,6 +1640,19 @@ 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);
+
int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::vector<std::string>::const_iterator argEnd)
{
@@ -1640,8 +1661,8 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
std::string arg_dep;
std::string arg_obj;
std::string arg_ddi;
- for (std::vector<std::string>::const_iterator a = argBeg; a != argEnd; ++a) {
- std::string const& arg = *a;
+ std::string arg_lang;
+ for (std::string const& arg : cmMakeRange(argBeg, argEnd)) {
if (cmHasLiteralPrefix(arg, "--tdi=")) {
arg_tdi = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--pp=")) {
@@ -1652,9 +1673,10 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
arg_obj = arg.substr(6);
} else if (cmHasLiteralPrefix(arg, "--ddi=")) {
arg_ddi = arg.substr(6);
+ } else if (cmHasLiteralPrefix(arg, "--lang=")) {
+ arg_lang = arg.substr(7);
} else {
- cmSystemTools::Error("-E cmake_ninja_depends unknown argument: ",
- arg.c_str());
+ cmSystemTools::Error("-E cmake_ninja_depends unknown argument: " + arg);
return 1;
}
}
@@ -1678,7 +1700,61 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
cmSystemTools::Error("-E cmake_ninja_depends requires value for --ddi=");
return 1;
}
+ if (arg_lang.empty()) {
+ cmSystemTools::Error("-E cmake_ninja_depends requires value for --lang=");
+ return 1;
+ }
+
+ std::unique_ptr<cmSourceInfo> info;
+ if (arg_lang == "Fortran") {
+ info = cmcmd_cmake_ninja_depends_fortran(arg_tdi, arg_pp);
+ } else {
+ cmSystemTools::Error("-E cmake_ninja_depends does not understand the " +
+ arg_lang + " language");
+ return 1;
+ }
+
+ if (!info) {
+ // The error message is already expected to have been output.
+ return 1;
+ }
+
+ {
+ cmGeneratedFileStream depfile(arg_dep);
+ depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
+ for (std::string const& include : info->Includes) {
+ depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
+ }
+ 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) {
+ cmSystemTools::Error("-E cmake_ninja_depends failed to write " + arg_ddi);
+ return 1;
+ }
+ return 0;
+}
+
+std::unique_ptr<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran(
+ std::string const& arg_tdi, std::string const& arg_pp)
+{
cmFortranCompiler fc;
std::vector<std::string> includes;
{
@@ -1688,10 +1764,9 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (!reader.parse(tdif, tdio, false)) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to parse ",
- arg_tdi.c_str(),
- reader.getFormattedErrorMessages().c_str());
- return 1;
+ cmSystemTools::Error("-E cmake_ninja_depends failed to parse " +
+ arg_tdi + reader.getFormattedErrorMessages());
+ return nullptr;
}
}
@@ -1712,54 +1787,26 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
fc.SModExt = tdi_submodule_ext.asString();
}
- cmFortranSourceInfo info;
+ cmFortranSourceInfo finfo;
std::set<std::string> defines;
- cmFortranParser parser(fc, includes, defines, info);
+ cmFortranParser parser(fc, includes, defines, finfo);
if (!cmFortranParser_FilePush(&parser, arg_pp.c_str())) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to open ",
- arg_pp.c_str());
- return 1;
+ cmSystemTools::Error("-E cmake_ninja_depends failed to open " + arg_pp);
+ return nullptr;
}
if (cmFortran_yyparse(parser.Scanner) != 0) {
// Failed to parse the file.
- return 1;
+ return nullptr;
}
- {
- cmGeneratedFileStream depfile(arg_dep);
- depfile << cmSystemTools::ConvertToUnixOutputPath(arg_pp) << ":";
- for (std::string const& include : info.Includes) {
- depfile << " \\\n " << cmSystemTools::ConvertToUnixOutputPath(include);
- }
- 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) {
- cmSystemTools::Error("-E cmake_ninja_depends failed to write ",
- arg_ddi.c_str());
- return 1;
- }
- return 0;
+ auto info = cm::make_unique<cmSourceInfo>();
+ info->Provides = finfo.Provides;
+ info->Requires = finfo.Requires;
+ info->Includes = finfo.Includes;
+ return info;
}
-struct cmFortranObjectInfo
+struct cmDyndepObjectInfo
{
std::string Object;
std::vector<std::string> Provides;
@@ -1771,7 +1818,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.
{
@@ -1788,7 +1836,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;
@@ -1796,13 +1844,12 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
cmsys::ifstream ddif(arg_ddi.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (!reader.parse(ddif, ddio, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- arg_ddi.c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " + arg_ddi +
+ reader.getFormattedErrorMessages());
return false;
}
- cmFortranObjectInfo info;
+ cmDyndepObjectInfo info;
info.Object = ddi["object"].asString();
Json::Value const& ddi_provides = ddi["provides"];
if (ddi_provides.isArray()) {
@@ -1824,14 +1871,15 @@ 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;
if (ltmf && !reader.parse(ltmf, ltm, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- linked_target_dir.c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " +
+ linked_target_dir +
+ reader.getFormattedErrorMessages());
return false;
}
if (ltm.isObject()) {
@@ -1845,7 +1893,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;
@@ -1856,7 +1904,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;
@@ -1887,7 +1935,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;
@@ -1901,19 +1949,21 @@ 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, "--") &&
cmHasLiteralSuffix(arg, ".ddi")) {
arg_ddis.push_back(arg);
} else {
- cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: ",
- arg.c_str());
+ cmSystemTools::Error("-E cmake_ninja_dyndep unknown argument: " + arg);
return 1;
}
}
@@ -1921,6 +1971,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;
@@ -1932,9 +1986,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
cmsys::ifstream tdif(arg_tdi.c_str(), std::ios::in | std::ios::binary);
Json::Reader reader;
if (!reader.parse(tdif, tdio, false)) {
- cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse ",
- arg_tdi.c_str(),
- reader.getFormattedErrorMessages().c_str());
+ cmSystemTools::Error("-E cmake_ninja_dyndep failed to parse " + arg_tdi +
+ reader.getFormattedErrorMessages());
return 1;
}
}
@@ -1944,7 +1997,7 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
std::string const dir_top_bld = tdi["dir-top-bld"].asString();
std::string const dir_top_src = tdi["dir-top-src"].asString();
std::string module_dir = tdi["module-dir"].asString();
- if (!module_dir.empty()) {
+ if (!module_dir.empty() && !cmHasLiteralSuffix(module_dir, "/")) {
module_dir += "/";
}
std::vector<std::string> linked_target_dirs;
@@ -1962,8 +2015,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;