From aeb1b2ae3d1c6774c2c4175aa566085697eefe49 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 31 Jan 2023 22:20:32 -0500 Subject: cmMakefileTargetGenerator: simplify string streaming --- Source/cmMakefileTargetGenerator.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 9df1af7..58cdb22 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1494,8 +1494,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() /* clang-format off */ *this->InfoFileStream << "\n" - << "# Targets to which this target links.\n" - << "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; + "# Targets to which this target links which contain Fortran sources.\n" + "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ std::vector dirs = this->GetLinkedTargetDirectories(this->GetConfigName()); -- cgit v0.12 From 245a89d8b68525a769bdd4f71c184aa97fa498b3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 31 Jan 2023 22:20:46 -0500 Subject: cmMakefileTargetGenerator: make "target linked info" variable Fortran-specific This variable is Fortran-specific, so clarify that through its name. --- Source/cmDependsFortran.cxx | 2 +- Source/cmMakefileTargetGenerator.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index ac93c90..95f2a6b 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -243,7 +243,7 @@ void cmDependsFortran::LocateModules() // Load information about other targets. cmMakefile* mf = this->LocalGenerator->GetMakefile(); std::vector infoFiles; - mf->GetDefExpandList("CMAKE_TARGET_LINKED_INFO_FILES", infoFiles); + mf->GetDefExpandList("CMAKE_Fortran_TARGET_LINKED_INFO_FILES", infoFiles); for (std::string const& i : infoFiles) { std::string targetDir = cmSystemTools::GetFilenamePath(i); std::string fname = targetDir + "/fortran.internal"; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 58cdb22..4f80edc 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1495,7 +1495,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() *this->InfoFileStream << "\n" "# Targets to which this target links which contain Fortran sources.\n" - "set(CMAKE_TARGET_LINKED_INFO_FILES\n"; + "set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ std::vector dirs = this->GetLinkedTargetDirectories(this->GetConfigName()); -- cgit v0.12 From d19648a9286d0943858ea0c5dc5e13d3b735b129 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 31 Jan 2023 22:19:47 -0500 Subject: cmGeneratorTarget: add a method to query if Fortran sources exist --- Source/cmGeneratorTarget.cxx | 9 +++++++++ Source/cmGeneratorTarget.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 30aa99b..5e352b2 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8860,6 +8860,15 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( return filename; } +bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const +{ + auto sources = cmGeneratorTarget::GetSourceFiles(config); + return std::any_of(sources.begin(), sources.end(), + [](BT const& sf) -> bool { + return sf.Value->GetLanguage() == "Fortran"_s; + }); +} + bool cmGeneratorTarget::HaveCxx20ModuleSources() const { auto const& fs_names = this->Target->GetAllFileSetNames(); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index dd10c64..afd9da4 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1225,6 +1225,8 @@ public: cmGeneratorTarget const* t2) const; }; + bool HaveFortranSources(std::string const& config) const; + // C++20 module support queries. /** -- cgit v0.12 From 837f7c113a9333997304c3b5742c922617da23b5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 31 Jan 2023 22:13:56 -0500 Subject: cmCommonTargetGenerator: classify linked target directories by language These directories are used to direct collators for Fortran and C++ modules to consume dependent module information to properly collate. However, the consumption of these files merely checks for existence of the file, not whether they are actually needed anymore. The problem arises when a target has Fortran or C++ modules at point A, a build occurs populating this file, and then the target is updated to no longer have potential modules. The `DependInfo.make` (for `Makefiles`) or `DependInfo.json` (for `Ninja`) files still exist as they are never guaranteed to be cleaned up. This can introduce stale information to the build which may cause a false-positive compilation if a module file happens to still exist and gets found this way. Instead, query the `linked-target-dirs` using the language in question and only add the directory if it contains potential sources for modules coming from the language in question. --- Source/cmCommonTargetGenerator.cxx | 7 ++++++- Source/cmCommonTargetGenerator.h | 2 +- Source/cmMakefileTargetGenerator.cxx | 2 +- Source/cmNinjaTargetGenerator.cxx | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 5fe6756..a065ba9 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -6,6 +6,9 @@ #include #include +#include +#include + #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" @@ -157,7 +160,7 @@ std::string cmCommonTargetGenerator::GetIncludes(std::string const& l, } std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories( - const std::string& config) const + const std::string& lang, const std::string& config) const { std::vector dirs; std::set emitted; @@ -172,6 +175,8 @@ std::vector cmCommonTargetGenerator::GetLinkedTargetDirectories( // Target->GetLinkInformation already processed their // link interface and they don't have any output themselves. && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY && + ((lang == "CXX"_s && linkee->HaveCxx20ModuleSources()) || + (lang == "Fortran"_s && linkee->HaveFortranSources(config))) && emitted.insert(linkee).second) { cmLocalGenerator* lg = linkee->GetLocalGenerator(); std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index e8c5a19..2d23037 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -65,7 +65,7 @@ protected: std::string GetAIXExports(std::string const& config); std::vector GetLinkedTargetDirectories( - const std::string& config) const; + const std::string& lang, const std::string& config) const; std::string ComputeTargetCompilePDB(const std::string& config) const; std::string GetLinkerLauncher(const std::string& config); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 4f80edc..c40d685 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1498,7 +1498,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() "set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES\n"; /* clang-format on */ std::vector dirs = - this->GetLinkedTargetDirectories(this->GetConfigName()); + this->GetLinkedTargetDirectories("Fortran", this->GetConfigName()); for (std::string const& d : dirs) { *this->InfoFileStream << " \"" << d << "/DependInfo.cmake\"\n"; } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 6887376..13782b0 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1675,7 +1675,7 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, Json::Value& tdi_linked_target_dirs = tdi["linked-target-dirs"] = Json::arrayValue; - for (std::string const& l : this->GetLinkedTargetDirectories(config)) { + for (std::string const& l : this->GetLinkedTargetDirectories(lang, config)) { tdi_linked_target_dirs.append(l); } -- cgit v0.12 From eed295fd8a84f4a4919acf2893053ad7e52e656d Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 1 Feb 2023 09:11:30 -0500 Subject: cmGlobalNinjaGenerator: require that dependency info files work Now that only targets expected to have information are listed, all `Modules.json` files should exist. --- Source/cmGlobalNinjaGenerator.cxx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index b80a06e..93aa30a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -2537,8 +2537,13 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( cmStrCat(linked_target_dir, '/', arg_lang, "Modules.json"); Json::Value ltm; cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary); + if (!ltmf) { + cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to open ", + ltmn, " for module information")); + return false; + } Json::Reader reader; - if (ltmf && !reader.parse(ltmf, ltm, false)) { + if (!reader.parse(ltmf, ltm, false)) { cmSystemTools::Error(cmStrCat("-E cmake_ninja_dyndep failed to parse ", linked_target_dir, reader.getFormattedErrorMessages())); -- cgit v0.12 From 13810dee17794c5d57845e5a7a0b38b4204dd734 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 1 Feb 2023 09:12:22 -0500 Subject: cmDependsFortran: require that dependency info files work Now that only targets expected to have information are listed, all `DependInfo.cmake` files should exist. --- Source/cmDependsFortran.cxx | 16 +++++++++++----- Source/cmDependsFortran.h | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 95f2a6b..718097f 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -150,7 +150,9 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, std::ostream& internalDepends) { // Prepare the module search process. - this->LocateModules(); + if (!this->LocateModules()) { + return false; + } // Get the directory in which stamp files will be stored. const std::string& stamp_dir = this->TargetDirectory; @@ -216,7 +218,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, return true; } -void cmDependsFortran::LocateModules() +bool cmDependsFortran::LocateModules() { // Collect the set of modules provided and required by all sources. using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap; @@ -234,7 +236,7 @@ void cmDependsFortran::LocateModules() // Short-circuit for simple targets. if (this->Internal->TargetRequires.empty()) { - return; + return true; } // Match modules provided by this target to those it requires. @@ -248,10 +250,14 @@ void cmDependsFortran::LocateModules() std::string targetDir = cmSystemTools::GetFilenamePath(i); std::string fname = targetDir + "/fortran.internal"; cmsys::ifstream fin(fname.c_str()); - if (fin) { - this->MatchRemoteModules(fin, targetDir); + if (!fin) { + cmSystemTools::Error(cmStrCat("-E cmake_depends failed to open ", fname, + " for module information")); + return false; } + this->MatchRemoteModules(fin, targetDir); } + return true; } void cmDependsFortran::MatchLocalModules() diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index a74db91..763f7bb 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -55,7 +55,7 @@ protected: std::ostream& internalDepends) override; // Find all the modules required by the target. - void LocateModules(); + bool LocateModules(); void MatchLocalModules(); void MatchRemoteModules(std::istream& fin, const std::string& stampDir); void ConsiderModule(const std::string& name, const std::string& stampDir); -- cgit v0.12