1// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef TOOLS_GN_BUILDER_H_
6#define TOOLS_GN_BUILDER_H_
7
8#include "base/basictypes.h"
9#include "base/callback.h"
10#include "base/containers/hash_tables.h"
11#include "base/memory/ref_counted.h"
12#include "tools/gn/builder_record.h"
13#include "tools/gn/label.h"
14#include "tools/gn/label_ptr.h"
15#include "tools/gn/unique_vector.h"
16
17class Config;
18class Err;
19class Loader;
20class ParseNode;
21
22class Builder : public base::RefCountedThreadSafe<Builder> {
23 public:
24  typedef base::Callback<void(const BuilderRecord*)> ResolvedCallback;
25
26  Builder(Loader* loader);
27
28  // The resolved callback is called whenever a target has been resolved. This
29  // will be executed only on the main thread.
30  void set_resolved_callback(const ResolvedCallback& cb) {
31    resolved_callback_ = cb;
32  }
33
34  Loader* loader() const { return loader_; }
35
36  void ItemDefined(scoped_ptr<Item> item);
37
38  // Returns NULL if there is not a thing with the corresponding label.
39  const Item* GetItem(const Label& label) const;
40  const Toolchain* GetToolchain(const Label& label) const;
41
42  std::vector<const BuilderRecord*> GetAllRecords() const;
43
44  // Returns targets which should be generated and which are defined.
45  std::vector<const Target*> GetAllResolvedTargets() const;
46
47  // Returns the record for the given label, or NULL if it doesn't exist.
48  // Mostly used for unit tests.
49  const BuilderRecord* GetRecord(const Label& label) const;
50  BuilderRecord* GetRecord(const Label& label);
51
52  // If there are any undefined references, returns false and sets the error.
53  bool CheckForBadItems(Err* err) const;
54
55 private:
56  friend class base::RefCountedThreadSafe<Builder>;
57
58  virtual ~Builder();
59
60  bool TargetDefined(BuilderRecord* record, Err* err);
61  bool ToolchainDefined(BuilderRecord* record, Err* err);
62
63  // Returns the record associated with the given label. This function checks
64  // that if we already have references for it, the type matches. If no record
65  // exists yet, a new one will be created.
66  //
67  // If any of the conditions fail, the return value will be null and the error
68  // will be set. request_from is used as the source of the error.
69  BuilderRecord* GetOrCreateRecordOfType(const Label& label,
70                                         const ParseNode* request_from,
71                                         BuilderRecord::ItemType type,
72                                         Err* err);
73
74  // Returns the record associated with the given label. This function checks
75  // that it's already been resolved to the correct type.
76  //
77  // If any of the conditions fail, the return value will be null and the error
78  // will be set. request_from is used as the source of the error.
79  BuilderRecord* GetResolvedRecordOfType(const Label& label,
80                                         const ParseNode* request_from,
81                                         BuilderRecord::ItemType type,
82                                         Err* err);
83
84  bool AddDeps(BuilderRecord* record,
85               const LabelConfigVector& configs,
86               Err* err);
87  bool AddDeps(BuilderRecord* record,
88               const UniqueVector<LabelConfigPair>& configs,
89               Err* err);
90  bool AddDeps(BuilderRecord* record,
91               const LabelTargetVector& targets,
92               Err* err);
93  bool AddToolchainDep(BuilderRecord* record,
94                       const Target* target,
95                       Err* err);
96
97  // Given a target, sets the "should generate" bit and pushes it through the
98  // dependency tree. Any time the bit it set, we ensure that the given item is
99  // scheduled to be loaded.
100  //
101  // If the force flag is set, we'll ignore the current state of the record's
102  // should_generate flag, and set it on the dependents every time. This is
103  // used when defining a target: the "should generate" may have been set
104  // before the item was defined (if it is required by something that is
105  // required). In this case, we need to re-push the "should generate" flag
106  // to the item's dependencies.
107  void RecursiveSetShouldGenerate(BuilderRecord* record, bool force);
108
109  void ScheduleItemLoadIfNecessary(BuilderRecord* record);
110
111  // This takes a BuilderRecord with resolved depdencies, and fills in the
112  // target's Label*Vectors with the resolved pointers.
113  bool ResolveItem(BuilderRecord* record, Err* err);
114
115  // Fills in the pointers in the given vector based on the labels. We assume
116  // that everything should be resolved by this point, so will return an error
117  // if anything isn't found or if the type doesn't match.
118  bool ResolveDeps(LabelTargetVector* deps, Err* err);
119  bool ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err);
120  bool ResolveForwardDependentConfigs(Target* target, Err* err);
121  bool ResolveToolchain(Target* target, Err* err);
122
123  // Given a list of unresolved records, tries to find any circular
124  // dependencies and returns the string describing the problem. If no circular
125  // deps were found, returns the empty string.
126  std::string CheckForCircularDependencies(
127      const std::vector<const BuilderRecord*>& bad_records) const;
128
129  // Non owning pointer.
130  Loader* loader_;
131
132  // Owning pointers.
133  typedef base::hash_map<Label, BuilderRecord*> RecordMap;
134  RecordMap records_;
135
136  ResolvedCallback resolved_callback_;
137
138  DISALLOW_COPY_AND_ASSIGN(Builder);
139};
140
141#endif  // TOOLS_GN_BUILDER_H_
142