| 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 |