OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "tools/gn/loader.h" | 5 #include "tools/gn/loader.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "tools/gn/build_settings.h" | 10 #include "tools/gn/build_settings.h" |
11 #include "tools/gn/err.h" | 11 #include "tools/gn/err.h" |
12 #include "tools/gn/filesystem_utils.h" | 12 #include "tools/gn/filesystem_utils.h" |
13 #include "tools/gn/input_file_manager.h" | 13 #include "tools/gn/input_file_manager.h" |
14 #include "tools/gn/parse_tree.h" | 14 #include "tools/gn/parse_tree.h" |
15 #include "tools/gn/scheduler.h" | 15 #include "tools/gn/scheduler.h" |
16 #include "tools/gn/scope_per_file_provider.h" | 16 #include "tools/gn/scope_per_file_provider.h" |
17 #include "tools/gn/settings.h" | 17 #include "tools/gn/settings.h" |
18 #include "tools/gn/source_dir.h" | 18 #include "tools/gn/source_dir.h" |
19 #include "tools/gn/source_file.h" | 19 #include "tools/gn/source_file.h" |
20 #include "tools/gn/trace.h" | 20 #include "tools/gn/trace.h" |
21 | 21 |
| 22 namespace { |
| 23 |
| 24 struct SourceFileAndOrigin { |
| 25 SourceFileAndOrigin(const SourceFile& f, const LocationRange& o) |
| 26 : file(f), |
| 27 origin(o) { |
| 28 } |
| 29 |
| 30 SourceFile file; |
| 31 LocationRange origin; |
| 32 }; |
| 33 |
| 34 } // namespace |
| 35 |
22 // Identifies one time a file is loaded in a given toolchain so we don't load | 36 // Identifies one time a file is loaded in a given toolchain so we don't load |
23 // it more than once. | 37 // it more than once. |
24 struct LoaderImpl::LoadID { | 38 struct LoaderImpl::LoadID { |
25 LoadID() {} | 39 LoadID() {} |
26 LoadID(const SourceFile& f, const Label& tc_name) | 40 LoadID(const SourceFile& f, const Label& tc_name) |
27 : file(f), | 41 : file(f), |
28 toolchain_name(tc_name) { | 42 toolchain_name(tc_name) { |
29 } | 43 } |
30 | 44 |
31 bool operator<(const LoadID& other) const { | 45 bool operator<(const LoadID& other) const { |
(...skipping 21 matching lines...) Expand all Loading... |
53 is_config_loaded(false) { | 67 is_config_loaded(false) { |
54 settings.set_default_toolchain_label(default_toolchain_label); | 68 settings.set_default_toolchain_label(default_toolchain_label); |
55 settings.set_toolchain_label(toolchain_label); | 69 settings.set_toolchain_label(toolchain_label); |
56 } | 70 } |
57 | 71 |
58 Settings settings; | 72 Settings settings; |
59 | 73 |
60 bool is_toolchain_loaded; | 74 bool is_toolchain_loaded; |
61 bool is_config_loaded; | 75 bool is_config_loaded; |
62 | 76 |
63 std::vector<SourceFile> waiting_on_me; | 77 std::vector<SourceFileAndOrigin> waiting_on_me; |
64 }; | 78 }; |
65 | 79 |
66 // ----------------------------------------------------------------------------- | 80 // ----------------------------------------------------------------------------- |
67 | 81 |
68 const void* Loader::kDefaultToolchainKey = &kDefaultToolchainKey; | 82 const void* Loader::kDefaultToolchainKey = &kDefaultToolchainKey; |
69 | 83 |
70 Loader::Loader() { | 84 Loader::Loader() { |
71 } | 85 } |
72 | 86 |
73 Loader::~Loader() { | 87 Loader::~Loader() { |
74 } | 88 } |
75 | 89 |
76 void Loader::Load(const Label& label) { | 90 void Loader::Load(const Label& label, const LocationRange& origin) { |
77 Load(BuildFileForLabel(label), label.GetToolchainLabel()); | 91 Load(BuildFileForLabel(label), origin, label.GetToolchainLabel()); |
78 } | 92 } |
79 | 93 |
80 // static | 94 // static |
81 SourceFile Loader::BuildFileForLabel(const Label& label) { | 95 SourceFile Loader::BuildFileForLabel(const Label& label) { |
82 return SourceFile(label.dir().value() + "BUILD.gn"); | 96 return SourceFile(label.dir().value() + "BUILD.gn"); |
83 } | 97 } |
84 | 98 |
85 // ----------------------------------------------------------------------------- | 99 // ----------------------------------------------------------------------------- |
86 | 100 |
87 LoaderImpl::LoaderImpl(const BuildSettings* build_settings) | 101 LoaderImpl::LoaderImpl(const BuildSettings* build_settings) |
88 : main_loop_(base::MessageLoop::current()), | 102 : main_loop_(base::MessageLoop::current()), |
89 pending_loads_(0), | 103 pending_loads_(0), |
90 build_settings_(build_settings) { | 104 build_settings_(build_settings) { |
91 } | 105 } |
92 | 106 |
93 LoaderImpl::~LoaderImpl() { | 107 LoaderImpl::~LoaderImpl() { |
94 STLDeleteContainerPairSecondPointers(toolchain_records_.begin(), | 108 STLDeleteContainerPairSecondPointers(toolchain_records_.begin(), |
95 toolchain_records_.end()); | 109 toolchain_records_.end()); |
96 } | 110 } |
97 | 111 |
98 void LoaderImpl::Load(const SourceFile& file, | 112 void LoaderImpl::Load(const SourceFile& file, |
99 const Label& in_toolchain_name) { | 113 const LocationRange& origin, |
| 114 const Label& in_toolchain_name) { |
100 const Label& toolchain_name = in_toolchain_name.is_null() | 115 const Label& toolchain_name = in_toolchain_name.is_null() |
101 ? default_toolchain_label_ : in_toolchain_name; | 116 ? default_toolchain_label_ : in_toolchain_name; |
102 LoadID load_id(file, toolchain_name); | 117 LoadID load_id(file, toolchain_name); |
103 if (!invocations_.insert(load_id).second) | 118 if (!invocations_.insert(load_id).second) |
104 return; // Already in set, so this file was already loaded or schedulerd. | 119 return; // Already in set, so this file was already loaded or schedulerd. |
105 | 120 |
106 if (toolchain_records_.empty()) { | 121 if (toolchain_records_.empty()) { |
107 // Nothing loaded, need to load the default build config. The intial load | 122 // Nothing loaded, need to load the default build config. The intial load |
108 // should not specify a toolchain. | 123 // should not specify a toolchain. |
109 DCHECK(toolchain_name.is_null()); | 124 DCHECK(toolchain_name.is_null()); |
110 | 125 |
111 ToolchainRecord* record = | 126 ToolchainRecord* record = |
112 new ToolchainRecord(build_settings_, Label(), Label()); | 127 new ToolchainRecord(build_settings_, Label(), Label()); |
113 toolchain_records_[Label()] = record; | 128 toolchain_records_[Label()] = record; |
114 | 129 |
115 // The default build config is no dependent on the toolchain definition, | 130 // The default build config is no dependent on the toolchain definition, |
116 // since we need to load the build config before we know what the default | 131 // since we need to load the build config before we know what the default |
117 // toolchain name is. | 132 // toolchain name is. |
118 record->is_toolchain_loaded = true; | 133 record->is_toolchain_loaded = true; |
119 | 134 |
120 record->waiting_on_me.push_back(file); | 135 record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin)); |
121 ScheduleLoadBuildConfig(&record->settings, Scope::KeyValueMap()); | 136 ScheduleLoadBuildConfig(&record->settings, Scope::KeyValueMap()); |
122 return; | 137 return; |
123 } | 138 } |
124 | 139 |
125 ToolchainRecord* record; | 140 ToolchainRecord* record; |
126 if (toolchain_name.is_null()) | 141 if (toolchain_name.is_null()) |
127 record = toolchain_records_[default_toolchain_label_]; | 142 record = toolchain_records_[default_toolchain_label_]; |
128 else | 143 else |
129 record = toolchain_records_[toolchain_name]; | 144 record = toolchain_records_[toolchain_name]; |
130 | 145 |
131 if (!record) { | 146 if (!record) { |
132 DCHECK(!default_toolchain_label_.is_null()); | 147 DCHECK(!default_toolchain_label_.is_null()); |
133 | 148 |
134 // No reference to this toolchain found yet, make one. | 149 // No reference to this toolchain found yet, make one. |
135 record = new ToolchainRecord(build_settings_, toolchain_name, | 150 record = new ToolchainRecord(build_settings_, toolchain_name, |
136 default_toolchain_label_); | 151 default_toolchain_label_); |
137 toolchain_records_[toolchain_name] = record; | 152 toolchain_records_[toolchain_name] = record; |
138 | 153 |
139 // Schedule a load of the toolchain using the default one. | 154 // Schedule a load of the toolchain using the default one. |
140 Load(BuildFileForLabel(toolchain_name), default_toolchain_label_); | 155 Load(BuildFileForLabel(toolchain_name), origin, default_toolchain_label_); |
141 } | 156 } |
142 | 157 |
143 if (record->is_config_loaded) | 158 if (record->is_config_loaded) |
144 ScheduleLoadFile(&record->settings, file); | 159 ScheduleLoadFile(&record->settings, origin, file); |
145 else | 160 else |
146 record->waiting_on_me.push_back(file); | 161 record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin)); |
147 } | 162 } |
148 | 163 |
149 void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) { | 164 void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) { |
150 ToolchainRecord* record = toolchain_records_[toolchain->label()]; | 165 ToolchainRecord* record = toolchain_records_[toolchain->label()]; |
151 if (!record) { | 166 if (!record) { |
152 DCHECK(!default_toolchain_label_.is_null()); | 167 DCHECK(!default_toolchain_label_.is_null()); |
153 record = new ToolchainRecord(build_settings_, toolchain->label(), | 168 record = new ToolchainRecord(build_settings_, toolchain->label(), |
154 default_toolchain_label_); | 169 default_toolchain_label_); |
155 toolchain_records_[toolchain->label()] = record; | 170 toolchain_records_[toolchain->label()] = record; |
156 } | 171 } |
(...skipping 24 matching lines...) Expand all Loading... |
181 } else { | 196 } else { |
182 found_toolchain = toolchain_records_.find(label); | 197 found_toolchain = toolchain_records_.find(label); |
183 } | 198 } |
184 | 199 |
185 if (found_toolchain == toolchain_records_.end()) | 200 if (found_toolchain == toolchain_records_.end()) |
186 return NULL; | 201 return NULL; |
187 return &found_toolchain->second->settings; | 202 return &found_toolchain->second->settings; |
188 } | 203 } |
189 | 204 |
190 void LoaderImpl::ScheduleLoadFile(const Settings* settings, | 205 void LoaderImpl::ScheduleLoadFile(const Settings* settings, |
| 206 const LocationRange& origin, |
191 const SourceFile& file) { | 207 const SourceFile& file) { |
192 Err err; | 208 Err err; |
193 pending_loads_++; | 209 pending_loads_++; |
194 if (!AsyncLoadFile(LocationRange(), settings->build_settings(), file, | 210 if (!AsyncLoadFile(origin, settings->build_settings(), file, |
195 base::Bind(&LoaderImpl::BackgroundLoadFile, this, | 211 base::Bind(&LoaderImpl::BackgroundLoadFile, this, |
196 settings, file), | 212 settings, file), |
197 &err)) { | 213 &err)) { |
198 g_scheduler->FailWithError(err); | 214 g_scheduler->FailWithError(err); |
199 DecrementPendingLoads(); | 215 DecrementPendingLoads(); |
200 } | 216 } |
201 } | 217 } |
202 | 218 |
203 void LoaderImpl::ScheduleLoadBuildConfig( | 219 void LoaderImpl::ScheduleLoadBuildConfig( |
204 Settings* settings, | 220 Settings* settings, |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 } | 383 } |
368 } else { | 384 } else { |
369 record = found_toolchain->second; | 385 record = found_toolchain->second; |
370 } | 386 } |
371 | 387 |
372 DCHECK(!record->is_config_loaded); | 388 DCHECK(!record->is_config_loaded); |
373 DCHECK(record->is_toolchain_loaded); | 389 DCHECK(record->is_toolchain_loaded); |
374 record->is_config_loaded = true; | 390 record->is_config_loaded = true; |
375 | 391 |
376 // Schedule all waiting file loads. | 392 // Schedule all waiting file loads. |
377 for (size_t i = 0; i < record->waiting_on_me.size(); i++) | 393 for (size_t i = 0; i < record->waiting_on_me.size(); i++) { |
378 ScheduleLoadFile(&record->settings, record->waiting_on_me[i]); | 394 ScheduleLoadFile(&record->settings, record->waiting_on_me[i].origin, |
| 395 record->waiting_on_me[i].file); |
| 396 } |
379 record->waiting_on_me.clear(); | 397 record->waiting_on_me.clear(); |
380 | 398 |
381 DecrementPendingLoads(); | 399 DecrementPendingLoads(); |
382 } | 400 } |
383 | 401 |
384 void LoaderImpl::DecrementPendingLoads() { | 402 void LoaderImpl::DecrementPendingLoads() { |
385 DCHECK(pending_loads_ > 0); | 403 DCHECK(pending_loads_ > 0); |
386 pending_loads_--; | 404 pending_loads_--; |
387 if (pending_loads_ == 0 && !complete_callback_.is_null()) | 405 if (pending_loads_ == 0 && !complete_callback_.is_null()) |
388 complete_callback_.Run(); | 406 complete_callback_.Run(); |
389 } | 407 } |
390 | 408 |
391 bool LoaderImpl::AsyncLoadFile( | 409 bool LoaderImpl::AsyncLoadFile( |
392 const LocationRange& origin, | 410 const LocationRange& origin, |
393 const BuildSettings* build_settings, | 411 const BuildSettings* build_settings, |
394 const SourceFile& file_name, | 412 const SourceFile& file_name, |
395 const base::Callback<void(const ParseNode*)>& callback, | 413 const base::Callback<void(const ParseNode*)>& callback, |
396 Err* err) { | 414 Err* err) { |
397 if (async_load_file_.is_null()) { | 415 if (async_load_file_.is_null()) { |
398 return g_scheduler->input_file_manager()->AsyncLoadFile( | 416 return g_scheduler->input_file_manager()->AsyncLoadFile( |
399 origin, build_settings, file_name, callback, err); | 417 origin, build_settings, file_name, callback, err); |
400 } | 418 } |
401 return async_load_file_.Run( | 419 return async_load_file_.Run( |
402 origin, build_settings, file_name, callback, err); | 420 origin, build_settings, file_name, callback, err); |
403 } | 421 } |
OLD | NEW |