From c4e296a60910c641a07695d1a9782912bce45d5c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Sep 2020 14:51:55 -0400 Subject: cmGlobalGenerator: Compute a global target ordering respecting dependencies Move this up from `cmGlobalXCodeGenerator`. It will be useful for all generators. --- Source/cmGlobalGenerator.cxx | 46 +++++++++++++++++++++++++++++++++++++++ Source/cmGlobalGenerator.h | 8 +++++++ Source/cmGlobalXCodeGenerator.cxx | 41 ++-------------------------------- Source/cmGlobalXCodeGenerator.h | 3 --- 4 files changed, 56 insertions(+), 42 deletions(-) diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 74360b8..8688b1b 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1471,6 +1471,7 @@ bool cmGlobalGenerator::Compute() if (!this->ComputeTargetDepends()) { return false; } + this->ComputeTargetOrder(); if (this->CheckTargetsForType()) { return false; @@ -1581,6 +1582,50 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } +std::vector +cmGlobalGenerator::GetLocalGeneratorTargetsInOrder(cmLocalGenerator* lg) const +{ + std::vector gts; + cm::append(gts, lg->GetGeneratorTargets()); + std::sort(gts.begin(), gts.end(), + [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { + return this->TargetOrderIndex.at(l) < + this->TargetOrderIndex.at(r); + }); + return gts; +} + +void cmGlobalGenerator::ComputeTargetOrder() +{ + size_t index = 0; + auto const& lgens = this->GetLocalGenerators(); + for (auto const& lgen : lgens) { + const auto& targets = lgen->GetGeneratorTargets(); + for (const auto& gt : targets) { + this->ComputeTargetOrder(gt.get(), index); + } + } + assert(index == this->TargetOrderIndex.size()); +} + +void cmGlobalGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, + size_t& index) +{ + std::map::value_type value(gt, 0); + auto insertion = this->TargetOrderIndex.insert(value); + if (!insertion.second) { + return; + } + auto entry = insertion.first; + + auto& deps = this->GetTargetDirectDepends(gt); + for (auto& d : deps) { + this->ComputeTargetOrder(d, index); + } + + entry->second = index++; +} + bool cmGlobalGenerator::QtAutoGen() { #ifndef CMAKE_BOOTSTRAP @@ -1760,6 +1805,7 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->GeneratorTargetSearchIndex.clear(); this->MakefileSearchIndex.clear(); this->LocalGeneratorSearchIndex.clear(); + this->TargetOrderIndex.clear(); this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 6ae7e15..478028e 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -4,6 +4,7 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include #include #include #include @@ -264,6 +265,9 @@ public: return this->LocalGenerators; } + std::vector GetLocalGeneratorTargetsInOrder( + cmLocalGenerator* lg) const; + cmMakefile* GetCurrentMakefile() const { return this->CurrentConfigureMakefile; @@ -613,6 +617,10 @@ private: // Its order is not deterministic. LocalGeneratorMap LocalGeneratorSearchIndex; + void ComputeTargetOrder(); + void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); + std::map TargetOrderIndex; + cmMakefile* TryCompileOuterMakefile; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index dbc95e6..2f27128 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -424,37 +424,6 @@ void cmGlobalXCodeGenerator::AddExtraIDETargets() } } -void cmGlobalXCodeGenerator::ComputeTargetOrder() -{ - size_t index = 0; - auto const& lgens = this->GetLocalGenerators(); - for (auto const& lgen : lgens) { - const auto& targets = lgen->GetGeneratorTargets(); - for (const auto& gt : targets) { - this->ComputeTargetOrder(gt.get(), index); - } - } - assert(index == this->TargetOrderIndex.size()); -} - -void cmGlobalXCodeGenerator::ComputeTargetOrder(cmGeneratorTarget const* gt, - size_t& index) -{ - std::map::value_type value(gt, 0); - auto insertion = this->TargetOrderIndex.insert(value); - if (!insertion.second) { - return; - } - auto entry = insertion.first; - - auto& deps = this->GetTargetDirectDepends(gt); - for (auto& d : deps) { - this->ComputeTargetOrder(d, index); - } - - entry->second = index++; -} - void cmGlobalXCodeGenerator::Generate() { this->cmGlobalGenerator::Generate(); @@ -462,8 +431,6 @@ void cmGlobalXCodeGenerator::Generate() return; } - this->ComputeTargetOrder(); - for (auto keyVal : this->ProjectMap) { cmLocalGenerator* root = keyVal.second[0]; @@ -1243,12 +1210,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector& targets) { this->SetCurrentLocalGenerator(gen); - std::vector gts; - cm::append(gts, this->CurrentLocalGenerator->GetGeneratorTargets()); - std::sort(gts.begin(), gts.end(), - [this](cmGeneratorTarget const* l, cmGeneratorTarget const* r) { - return this->TargetOrderIndex[l] < this->TargetOrderIndex[r]; - }); + std::vector gts = + this->GetLocalGeneratorTargetsInOrder(gen); for (auto gtgt : gts) { if (!this->CreateXCodeTarget(gtgt, targets)) { return false; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index c9f9926..c7524e8 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -115,8 +115,6 @@ public: protected: void AddExtraIDETargets() override; - void ComputeTargetOrder(); - void ComputeTargetOrder(cmGeneratorTarget const* gt, size_t& index); void Generate() override; private: @@ -303,7 +301,6 @@ private: std::string ObjectDirArch; std::string SystemName; std::string GeneratorToolset; - std::map TargetOrderIndex; std::vector EnabledLangs; std::map> CommandsVisited; -- cgit v0.12 From 69ee18163b9cf062d1306386b1bffceccdb24e3c Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 4 Sep 2020 08:37:18 -0400 Subject: cmLocalGhsMultiGenerator: Generate targets in dependency order Use the globally computed target ordering so that we generate all of a target's dependencies before generating the target itself. --- Source/cmLocalGhsMultiGenerator.cxx | 36 ++++++++---------------------------- Source/cmLocalGhsMultiGenerator.h | 5 ----- 2 files changed, 8 insertions(+), 33 deletions(-) diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index a23ad57..b223813 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -2,10 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmLocalGhsMultiGenerator.h" -#include #include - -#include +#include #include "cmGeneratorTarget.h" #include "cmGhsMultiTargetGenerator.h" @@ -29,34 +27,16 @@ std::string cmLocalGhsMultiGenerator::GetTargetDirectory( return dir; } -void cmLocalGhsMultiGenerator::GenerateTargetsDepthFirst( - cmGeneratorTarget* target, std::vector& remaining) -{ - if (!target->IsInBuildSystem()) { - return; - } - // Find this target in the list of remaining targets. - auto it = std::find(remaining.begin(), remaining.end(), target); - if (it == remaining.end()) { - // This target was already handled. - return; - } - // Remove this target from the list of remaining targets because - // we are handling it now. - *it = nullptr; - - cmGhsMultiTargetGenerator tg(target); - tg.Generate(); -} - void cmLocalGhsMultiGenerator::Generate() { - std::vector remaining; - cm::append(remaining, this->GetGeneratorTargets()); - for (auto& t : remaining) { - if (t) { - this->GenerateTargetsDepthFirst(t, remaining); + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem()) { + continue; } + + cmGhsMultiTargetGenerator tg(gt); + tg.Generate(); } } diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index 1b6f109..be32a94 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -4,7 +4,6 @@ #include #include -#include #include "cmLocalGenerator.h" @@ -37,8 +36,4 @@ public: void ComputeObjectFilenames( std::map& mapping, cmGeneratorTarget const* gt = nullptr) override; - -private: - void GenerateTargetsDepthFirst(cmGeneratorTarget* target, - std::vector& remaining); }; -- cgit v0.12 From 17aba9c9a6a73dfc110c026abfe1f16e13cb1bec Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Sep 2020 14:55:34 -0400 Subject: cmLocalUnixMakefileGenerator3: Generate targets in dependency order Use the globally computed target ordering so that we generate all of a target's dependencies before generating the target itself. --- Source/cmLocalUnixMakefileGenerator3.cxx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 9825f1c..c449450 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -100,12 +100,13 @@ void cmLocalUnixMakefileGenerator3::Generate() // Generate the rule files for each target. cmGlobalUnixMakefileGenerator3* gg = static_cast(this->GlobalGenerator); - for (const auto& target : this->GetGeneratorTargets()) { - if (!target->IsInBuildSystem()) { + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem()) { continue; } std::unique_ptr tg( - cmMakefileTargetGenerator::New(target.get())); + cmMakefileTargetGenerator::New(gt)); if (tg) { tg->WriteRuleFiles(); gg->RecordTargetProgress(tg.get()); -- cgit v0.12 From 48bf7192e702f9fdc99585e3d9d616091cc62974 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Sep 2020 15:17:18 -0400 Subject: cmLocalVisualStudio7Generator: Generate targets in dependency order Use the globally computed target ordering so that we generate all of a target's dependencies before generating the target itself. --- Source/cmLocalVisualStudio7Generator.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index fb10022..1eaf450 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -125,7 +125,8 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles() } // Get the set of targets in this directory. - const auto& tgts = this->GetGeneratorTargets(); + const auto& tgts = + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this); // Create the project file for each target. for (const auto& l : tgts) { @@ -135,7 +136,7 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles() // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace // so don't build a projectfile for it if (!l->GetProperty("EXTERNAL_MSPROJECT")) { - this->CreateSingleVCProj(l->GetName(), l.get()); + this->CreateSingleVCProj(l->GetName(), l); } } } -- cgit v0.12 From 152724274534def1126f97a28f0ce9f0e126a2b2 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Sep 2020 15:09:19 -0400 Subject: cmLocalVisualStudio10Generator: Simplify target ordering by dependencies Replace our own depth-first traversal with use of the global generator's computed target order that respects dependencies. --- Source/cmLocalVisualStudio10Generator.cxx | 29 +++++++---------------------- Source/cmLocalVisualStudio10Generator.h | 9 +++++---- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 6c7d6c6..9706f2e 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -66,29 +66,17 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator() { } -void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( - cmGeneratorTarget* target, std::vector& remaining) +void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target) { if (!target->IsInBuildSystem()) { return; } - // Find this target in the list of remaining targets. - auto it = std::find(remaining.begin(), remaining.end(), target); - if (it == remaining.end()) { - // This target was already handled. - return; - } - // Remove this target from the list of remaining targets because - // we are handling it now. - *it = nullptr; + auto& targetVisited = this->GetSourcesVisited(target); auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target); for (auto& d : deps) { - // FIXME: Revise CreateSingleVCProj so we do not have to drop `const` here. - auto dependee = const_cast(&*d); - GenerateTargetsDepthFirst(dependee, remaining); // Take the union of visited source files of custom commands - auto visited = GetSourcesVisited(dependee); - GetSourcesVisited(target).insert(visited.begin(), visited.end()); + auto depVisited = this->GetSourcesVisited(d); + targetVisited.insert(depVisited.begin(), depVisited.end()); } if (static_cast(this->GlobalGenerator) ->TargetIsFortranOnly(target)) { @@ -104,12 +92,9 @@ void cmLocalVisualStudio10Generator::GenerateTargetsDepthFirst( void cmLocalVisualStudio10Generator::Generate() { - std::vector remaining; - cm::append(remaining, this->GetGeneratorTargets()); - for (auto& t : remaining) { - if (t) { - this->GenerateTargetsDepthFirst(t, remaining); - } + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + this->GenerateTarget(gt); } this->WriteStampFiles(); } diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index 84216c8..a12247c 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -32,7 +32,8 @@ public: void ReadAndStoreExternalGUID(const std::string& name, const char* path) override; - std::set& GetSourcesVisited(cmGeneratorTarget* target) + std::set& GetSourcesVisited( + cmGeneratorTarget const* target) { return SourcesVisited[target]; }; @@ -42,8 +43,8 @@ protected: bool CustomCommandUseLocal() const override { return true; } private: - void GenerateTargetsDepthFirst(cmGeneratorTarget* target, - std::vector& remaining); + void GenerateTarget(cmGeneratorTarget* target); - std::map> SourcesVisited; + std::map> + SourcesVisited; }; -- cgit v0.12 From aea465793e9744fcda0c26dad14c0620b7448f14 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 3 Sep 2020 15:28:36 -0400 Subject: cmLocalVisualStudio7Generator: Consolidate target iteration Combine iteration with `cmLocalVisualStudio10Generator` and dispatch generation of each target with a virtual `GenerateTarget` method. --- Source/cmLocalVisualStudio10Generator.cxx | 14 +--------- Source/cmLocalVisualStudio10Generator.h | 6 +--- Source/cmLocalVisualStudio7Generator.cxx | 44 ++++++++---------------------- Source/cmLocalVisualStudio7Generator.h | 3 +- Source/cmVisualStudio10TargetGenerator.cxx | 4 --- 5 files changed, 14 insertions(+), 57 deletions(-) diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 9706f2e..98e9db9 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -68,9 +68,6 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator() void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target) { - if (!target->IsInBuildSystem()) { - return; - } auto& targetVisited = this->GetSourcesVisited(target); auto& deps = this->GlobalGenerator->GetTargetDirectDepends(target); for (auto& d : deps) { @@ -80,7 +77,7 @@ void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target) } if (static_cast(this->GlobalGenerator) ->TargetIsFortranOnly(target)) { - this->CreateSingleVCProj(target->GetName(), target); + this->cmLocalVisualStudio7Generator::GenerateTarget(target); } else { cmVisualStudio10TargetGenerator tg( target, @@ -90,15 +87,6 @@ void cmLocalVisualStudio10Generator::GenerateTarget(cmGeneratorTarget* target) } } -void cmLocalVisualStudio10Generator::Generate() -{ - for (cmGeneratorTarget* gt : - this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { - this->GenerateTarget(gt); - } - this->WriteStampFiles(); -} - void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID( const std::string& name, const char* path) { diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index a12247c..631132e 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -25,10 +25,6 @@ public: virtual ~cmLocalVisualStudio10Generator(); - /** - * Generate the makefile for this directory. - */ - void Generate() override; void ReadAndStoreExternalGUID(const std::string& name, const char* path) override; @@ -43,7 +39,7 @@ protected: bool CustomCommandUseLocal() const override { return true; } private: - void GenerateTarget(cmGeneratorTarget* target); + void GenerateTarget(cmGeneratorTarget* target) override; std::map> SourcesVisited; diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 1eaf450..1ebd5da 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -80,7 +80,15 @@ void cmLocalVisualStudio7Generator::AddHelperCommands() void cmLocalVisualStudio7Generator::Generate() { - this->WriteProjectFiles(); + // Create the project file for each target. + for (cmGeneratorTarget* gt : + this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this)) { + if (!gt->IsInBuildSystem() || gt->GetProperty("EXTERNAL_MSPROJECT")) { + continue; + } + this->GenerateTarget(gt); + } + this->WriteStampFiles(); } @@ -111,36 +119,6 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets() } } -// TODO -// for CommandLine= need to repleace quotes with " -// write out configurations -void cmLocalVisualStudio7Generator::WriteProjectFiles() -{ - // If not an in source build, then create the output directory - if (this->GetCurrentBinaryDirectory() != this->GetSourceDirectory()) { - if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) { - cmSystemTools::Error("Error creating directory " + - this->GetCurrentBinaryDirectory()); - } - } - - // Get the set of targets in this directory. - const auto& tgts = - this->GlobalGenerator->GetLocalGeneratorTargetsInOrder(this); - - // Create the project file for each target. - for (const auto& l : tgts) { - if (!l->IsInBuildSystem()) { - continue; - } - // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace - // so don't build a projectfile for it - if (!l->GetProperty("EXTERNAL_MSPROJECT")) { - this->CreateSingleVCProj(l->GetName(), l); - } - } -} - void cmLocalVisualStudio7Generator::WriteStampFiles() { // Touch a timestamp file used to determine when the project file is @@ -179,9 +157,9 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() } } -void cmLocalVisualStudio7Generator::CreateSingleVCProj( - const std::string& lname, cmGeneratorTarget* target) +void cmLocalVisualStudio7Generator::GenerateTarget(cmGeneratorTarget* target) { + std::string const& lname = target->GetName(); cmGlobalVisualStudioGenerator* gg = static_cast(this->GlobalGenerator); this->FortranProject = gg->TargetIsFortranOnly(target); diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index d76fc82..9ccd1a1 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -84,7 +84,7 @@ public: const char* path); protected: - void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt); + virtual void GenerateTarget(cmGeneratorTarget* target); private: using Options = cmVS7GeneratorOptions; @@ -92,7 +92,6 @@ private: std::string GetBuildTypeLinkerFlags(std::string rootLinkerFlags, const std::string& configName); void FixGlobalTargets(); - void WriteProjectFiles(); void WriteVCProjHeader(std::ostream& fout, const std::string& libName, cmGeneratorTarget* tgt, std::vector& sgs); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index dc61def..b5368cf 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -314,10 +314,6 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( void cmVisualStudio10TargetGenerator::Generate() { - // do not generate external ms projects - if (this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) { - return; - } const std::string ProjectFileExtension = computeProjectFileExtension(this->GeneratorTarget); if (ProjectFileExtension == ".vcxproj") { -- cgit v0.12