summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorMartin Duffy <martin.duffy@kitware.com>2023-09-14 17:13:38 (GMT)
committerBrad King <brad.king@kitware.com>2023-09-20 14:25:24 (GMT)
commitec2ba29ac5e424cf0c52ba8ea5c2e3a4c2667d7a (patch)
treeeee817eede0b5dec75baf45735268ffc7e5e4997 /Source
parent123cdf981661c8ae32335d4ae7e1ddcbcffd09cc (diff)
downloadCMake-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.cxx14
-rw-r--r--Source/cmGlobalNinjaGenerator.h6
-rw-r--r--Source/cmNinjaTargetGenerator.cxx94
-rw-r--r--Source/cmNinjaTargetGenerator.h2
-rw-r--r--Source/cmPolicies.h9
-rw-r--r--Source/cmTarget.cxx5
-rw-r--r--Source/cmTarget.h2
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);