summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/cmComputeTargetDepends.cxx163
-rw-r--r--Source/cmComputeTargetDepends.h19
-rw-r--r--Source/cmGeneratorTarget.cxx31
-rw-r--r--Source/cmGeneratorTarget.h6
-rw-r--r--Source/cmTarget.cxx1
5 files changed, 212 insertions, 8 deletions
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index e717f71..1f22ce6 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -17,10 +17,12 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
+#include "cmProperty.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
@@ -115,19 +117,32 @@ bool cmComputeTargetDepends::Compute()
if (this->DebugMode) {
this->DisplayGraph(this->InitialGraph, "initial");
}
+ cmComputeComponentGraph ccg1(this->InitialGraph);
+ ccg1.Compute();
+ if (!this->CheckComponents(ccg1)) {
+ return false;
+ }
+
+ // Compute the intermediate graph.
+ this->CollectSideEffects();
+ this->ComputeIntermediateGraph();
+ if (this->DebugMode) {
+ this->DisplaySideEffects();
+ this->DisplayGraph(this->IntermediateGraph, "intermediate");
+ }
// Identify components.
- cmComputeComponentGraph ccg(this->InitialGraph);
- ccg.Compute();
+ cmComputeComponentGraph ccg2(this->IntermediateGraph);
+ ccg2.Compute();
if (this->DebugMode) {
- this->DisplayComponents(ccg);
+ this->DisplayComponents(ccg2, "intermediate");
}
- if (!this->CheckComponents(ccg)) {
+ if (!this->CheckComponents(ccg2)) {
return false;
}
// Compute the final dependency graph.
- if (!this->ComputeFinalDepends(ccg)) {
+ if (!this->ComputeFinalDepends(ccg2)) {
return false;
}
if (this->DebugMode) {
@@ -382,6 +397,111 @@ void cmComputeTargetDepends::AddTargetDepend(
}
}
+void cmComputeTargetDepends::CollectSideEffects()
+{
+ this->SideEffects.resize(0);
+ this->SideEffects.resize(this->InitialGraph.size());
+
+ int n = static_cast<int>(this->InitialGraph.size());
+ std::set<int> visited;
+ for (int i = 0; i < n; ++i) {
+ this->CollectSideEffectsForTarget(visited, i);
+ }
+}
+
+void cmComputeTargetDepends::CollectSideEffectsForTarget(
+ std::set<int>& visited, int depender_index)
+{
+ if (!visited.count(depender_index)) {
+ auto& se = this->SideEffects[depender_index];
+ visited.insert(depender_index);
+ this->Targets[depender_index]->AppendCustomCommandSideEffects(
+ se.CustomCommandSideEffects);
+ this->Targets[depender_index]->AppendLanguageSideEffects(
+ se.LanguageSideEffects);
+
+ for (auto const& edge : this->InitialGraph[depender_index]) {
+ this->CollectSideEffectsForTarget(visited, edge);
+ auto const& dse = this->SideEffects[edge];
+ se.CustomCommandSideEffects.insert(dse.CustomCommandSideEffects.cbegin(),
+ dse.CustomCommandSideEffects.cend());
+ for (auto const& it : dse.LanguageSideEffects) {
+ se.LanguageSideEffects[it.first].insert(it.second.cbegin(),
+ it.second.cend());
+ }
+ }
+ }
+}
+
+void cmComputeTargetDepends::ComputeIntermediateGraph()
+{
+ this->IntermediateGraph.resize(0);
+ this->IntermediateGraph.resize(this->InitialGraph.size());
+
+ int n = static_cast<int>(this->InitialGraph.size());
+ for (int i = 0; i < n; ++i) {
+ auto const& initialEdges = this->InitialGraph[i];
+ auto& intermediateEdges = this->IntermediateGraph[i];
+ cmGeneratorTarget const* gt = this->Targets[i];
+ if (gt->GetType() != cmStateEnums::STATIC_LIBRARY &&
+ gt->GetType() != cmStateEnums::OBJECT_LIBRARY) {
+ intermediateEdges = initialEdges;
+ } else {
+ if (cmProp optimizeDependencies =
+ gt->GetProperty("OPTIMIZE_DEPENDENCIES")) {
+ if (cmIsOn(optimizeDependencies)) {
+ this->OptimizeLinkDependencies(gt, intermediateEdges, initialEdges);
+ } else {
+ intermediateEdges = initialEdges;
+ }
+ } else {
+ intermediateEdges = initialEdges;
+ }
+ }
+ }
+}
+
+void cmComputeTargetDepends::OptimizeLinkDependencies(
+ cmGeneratorTarget const* gt, cmGraphEdgeList& outputEdges,
+ cmGraphEdgeList const& inputEdges)
+{
+ std::set<int> emitted;
+ for (auto const& edge : inputEdges) {
+ if (edge.IsStrong()) {
+ // Preserve strong edges
+ outputEdges.push_back(edge);
+ } else {
+ auto const& dse = this->SideEffects[edge];
+
+ // Add edges that have custom command side effects
+ for (cmGeneratorTarget const* dep : dse.CustomCommandSideEffects) {
+ auto index = this->TargetIndex[dep];
+ if (!emitted.count(index)) {
+ emitted.insert(index);
+ outputEdges.push_back(
+ cmGraphEdge(index, false, edge.IsCross(), edge.GetBacktrace()));
+ }
+ }
+
+ // Add edges that have language side effects for languages we
+ // care about
+ for (auto const& lang : gt->GetAllConfigCompileLanguages()) {
+ auto it = dse.LanguageSideEffects.find(lang);
+ if (it != dse.LanguageSideEffects.end()) {
+ for (cmGeneratorTarget const* dep : it->second) {
+ auto index = this->TargetIndex[dep];
+ if (!emitted.count(index)) {
+ emitted.insert(index);
+ outputEdges.push_back(cmGraphEdge(index, false, edge.IsCross(),
+ edge.GetBacktrace()));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
const std::string& name)
{
@@ -402,10 +522,39 @@ void cmComputeTargetDepends::DisplayGraph(Graph const& graph,
fprintf(stderr, "\n");
}
+void cmComputeTargetDepends::DisplaySideEffects()
+{
+ fprintf(stderr, "The side effects are:\n");
+ int n = static_cast<int>(SideEffects.size());
+ for (int depender_index = 0; depender_index < n; ++depender_index) {
+ cmGeneratorTarget const* depender = this->Targets[depender_index];
+ fprintf(stderr, "target %d is [%s]\n", depender_index,
+ depender->GetName().c_str());
+ if (!this->SideEffects[depender_index].CustomCommandSideEffects.empty()) {
+ fprintf(stderr, " custom commands\n");
+ for (auto const* gt :
+ this->SideEffects[depender_index].CustomCommandSideEffects) {
+ fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt],
+ gt->GetName().c_str());
+ }
+ }
+ for (auto const& it :
+ this->SideEffects[depender_index].LanguageSideEffects) {
+ fprintf(stderr, " language %s\n", it.first.c_str());
+ for (auto const* gt : it.second) {
+ fprintf(stderr, " from target %d [%s]\n", this->TargetIndex[gt],
+ gt->GetName().c_str());
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
void cmComputeTargetDepends::DisplayComponents(
- cmComputeComponentGraph const& ccg)
+ cmComputeComponentGraph const& ccg, const std::string& name)
{
- fprintf(stderr, "The strongly connected components are:\n");
+ fprintf(stderr, "The strongly connected components for the %s graph are:\n",
+ name.c_str());
std::vector<NodeList> const& components = ccg.GetComponents();
int n = static_cast<int>(components.size());
for (int c = 0; c < n; ++c) {
diff --git a/Source/cmComputeTargetDepends.h b/Source/cmComputeTargetDepends.h
index e0d625f..277521d 100644
--- a/Source/cmComputeTargetDepends.h
+++ b/Source/cmComputeTargetDepends.h
@@ -42,6 +42,13 @@ public:
cmTargetDependSet& deps);
private:
+ struct TargetSideEffects
+ {
+ std::set<cmGeneratorTarget const*> CustomCommandSideEffects;
+ std::map<std::string, std::set<cmGeneratorTarget const*>>
+ LanguageSideEffects;
+ };
+
void CollectTargets();
void CollectDepends();
void CollectTargetDepends(int depender_index);
@@ -50,6 +57,12 @@ private:
void AddTargetDepend(int depender_index, cmGeneratorTarget const* dependee,
cmListFileBacktrace const& dependee_backtrace,
bool linking, bool cross);
+ void CollectSideEffects();
+ void CollectSideEffectsForTarget(std::set<int>& visited, int depender_index);
+ void ComputeIntermediateGraph();
+ void OptimizeLinkDependencies(cmGeneratorTarget const* gt,
+ cmGraphEdgeList& outputEdges,
+ cmGraphEdgeList const& inputEdges);
bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
void AddInterfaceDepends(int depender_index, cmLinkItem const& dependee_name,
const std::string& config,
@@ -74,11 +87,15 @@ private:
using EdgeList = cmGraphEdgeList;
using Graph = cmGraphAdjacencyList;
Graph InitialGraph;
+ Graph IntermediateGraph;
Graph FinalGraph;
+ std::vector<TargetSideEffects> SideEffects;
void DisplayGraph(Graph const& graph, const std::string& name);
+ void DisplaySideEffects();
// Deal with connected components.
- void DisplayComponents(cmComputeComponentGraph const& ccg);
+ void DisplayComponents(cmComputeComponentGraph const& ccg,
+ const std::string& name);
bool CheckComponents(cmComputeComponentGraph const& ccg);
void ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, int c,
bool strong = false);
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 889ad7c..9611e14 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1084,6 +1084,37 @@ std::vector<cmCustomCommand> const& cmGeneratorTarget::GetPostBuildCommands()
return this->Target->GetPostBuildCommands();
}
+void cmGeneratorTarget::AppendCustomCommandSideEffects(
+ std::set<cmGeneratorTarget const*>& sideEffects) const
+{
+ if (!this->GetPreBuildCommands().empty() ||
+ !this->GetPreLinkCommands().empty() ||
+ !this->GetPostBuildCommands().empty()) {
+ sideEffects.insert(this);
+ } else {
+ for (auto const& source : this->GetAllConfigSources()) {
+ if (source.Source->GetCustomCommand() != nullptr) {
+ sideEffects.insert(this);
+ break;
+ }
+ }
+ }
+}
+
+void cmGeneratorTarget::AppendLanguageSideEffects(
+ std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects) const
+{
+ static const std::set<cm::string_view> LANGS_WITH_NO_SIDE_EFFECTS = {
+ "C"_s, "CXX"_s, "OBJC"_s, "OBJCXX"_s, "ASM"_s, "CUDA"_s,
+ };
+
+ for (auto const& lang : this->GetAllConfigCompileLanguages()) {
+ if (!LANGS_WITH_NO_SIDE_EFFECTS.count(lang)) {
+ sideEffects[lang].insert(this);
+ }
+ }
+}
+
bool cmGeneratorTarget::IsInBuildSystem() const
{
if (this->IsImported()) {
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 4a03f65..69c5faf 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -55,6 +55,12 @@ public:
std::vector<cmCustomCommand> const& GetPreLinkCommands() const;
std::vector<cmCustomCommand> const& GetPostBuildCommands() const;
+ void AppendCustomCommandSideEffects(
+ std::set<cmGeneratorTarget const*>& sideEffects) const;
+ void AppendLanguageSideEffects(
+ std::map<std::string, std::set<cmGeneratorTarget const*>>& sideEffects)
+ const;
+
#define DECLARE_TARGET_POLICY(POLICY) \
cmPolicies::PolicyStatus GetPolicyStatus##POLICY() const \
{ \
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 51b4e9e..60416a3 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -373,6 +373,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
initProp("VS_JUST_MY_CODE_DEBUGGING");
initProp("DISABLE_PRECOMPILE_HEADERS");
initProp("UNITY_BUILD");
+ initProp("OPTIMIZE_DEPENDENCIES");
initPropValue("UNITY_BUILD_BATCH_SIZE", "8");
initPropValue("UNITY_BUILD_MODE", "BATCH");
initPropValue("PCH_WARN_INVALID", "ON");