- add sources.
[platform/framework/web/crosswalk.git] / src / tools / gn / item_node.cc
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 #include "tools/gn/item_node.h"
6
7 #include <algorithm>
8
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "tools/gn/build_settings.h"
12 #include "tools/gn/item.h"
13
14 ItemNode::ItemNode(Item* i)
15     : state_(REFERENCED),
16       item_(i),
17       should_generate_(false) {
18   item_->set_item_node(this);
19 }
20
21 ItemNode::~ItemNode() {
22 }
23
24 bool ItemNode::SetShouldGenerate(const BuildSettings* build_settings,
25                                  Err* err) {
26   if (should_generate_)
27     return true;
28   should_generate_ = true;
29
30   if (state_ == DEFINED) {
31     if (!ScheduleDepsLoad(build_settings, err))
32       return false;
33   } else if (state_ == RESOLVED) {
34     // The item may have been resolved even if we didn't set the generate bit
35     // if all of its deps were loaded some other way. In this case, we need
36     // to run the closure which we skipped when it became resolved.
37     if (!resolved_closure_.is_null())
38       resolved_closure_.Run();
39   }
40
41   // Pass the generate bit to all deps.
42   for (ItemNodeMap::iterator i = direct_dependencies_.begin();
43        i != direct_dependencies_.end(); ++i) {
44     if (!i->first->SetShouldGenerate(build_settings, err))
45       return false;
46   }
47   return true;
48 }
49
50 bool ItemNode::AddDependency(const BuildSettings* build_settings,
51                              const LocationRange& specified_from_here,
52                              ItemNode* node,
53                              Err* err) {
54   // Can't add more deps once it's been defined.
55   DCHECK(state_ == REFERENCED);
56
57   if (direct_dependencies_.find(node) != direct_dependencies_.end())
58     return true;  // Already have this dep.
59
60   direct_dependencies_[node] = specified_from_here;
61
62   if (node->state() != RESOLVED) {
63     // Wire up the pending resolution info.
64     unresolved_dependencies_[node] = specified_from_here;
65     node->waiting_on_resolution_[this] = specified_from_here;
66   }
67
68   if (should_generate_) {
69     if (!node->SetShouldGenerate(build_settings, err))
70       return false;
71   }
72   return true;
73 }
74
75 void ItemNode::MarkDirectDependencyResolved(ItemNode* node) {
76   DCHECK(unresolved_dependencies_.find(node) != unresolved_dependencies_.end());
77   unresolved_dependencies_.erase(node);
78 }
79
80 void ItemNode::SwapOutWaitingDependencySet(ItemNodeMap* out_map) {
81   waiting_on_resolution_.swap(*out_map);
82   DCHECK(waiting_on_resolution_.empty());
83 }
84
85 bool ItemNode::SetDefined(const BuildSettings* build_settings, Err* err) {
86   DCHECK(state_ == REFERENCED);
87   state_ = DEFINED;
88
89   if (should_generate_)
90     return ScheduleDepsLoad(build_settings, err);
91   return true;
92 }
93
94 void ItemNode::SetResolved() {
95   DCHECK(state_ != RESOLVED);
96   state_ = RESOLVED;
97
98   if (should_generate_ && !resolved_closure_.is_null())
99     resolved_closure_.Run();
100 }
101
102 bool ItemNode::ScheduleDepsLoad(const BuildSettings* build_settings,
103                                 Err* err) {
104   DCHECK(state_ == DEFINED);
105   DCHECK(should_generate_);  // Shouldn't be requesting deps for ungenerated
106                              // items.
107
108   for (ItemNodeMap::const_iterator i = unresolved_dependencies_.begin();
109        i != unresolved_dependencies_.end(); ++i) {
110     Label toolchain_label = i->first->item()->label().GetToolchainLabel();
111     SourceDir dir_to_load = i->first->item()->label().dir();
112
113     if (!build_settings->toolchain_manager().ScheduleInvocationLocked(
114             i->second, toolchain_label, dir_to_load, err))
115       return false;
116   }
117
118   state_ = PENDING_DEPS;
119   return true;
120 }