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