summaryrefslogtreecommitdiff
path: root/Source/cmComputeTargetDepends.h
blob: 3ed041bfa97c2987efec273a5d42ab3fa9c9fc29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#pragma once

#include "cmConfigure.h" // IWYU pragma: keep

#include <cstddef>
#include <map>
#include <set>
#include <string>
#include <vector>

#include "cmGraphAdjacencyList.h"

class cmComputeComponentGraph;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmLinkItem;
class cmListFileBacktrace;
class cmSourceFile;
class cmTargetDependSet;

/** \class cmComputeTargetDepends
 * \brief Compute global interdependencies among targets.
 *
 * Static libraries may form cycles in the target dependency graph.
 * This class evaluates target dependencies globally and adjusts them
 * to remove cycles while preserving a safe build order.
 */
class cmComputeTargetDepends
{
public:
  cmComputeTargetDepends(cmGlobalGenerator* gg);
  ~cmComputeTargetDepends();

  bool Compute();

  std::vector<cmGeneratorTarget const*> const& GetTargets() const
  {
    return this->Targets;
  }
  void GetTargetDirectDepends(cmGeneratorTarget const* t,
                              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(size_t depender_index);
  void AddTargetDepend(size_t depender_index, cmLinkItem const& dependee_name,
                       bool linking, bool cross);
  void AddTargetDepend(size_t depender_index,
                       cmGeneratorTarget const* dependee,
                       cmListFileBacktrace const& dependee_backtrace,
                       bool linking, bool cross);
  void CollectSideEffects();
  void CollectSideEffectsForTarget(std::set<size_t>& visited,
                                   size_t depender_index);
  void ComputeIntermediateGraph();
  void OptimizeLinkDependencies(cmGeneratorTarget const* gt,
                                cmGraphEdgeList& outputEdges,
                                cmGraphEdgeList const& inputEdges);
  bool ComputeFinalDepends(cmComputeComponentGraph const& ccg);
  void AddInterfaceDepends(size_t depender_index,
                           cmLinkItem const& dependee_name,
                           const std::string& config,
                           std::set<cmLinkItem>& emitted);
  void AddInterfaceDepends(size_t depender_index,
                           cmGeneratorTarget const* dependee,
                           cmListFileBacktrace const& dependee_backtrace,
                           const std::string& config,
                           std::set<cmLinkItem>& emitted);
  void AddObjectDepends(size_t depender_index, cmSourceFile const* o,
                        std::set<cmLinkItem>& emitted);
  cmGlobalGenerator* GlobalGenerator;
  bool DebugMode;
  bool NoCycles;

  // Collect all targets.
  std::vector<cmGeneratorTarget const*> Targets;
  std::map<cmGeneratorTarget const*, size_t> TargetIndex;

  // Represent the target dependency graph.  The entry at each
  // top-level index corresponds to a depender whose dependencies are
  // listed.
  using NodeList = cmGraphNodeList;
  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,
                         const std::string& name);
  bool CheckComponents(cmComputeComponentGraph const& ccg);
  void ComplainAboutBadComponent(cmComputeComponentGraph const& ccg, size_t c,
                                 bool strong = false);

  std::vector<size_t> ComponentHead;
  std::vector<size_t> ComponentTail;
  bool IntraComponent(std::vector<size_t> const& cmap, size_t c, size_t i,
                      size_t* head, std::set<size_t>& emitted,
                      std::set<size_t>& visited);
};