diff options
author | Martin Duffy <martin.duffy@kitware.com> | 2023-09-14 17:13:38 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2023-09-20 14:25:24 (GMT) |
commit | ec2ba29ac5e424cf0c52ba8ea5c2e3a4c2667d7a (patch) | |
tree | eee817eede0b5dec75baf45735268ffc7e5e4997 /Source | |
parent | 123cdf981661c8ae32335d4ae7e1ddcbcffd09cc (diff) | |
download | CMake-ec2ba29ac5e424cf0c52ba8ea5c2e3a4c2667d7a.zip CMake-ec2ba29ac5e424cf0c52ba8ea5c2e3a4c2667d7a.tar.gz CMake-ec2ba29ac5e424cf0c52ba8ea5c2e3a4c2667d7a.tar.bz2 |
Ninja: Allow compilation before generation of dependencies' private sources
This requires knowing when a generated header is public, which we can
model using file sets. Add policy CMP0154 to treat generated sources
as private by default in targets with file sets. Generated public
headers can be specified in public file sets.
Fixes: #24959
Issue: #15555
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmGlobalNinjaGenerator.cxx | 14 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.h | 6 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 94 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmPolicies.h | 9 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 5 | ||||
-rw-r--r-- | Source/cmTarget.h | 2 |
7 files changed, 117 insertions, 15 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 30305a1..7368a6a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1278,6 +1278,13 @@ std::string cmGlobalNinjaGenerator::OrderDependsTargetForTarget( return cmStrCat("cmake_object_order_depends_target_", target->GetName()); } +std::string cmGlobalNinjaGenerator::OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const +{ + return cmStrCat(this->OrderDependsTargetForTarget(target, config), + "_private"); +} + void cmGlobalNinjaGenerator::AppendTargetOutputs( cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends) const @@ -3176,3 +3183,10 @@ std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTarget( return cmStrCat("cmake_object_order_depends_target_", target->GetName(), '_', cmSystemTools::UpperCase(config)); } + +std::string cmGlobalNinjaMultiGenerator::OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const +{ + return cmStrCat(this->OrderDependsTargetForTarget(target, config), + "_private"); +} diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index c43e27c..56a922c 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -349,6 +349,9 @@ public: virtual std::string OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) const; + virtual std::string OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const; + void AppendTargetOutputs(cmGeneratorTarget const* target, cmNinjaDeps& outputs, const std::string& config, cmNinjaTargetDepends depends) const; @@ -738,6 +741,9 @@ public: std::string OrderDependsTargetForTarget( cmGeneratorTarget const* target, const std::string& config) const override; + std::string OrderDependsTargetForTargetPrivate( + cmGeneratorTarget const* target, const std::string& config) const override; + protected: bool OpenBuildFileStreams() override; void CloseBuildFileStreams() override; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 6187543..193cc0f 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -38,6 +38,7 @@ #include "cmNinjaNormalTargetGenerator.h" #include "cmNinjaUtilityTargetGenerator.h" #include "cmOutputConverter.h" +#include "cmPolicies.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" @@ -169,6 +170,13 @@ std::string cmNinjaTargetGenerator::OrderDependsTargetForTarget( this->GeneratorTarget, config); } +std::string cmNinjaTargetGenerator::OrderDependsTargetForTargetPrivate( + const std::string& config) +{ + return this->GetGlobalGenerator()->OrderDependsTargetForTargetPrivate( + this->GeneratorTarget, config); +} + // TODO: Most of the code is picked up from // void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink), // void cmMakefileTargetGenerator::WriteTargetLanguageFlags() @@ -1020,6 +1028,45 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( cmStrCat("Order-only phony target for ", this->GetTargetName()); build.Outputs.push_back(this->OrderDependsTargetForTarget(config)); + // Gather order-only dependencies on custom command outputs. + std::vector<std::string> ccouts; + std::vector<std::string> ccouts_private; + bool usePrivateGeneratedSources = false; + if (this->GeneratorTarget->Target->HasFileSets()) { + switch (this->GetGeneratorTarget()->GetPolicyStatusCMP0154()) { + case cmPolicies::WARN: + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + usePrivateGeneratedSources = true; + break; + } + } + for (cmCustomCommand const* cc : customCommands) { + cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); + const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); + const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); + ccouts.insert(ccouts.end(), ccoutputs.begin(), ccoutputs.end()); + ccouts.insert(ccouts.end(), ccbyproducts.begin(), ccbyproducts.end()); + if (usePrivateGeneratedSources) { + auto it = ccouts.begin(); + while (it != ccouts.end()) { + cmFileSet const* fileset = + this->GeneratorTarget->GetFileSetForSource( + config, this->Makefile->GetOrCreateGeneratedSource(*it)); + if (fileset && + fileset->GetVisibility() != cmFileSetVisibility::Private) { + ++it; + } else { + ccouts_private.push_back(*it); + it = ccouts.erase(it); + } + } + } + } + cmNinjaDeps& orderOnlyDeps = build.OrderOnlyDeps; this->GetLocalGenerator()->AppendTargetDepends( this->GeneratorTarget, orderOnlyDeps, config, fileConfig, @@ -1029,17 +1076,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( cm::append(orderOnlyDeps, this->Configs[config].ExtraFiles); // Add order-only dependencies on custom command outputs. - for (cmCustomCommand const* cc : customCommands) { - cmCustomCommandGenerator ccg(*cc, config, this->GetLocalGenerator()); - const std::vector<std::string>& ccoutputs = ccg.GetOutputs(); - const std::vector<std::string>& ccbyproducts = ccg.GetByproducts(); - std::transform(ccoutputs.begin(), ccoutputs.end(), - std::back_inserter(orderOnlyDeps), - this->MapToNinjaPath()); - std::transform(ccbyproducts.begin(), ccbyproducts.end(), - std::back_inserter(orderOnlyDeps), - this->MapToNinjaPath()); - } + std::transform(ccouts.begin(), ccouts.end(), + std::back_inserter(orderOnlyDeps), this->MapToNinjaPath()); std::sort(orderOnlyDeps.begin(), orderOnlyDeps.end()); orderOnlyDeps.erase( @@ -1060,8 +1098,32 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig), build); - } + // Add order-only dependencies on custom command outputs that are + // private to this target. + this->HasPrivateGeneratedSources = !ccouts_private.empty(); + if (this->HasPrivateGeneratedSources) { + cmNinjaBuild buildPrivate("phony"); + cmNinjaDeps& orderOnlyDepsPrivate = buildPrivate.OrderOnlyDeps; + orderOnlyDepsPrivate.push_back( + this->OrderDependsTargetForTarget(config)); + + buildPrivate.Outputs.push_back( + this->OrderDependsTargetForTargetPrivate(config)); + + std::transform(ccouts_private.begin(), ccouts_private.end(), + std::back_inserter(orderOnlyDepsPrivate), + this->MapToNinjaPath()); + + std::sort(orderOnlyDepsPrivate.begin(), orderOnlyDepsPrivate.end()); + orderOnlyDepsPrivate.erase( + std::unique(orderOnlyDepsPrivate.begin(), orderOnlyDepsPrivate.end()), + orderOnlyDepsPrivate.end()); + + this->GetGlobalGenerator()->WriteBuild( + this->GetImplFileStream(fileConfig), buildPrivate); + } + } { std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, config); @@ -1388,7 +1450,13 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->MapToNinjaPath()); } - objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config)); + if (this->HasPrivateGeneratedSources) { + objBuild.OrderOnlyDeps.push_back( + this->OrderDependsTargetForTargetPrivate(config)); + } else { + objBuild.OrderOnlyDeps.push_back( + this->OrderDependsTargetForTarget(config)); + } // If the source file is GENERATED and does not have a custom command // (either attached to this source file or another one), assume that one of diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index d41d86e..3f56113 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -81,6 +81,7 @@ protected: bool CompileWithDefines(std::string const& lang) const; std::string OrderDependsTargetForTarget(const std::string& config); + std::string OrderDependsTargetForTargetPrivate(const std::string& config); std::string ComputeOrderDependsForTarget(); @@ -228,6 +229,7 @@ protected: private: cmLocalNinjaGenerator* LocalGenerator; + bool HasPrivateGeneratedSources = false; struct ScanningFiles { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 26c141d..e894073 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -465,7 +465,11 @@ class cmMakefile; "file(REAL_PATH) resolves symlinks before collapsing ../ components.", 3, \ 28, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0153, "The exec_program command should not be called.", \ - 3, 28, 0, cmPolicies::WARN) + 3, 28, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0154, \ + "Generated files are private by default in targets using file sets.", 3, \ + 28, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -503,7 +507,8 @@ class cmMakefile; F(CMP0113) \ F(CMP0119) \ F(CMP0131) \ - F(CMP0142) + F(CMP0142) \ + F(CMP0154) #define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \ F(CMP0116) \ diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ace93e8..abbf29e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -3201,6 +3201,11 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const return result; } +bool cmTarget::HasFileSets() const +{ + return !this->impl->FileSets.empty(); +} + bool cmTargetInternals::CheckImportedLibName(std::string const& prop, std::string const& value) const { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index b77ea0c..584856a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -321,6 +321,8 @@ public: static std::string GetFileSetsPropertyName(const std::string& type); static std::string GetInterfaceFileSetsPropertyName(const std::string& type); + bool HasFileSets() const; + private: template <typename ValueType> void StoreProperty(const std::string& prop, ValueType value); |