[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 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. |
Dirk Pranke | c9126ec98 | 2017-08-17 15:05:07 | [diff] [blame] | 4 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 5 | #include "tools/gn/loader.h" |
| 6 | |
| 7 | #include "base/bind.h" |
dcheng | a500b69 | 2016-04-08 19:55:42 | [diff] [blame] | 8 | #include "base/memory/ptr_util.h" |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 9 | #include "base/threading/thread_task_runner_handle.h" |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 10 | #include "tools/gn/build_settings.h" |
| 11 | #include "tools/gn/err.h" |
| 12 | #include "tools/gn/filesystem_utils.h" |
| 13 | #include "tools/gn/input_file_manager.h" |
| 14 | #include "tools/gn/parse_tree.h" |
| 15 | #include "tools/gn/scheduler.h" |
| 16 | #include "tools/gn/scope_per_file_provider.h" |
| 17 | #include "tools/gn/settings.h" |
| 18 | #include "tools/gn/source_dir.h" |
| 19 | #include "tools/gn/source_file.h" |
| 20 | #include "tools/gn/trace.h" |
| 21 | |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 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 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 36 | // Identifies one time a file is loaded in a given toolchain so we don't load |
| 37 | // it more than once. |
| 38 | struct LoaderImpl::LoadID { |
| 39 | LoadID() {} |
| 40 | LoadID(const SourceFile& f, const Label& tc_name) |
| 41 | : file(f), |
| 42 | toolchain_name(tc_name) { |
| 43 | } |
| 44 | |
| 45 | bool operator<(const LoadID& other) const { |
| 46 | if (file.value() == other.file.value()) |
| 47 | return toolchain_name < other.toolchain_name; |
| 48 | return file < other.file; |
| 49 | } |
| 50 | |
| 51 | SourceFile file; |
| 52 | Label toolchain_name; |
| 53 | }; |
| 54 | |
| 55 | // Our tracking information for a toolchain. |
| 56 | struct LoaderImpl::ToolchainRecord { |
| 57 | // The default toolchain label can be empty for the first time the default |
| 58 | // toolchain is loaded, since we don't know it yet. This will be fixed up |
| 59 | // later. It should be valid in all other cases. |
| 60 | ToolchainRecord(const BuildSettings* build_settings, |
| 61 | const Label& toolchain_label, |
| 62 | const Label& default_toolchain_label) |
| 63 | : settings(build_settings, |
| 64 | GetOutputSubdirName(toolchain_label, |
| 65 | toolchain_label == default_toolchain_label)), |
| 66 | is_toolchain_loaded(false), |
| 67 | is_config_loaded(false) { |
| 68 | settings.set_default_toolchain_label(default_toolchain_label); |
| 69 | settings.set_toolchain_label(toolchain_label); |
| 70 | } |
| 71 | |
| 72 | Settings settings; |
| 73 | |
| 74 | bool is_toolchain_loaded; |
| 75 | bool is_config_loaded; |
| 76 | |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 77 | std::vector<SourceFileAndOrigin> waiting_on_me; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 78 | }; |
| 79 | |
| 80 | // ----------------------------------------------------------------------------- |
| 81 | |
thestig | 3b6a2f1 | 2015-09-25 08:17:20 | [diff] [blame] | 82 | const void* const Loader::kDefaultToolchainKey = &kDefaultToolchainKey; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 83 | |
| 84 | Loader::Loader() { |
| 85 | } |
| 86 | |
| 87 | Loader::~Loader() { |
| 88 | } |
| 89 | |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 90 | void Loader::Load(const Label& label, const LocationRange& origin) { |
| 91 | Load(BuildFileForLabel(label), origin, label.GetToolchainLabel()); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | // static |
| 95 | SourceFile Loader::BuildFileForLabel(const Label& label) { |
| 96 | return SourceFile(label.dir().value() + "BUILD.gn"); |
| 97 | } |
| 98 | |
| 99 | // ----------------------------------------------------------------------------- |
| 100 | |
| 101 | LoaderImpl::LoaderImpl(const BuildSettings* build_settings) |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 102 | : pending_loads_(0), build_settings_(build_settings) { |
| 103 | // There may not be an active TaskRunner at this point. When that's the case, |
| 104 | // the calling code is expected to call set_task_runner(). |
| 105 | if (base::ThreadTaskRunnerHandle::IsSet()) |
| 106 | task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | LoaderImpl::~LoaderImpl() { |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | void LoaderImpl::Load(const SourceFile& file, |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 113 | const LocationRange& origin, |
| 114 | const Label& in_toolchain_name) { |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 115 | const Label& toolchain_name = in_toolchain_name.is_null() |
| 116 | ? default_toolchain_label_ : in_toolchain_name; |
| 117 | LoadID load_id(file, toolchain_name); |
| 118 | if (!invocations_.insert(load_id).second) |
| 119 | return; // Already in set, so this file was already loaded or schedulerd. |
| 120 | |
| 121 | if (toolchain_records_.empty()) { |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 122 | // Nothing loaded, need to load the default build config. The initial load |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 123 | // should not specify a toolchain. |
| 124 | DCHECK(toolchain_name.is_null()); |
| 125 | |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 126 | std::unique_ptr<ToolchainRecord> new_record( |
| 127 | new ToolchainRecord(build_settings_, Label(), Label())); |
| 128 | ToolchainRecord* record = new_record.get(); |
| 129 | toolchain_records_[Label()] = std::move(new_record); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 130 | |
| 131 | // The default build config is no dependent on the toolchain definition, |
| 132 | // since we need to load the build config before we know what the default |
| 133 | // toolchain name is. |
| 134 | record->is_toolchain_loaded = true; |
| 135 | |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 136 | record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 137 | ScheduleLoadBuildConfig(&record->settings, Scope::KeyValueMap()); |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 138 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 139 | return; |
| 140 | } |
| 141 | |
| 142 | ToolchainRecord* record; |
| 143 | if (toolchain_name.is_null()) |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 144 | record = toolchain_records_[default_toolchain_label_].get(); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 145 | else |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 146 | record = toolchain_records_[toolchain_name].get(); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 147 | |
| 148 | if (!record) { |
| 149 | DCHECK(!default_toolchain_label_.is_null()); |
| 150 | |
| 151 | // No reference to this toolchain found yet, make one. |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 152 | std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord( |
| 153 | build_settings_, toolchain_name, default_toolchain_label_)); |
| 154 | record = new_record.get(); |
| 155 | toolchain_records_[toolchain_name] = std::move(new_record); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 156 | |
| 157 | // Schedule a load of the toolchain using the default one. |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 158 | Load(BuildFileForLabel(toolchain_name), origin, default_toolchain_label_); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 159 | } |
| 160 | |
| 161 | if (record->is_config_loaded) |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 162 | ScheduleLoadFile(&record->settings, origin, file); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 163 | else |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 164 | record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 165 | } |
| 166 | |
| 167 | void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) { |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 168 | ToolchainRecord* record = toolchain_records_[toolchain->label()].get(); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 169 | if (!record) { |
| 170 | DCHECK(!default_toolchain_label_.is_null()); |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 171 | std::unique_ptr<ToolchainRecord> new_record(new ToolchainRecord( |
| 172 | build_settings_, toolchain->label(), default_toolchain_label_)); |
| 173 | record = new_record.get(); |
| 174 | toolchain_records_[toolchain->label()] = std::move(new_record); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 175 | } |
| 176 | record->is_toolchain_loaded = true; |
| 177 | |
| 178 | // The default build config is loaded first, then its toolchain. Secondary |
| 179 | // ones are loaded in the opposite order so we can pass toolchain parameters |
| 180 | // to the build config. So we may or may not have a config at this point. |
| 181 | if (!record->is_config_loaded) { |
| 182 | ScheduleLoadBuildConfig(&record->settings, toolchain->args()); |
| 183 | } else { |
| 184 | // There should be nobody waiting on this if the build config is already |
| 185 | // loaded. |
| 186 | DCHECK(record->waiting_on_me.empty()); |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | Label LoaderImpl::GetDefaultToolchain() const { |
| 191 | return default_toolchain_label_; |
| 192 | } |
| 193 | |
[email protected] | 003361c | 2014-02-12 11:27:00 | [diff] [blame] | 194 | const Settings* LoaderImpl::GetToolchainSettings(const Label& label) const { |
| 195 | ToolchainRecordMap::const_iterator found_toolchain; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 196 | if (label.is_null()) { |
| 197 | if (default_toolchain_label_.is_null()) |
tfarina | 9b636af | 2014-12-23 00:52:07 | [diff] [blame] | 198 | return nullptr; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 199 | found_toolchain = toolchain_records_.find(default_toolchain_label_); |
| 200 | } else { |
| 201 | found_toolchain = toolchain_records_.find(label); |
| 202 | } |
| 203 | |
| 204 | if (found_toolchain == toolchain_records_.end()) |
tfarina | 9b636af | 2014-12-23 00:52:07 | [diff] [blame] | 205 | return nullptr; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 206 | return &found_toolchain->second->settings; |
| 207 | } |
| 208 | |
| 209 | void LoaderImpl::ScheduleLoadFile(const Settings* settings, |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 210 | const LocationRange& origin, |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 211 | const SourceFile& file) { |
| 212 | Err err; |
| 213 | pending_loads_++; |
[email protected] | a59f713 | 2014-06-10 17:48:39 | [diff] [blame] | 214 | if (!AsyncLoadFile(origin, settings->build_settings(), file, |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 215 | base::Bind(&LoaderImpl::BackgroundLoadFile, this, |
agrieve | dbecf02 | 2016-04-22 00:58:08 | [diff] [blame] | 216 | settings, file, origin), |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 217 | &err)) { |
| 218 | g_scheduler->FailWithError(err); |
| 219 | DecrementPendingLoads(); |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | void LoaderImpl::ScheduleLoadBuildConfig( |
| 224 | Settings* settings, |
| 225 | const Scope::KeyValueMap& toolchain_overrides) { |
| 226 | Err err; |
| 227 | pending_loads_++; |
| 228 | if (!AsyncLoadFile(LocationRange(), settings->build_settings(), |
| 229 | settings->build_settings()->build_config_file(), |
| 230 | base::Bind(&LoaderImpl::BackgroundLoadBuildConfig, |
| 231 | this, settings, toolchain_overrides), |
| 232 | &err)) { |
| 233 | g_scheduler->FailWithError(err); |
| 234 | DecrementPendingLoads(); |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | void LoaderImpl::BackgroundLoadFile(const Settings* settings, |
| 239 | const SourceFile& file_name, |
agrieve | dbecf02 | 2016-04-22 00:58:08 | [diff] [blame] | 240 | const LocationRange& origin, |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 241 | const ParseNode* root) { |
| 242 | if (!root) { |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 243 | task_runner_->PostTask( |
fdoray | 01c8157e | 2016-06-22 18:49:15 | [diff] [blame] | 244 | FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 245 | return; |
| 246 | } |
| 247 | |
| 248 | if (g_scheduler->verbose_logging()) { |
| 249 | g_scheduler->Log("Running", file_name.value() + " with toolchain " + |
| 250 | settings->toolchain_label().GetUserVisibleName(false)); |
| 251 | } |
| 252 | |
| 253 | Scope our_scope(settings->base_config()); |
[email protected] | 3aa6f81 | 2014-04-08 22:35:18 | [diff] [blame] | 254 | ScopePerFileProvider per_file_provider(&our_scope, true); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 255 | our_scope.set_source_dir(file_name.GetDir()); |
| 256 | |
[email protected] | e1bd79f | 2014-05-05 20:27:53 | [diff] [blame] | 257 | // Targets, etc. generated as part of running this file will end up here. |
| 258 | Scope::ItemVector collected_items; |
| 259 | our_scope.set_item_collector(&collected_items); |
| 260 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 261 | ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, file_name.value()); |
| 262 | trace.SetToolchain(settings->toolchain_label()); |
| 263 | |
| 264 | Err err; |
| 265 | root->Execute(&our_scope, &err); |
agrieve | dbecf02 | 2016-04-22 00:58:08 | [diff] [blame] | 266 | if (!err.has_error()) |
| 267 | our_scope.CheckForUnusedVars(&err); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 268 | |
agrieve | dbecf02 | 2016-04-22 00:58:08 | [diff] [blame] | 269 | if (err.has_error()) { |
| 270 | if (!origin.is_null()) |
| 271 | err.AppendSubErr(Err(origin, "which caused the file to be included.")); |
[email protected] | afb30e3 | 2014-05-16 19:31:36 | [diff] [blame] | 272 | g_scheduler->FailWithError(err); |
agrieve | dbecf02 | 2016-04-22 00:58:08 | [diff] [blame] | 273 | } |
| 274 | |
[email protected] | afb30e3 | 2014-05-16 19:31:36 | [diff] [blame] | 275 | |
[email protected] | e1bd79f | 2014-05-05 20:27:53 | [diff] [blame] | 276 | // Pass all of the items that were defined off to the builder. |
avi | f6016b0 | 2017-07-06 21:24:13 | [diff] [blame] | 277 | for (auto& item : collected_items) |
| 278 | settings->build_settings()->ItemDefined(std::move(item)); |
[email protected] | e1bd79f | 2014-05-05 20:27:53 | [diff] [blame] | 279 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 280 | trace.Done(); |
| 281 | |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 282 | task_runner_->PostTask(FROM_HERE, base::Bind(&LoaderImpl::DidLoadFile, this)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | void LoaderImpl::BackgroundLoadBuildConfig( |
| 286 | Settings* settings, |
| 287 | const Scope::KeyValueMap& toolchain_overrides, |
| 288 | const ParseNode* root) { |
| 289 | if (!root) { |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 290 | task_runner_->PostTask( |
fdoray | 01c8157e | 2016-06-22 18:49:15 | [diff] [blame] | 291 | FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 292 | return; |
| 293 | } |
| 294 | |
| 295 | Scope* base_config = settings->base_config(); |
| 296 | base_config->set_source_dir(SourceDir("//")); |
| 297 | |
| 298 | settings->build_settings()->build_args().SetupRootScope( |
| 299 | base_config, toolchain_overrides); |
| 300 | |
| 301 | base_config->SetProcessingBuildConfig(); |
| 302 | |
| 303 | // See kDefaultToolchainKey in the header. |
| 304 | Label default_toolchain_label; |
| 305 | if (settings->is_default()) |
| 306 | base_config->SetProperty(kDefaultToolchainKey, &default_toolchain_label); |
| 307 | |
| 308 | ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, |
| 309 | settings->build_settings()->build_config_file().value()); |
| 310 | trace.SetToolchain(settings->toolchain_label()); |
| 311 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 312 | Err err; |
mdempsky | 3ad7aeb3 | 2015-03-17 22:38:02 | [diff] [blame] | 313 | root->Execute(base_config, &err); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 314 | |
[email protected] | afb30e3 | 2014-05-16 19:31:36 | [diff] [blame] | 315 | // Clear all private variables left in the scope. We want the root build |
| 316 | // config to be like a .gni file in that variables beginning with an |
| 317 | // underscore aren't exported. |
| 318 | base_config->RemovePrivateIdentifiers(); |
| 319 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 320 | trace.Done(); |
| 321 | |
[email protected] | 42b013f | 2013-12-16 17:58:16 | [diff] [blame] | 322 | if (err.has_error()) |
| 323 | g_scheduler->FailWithError(err); |
| 324 | |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 325 | base_config->ClearProcessingBuildConfig(); |
| 326 | if (settings->is_default()) { |
| 327 | // The default toolchain must have been set in the default build config |
| 328 | // file. |
| 329 | if (default_toolchain_label.is_null()) { |
| 330 | g_scheduler->FailWithError(Err(Location(), |
| 331 | "The default build config file did not call set_default_toolchain()", |
| 332 | "If you don't call this, I can't figure out what toolchain to use\n" |
| 333 | "for all of this code.")); |
| 334 | } else { |
| 335 | DCHECK(settings->toolchain_label().is_null()); |
| 336 | settings->set_toolchain_label(default_toolchain_label); |
| 337 | } |
| 338 | } |
| 339 | |
fdoray | f0544fc | 2016-07-18 16:05:15 | [diff] [blame] | 340 | task_runner_->PostTask(FROM_HERE, |
| 341 | base::Bind(&LoaderImpl::DidLoadBuildConfig, this, |
| 342 | settings->toolchain_label())); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 343 | } |
| 344 | |
| 345 | void LoaderImpl::DidLoadFile() { |
| 346 | DecrementPendingLoads(); |
| 347 | } |
| 348 | |
| 349 | void LoaderImpl::DidLoadBuildConfig(const Label& label) { |
| 350 | // Do not return early, we must call DecrementPendingLoads() at the bottom. |
| 351 | |
| 352 | ToolchainRecordMap::iterator found_toolchain = toolchain_records_.find(label); |
tfarina | 9b636af | 2014-12-23 00:52:07 | [diff] [blame] | 353 | ToolchainRecord* record = nullptr; |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 354 | if (found_toolchain == toolchain_records_.end()) { |
| 355 | // When loading the default build config, we'll insert it into the record |
| 356 | // map with an empty label since we don't yet know what to call it. |
| 357 | // |
| 358 | // In this case, we should have exactly one entry in the map with an empty |
| 359 | // label. We now need to fix up the naming so it refers to the "real" one. |
thestig | 3b6a2f1 | 2015-09-25 08:17:20 | [diff] [blame] | 360 | CHECK_EQ(1U, toolchain_records_.size()); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 361 | ToolchainRecordMap::iterator empty_label = toolchain_records_.find(Label()); |
| 362 | CHECK(empty_label != toolchain_records_.end()); |
| 363 | |
| 364 | // Fix up the toolchain record. |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 365 | std::unique_ptr<ToolchainRecord> moved_record = |
| 366 | std::move(empty_label->second); |
| 367 | record = moved_record.get(); |
| 368 | toolchain_records_[label] = std::move(moved_record); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 369 | toolchain_records_.erase(empty_label); |
| 370 | |
| 371 | // Save the default toolchain label. |
| 372 | default_toolchain_label_ = label; |
| 373 | DCHECK(record->settings.default_toolchain_label().is_null()); |
| 374 | record->settings.set_default_toolchain_label(label); |
| 375 | |
| 376 | // The settings object should have the toolchain label already set. |
| 377 | DCHECK(!record->settings.toolchain_label().is_null()); |
| 378 | |
| 379 | // Update any stored invocations that refer to the empty toolchain label. |
| 380 | // This will normally only be one, for the root build file, so brute-force |
| 381 | // is OK. |
| 382 | LoadIDSet old_loads; |
| 383 | invocations_.swap(old_loads); |
brettw | d1033b6 | 2014-09-30 21:44:05 | [diff] [blame] | 384 | for (const auto& load : old_loads) { |
| 385 | if (load.toolchain_name.is_null()) { |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 386 | // Fix up toolchain label |
brettw | d1033b6 | 2014-09-30 21:44:05 | [diff] [blame] | 387 | invocations_.insert(LoadID(load.file, label)); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 388 | } else { |
| 389 | // Can keep the old one. |
brettw | d1033b6 | 2014-09-30 21:44:05 | [diff] [blame] | 390 | invocations_.insert(load); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 391 | } |
| 392 | } |
| 393 | } else { |
jbroman | f9b6b5a | 2016-04-18 20:59:38 | [diff] [blame] | 394 | record = found_toolchain->second.get(); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 395 | } |
| 396 | |
| 397 | DCHECK(!record->is_config_loaded); |
| 398 | DCHECK(record->is_toolchain_loaded); |
| 399 | record->is_config_loaded = true; |
| 400 | |
| 401 | // Schedule all waiting file loads. |
brettw | d1033b6 | 2014-09-30 21:44:05 | [diff] [blame] | 402 | for (const auto& waiting : record->waiting_on_me) |
| 403 | ScheduleLoadFile(&record->settings, waiting.origin, waiting.file); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 404 | record->waiting_on_me.clear(); |
| 405 | |
| 406 | DecrementPendingLoads(); |
| 407 | } |
| 408 | |
| 409 | void LoaderImpl::DecrementPendingLoads() { |
thestig | 3b6a2f1 | 2015-09-25 08:17:20 | [diff] [blame] | 410 | DCHECK_GT(pending_loads_, 0); |
[email protected] | 26542b0 | 2013-11-08 23:25:04 | [diff] [blame] | 411 | pending_loads_--; |
| 412 | if (pending_loads_ == 0 && !complete_callback_.is_null()) |
| 413 | complete_callback_.Run(); |
| 414 | } |
| 415 | |
| 416 | bool LoaderImpl::AsyncLoadFile( |
| 417 | const LocationRange& origin, |
| 418 | const BuildSettings* build_settings, |
| 419 | const SourceFile& file_name, |
| 420 | const base::Callback<void(const ParseNode*)>& callback, |
| 421 | Err* err) { |
| 422 | if (async_load_file_.is_null()) { |
| 423 | return g_scheduler->input_file_manager()->AsyncLoadFile( |
| 424 | origin, build_settings, file_name, callback, err); |
| 425 | } |
| 426 | return async_load_file_.Run( |
| 427 | origin, build_settings, file_name, callback, err); |
| 428 | } |