120 lines
3.5 KiB
C++
120 lines
3.5 KiB
C++
|
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "tools/gn/item_node.h"
|
||
|
|
||
|
#include <algorithm>
|
||
|
|
||
|
#include "base/callback.h"
|
||
|
#include "base/logging.h"
|
||
|
#include "tools/gn/build_settings.h"
|
||
|
#include "tools/gn/item.h"
|
||
|
|
||
|
ItemNode::ItemNode(Item* i)
|
||
|
: state_(REFERENCED),
|
||
|
item_(i),
|
||
|
should_generate_(false) {
|
||
|
}
|
||
|
|
||
|
ItemNode::~ItemNode() {
|
||
|
}
|
||
|
|
||
|
bool ItemNode::SetShouldGenerate(const BuildSettings* build_settings,
|
||
|
Err* err) {
|
||
|
if (should_generate_)
|
||
|
return true;
|
||
|
should_generate_ = true;
|
||
|
|
||
|
if (state_ == DEFINED) {
|
||
|
if (!ScheduleDepsLoad(build_settings, err))
|
||
|
return false;
|
||
|
} else if (state_ == RESOLVED) {
|
||
|
// The item may have been resolved even if we didn't set the generate bit
|
||
|
// if all of its deps were loaded some other way. In this case, we need
|
||
|
// to run the closure which we skipped when it became resolved.
|
||
|
if (!resolved_closure_.is_null())
|
||
|
resolved_closure_.Run();
|
||
|
}
|
||
|
|
||
|
// Pass the generate bit to all deps.
|
||
|
for (ItemNodeMap::iterator i = direct_dependencies_.begin();
|
||
|
i != direct_dependencies_.end(); ++i) {
|
||
|
if (!i->first->SetShouldGenerate(build_settings, err))
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool ItemNode::AddDependency(const BuildSettings* build_settings,
|
||
|
const LocationRange& specified_from_here,
|
||
|
ItemNode* node,
|
||
|
Err* err) {
|
||
|
// Can't add more deps once it's been defined.
|
||
|
DCHECK(state_ == REFERENCED);
|
||
|
|
||
|
if (direct_dependencies_.find(node) != direct_dependencies_.end())
|
||
|
return true; // Already have this dep.
|
||
|
|
||
|
direct_dependencies_[node] = specified_from_here;
|
||
|
|
||
|
if (node->state() != RESOLVED) {
|
||
|
// Wire up the pending resolution info.
|
||
|
unresolved_dependencies_[node] = specified_from_here;
|
||
|
node->waiting_on_resolution_[this] = specified_from_here;
|
||
|
}
|
||
|
|
||
|
if (should_generate_) {
|
||
|
if (!node->SetShouldGenerate(build_settings, err))
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void ItemNode::MarkDirectDependencyResolved(ItemNode* node) {
|
||
|
DCHECK(unresolved_dependencies_.find(node) != unresolved_dependencies_.end());
|
||
|
unresolved_dependencies_.erase(node);
|
||
|
}
|
||
|
|
||
|
void ItemNode::SwapOutWaitingDependencySet(ItemNodeMap* out_map) {
|
||
|
waiting_on_resolution_.swap(*out_map);
|
||
|
DCHECK(waiting_on_resolution_.empty());
|
||
|
}
|
||
|
|
||
|
bool ItemNode::SetDefined(const BuildSettings* build_settings, Err* err) {
|
||
|
DCHECK(state_ == REFERENCED);
|
||
|
state_ = DEFINED;
|
||
|
|
||
|
if (should_generate_)
|
||
|
return ScheduleDepsLoad(build_settings, err);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void ItemNode::SetResolved() {
|
||
|
DCHECK(state_ != RESOLVED);
|
||
|
state_ = RESOLVED;
|
||
|
|
||
|
if (should_generate_ && !resolved_closure_.is_null())
|
||
|
resolved_closure_.Run();
|
||
|
}
|
||
|
|
||
|
bool ItemNode::ScheduleDepsLoad(const BuildSettings* build_settings,
|
||
|
Err* err) {
|
||
|
DCHECK(state_ == DEFINED);
|
||
|
DCHECK(should_generate_); // Shouldn't be requesting deps for ungenerated
|
||
|
// items.
|
||
|
|
||
|
for (ItemNodeMap::const_iterator i = unresolved_dependencies_.begin();
|
||
|
i != unresolved_dependencies_.end(); ++i) {
|
||
|
Label toolchain_label = i->first->item()->label().GetToolchainLabel();
|
||
|
SourceDir dir_to_load = i->first->item()->label().dir();
|
||
|
|
||
|
if (!build_settings->toolchain_manager().ScheduleInvocationLocked(
|
||
|
i->second, toolchain_label, dir_to_load, err))
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
state_ = PENDING_DEPS;
|
||
|
return true;
|
||
|
}
|