Ninja
state.cc
Go to the documentation of this file.
00001 // Copyright 2011 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //     http://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "state.h"
00016 
00017 #include <assert.h>
00018 
00019 #include "graph.h"
00020 #include "util.h"
00021 
00022 const Rule State::kPhonyRule("phony");
00023 
00024 State::State() : build_log_(NULL) {
00025   AddRule(&kPhonyRule);
00026 }
00027 
00028 void State::AddRule(const Rule* rule) {
00029   assert(LookupRule(rule->name_) == NULL);
00030   rules_[rule->name_] = rule;
00031 }
00032 
00033 const Rule* State::LookupRule(const string& rule_name) {
00034   map<string, const Rule*>::iterator i = rules_.find(rule_name);
00035   if (i == rules_.end())
00036     return NULL;
00037   return i->second;
00038 }
00039 
00040 Edge* State::AddEdge(const Rule* rule) {
00041   Edge* edge = new Edge();
00042   edge->rule_ = rule;
00043   edge->env_ = &bindings_;
00044   edges_.push_back(edge);
00045   return edge;
00046 }
00047 
00048 Node* State::GetNode(const string& path) {
00049   FileStat* file = stat_cache_.GetFile(path);
00050   if (!file->node_)
00051     file->node_ = new Node(file);
00052   return file->node_;
00053 }
00054 
00055 Node* State::LookupNode(const string& path) {
00056   FileStat* file = stat_cache_.GetFile(path);
00057   if (!file->node_)
00058     return NULL;
00059   return file->node_;
00060 }
00061 
00062 void State::AddIn(Edge* edge, const string& path) {
00063   Node* node = GetNode(path);
00064   edge->inputs_.push_back(node);
00065   node->out_edges_.push_back(edge);
00066 }
00067 
00068 void State::AddOut(Edge* edge, const string& path) {
00069   Node* node = GetNode(path);
00070   edge->outputs_.push_back(node);
00071   if (node->in_edge_) {
00072     Warning("multiple rules generate %s. "
00073             "build will not be correct; continuing anyway", path.c_str());
00074   }
00075   node->in_edge_ = edge;
00076 }
00077 
00078 bool State::AddDefault(const string& path, string* err) {
00079   Node* node = LookupNode(path);
00080   if (!node) {
00081     *err = "unknown target '" + path + "'";
00082     return false;
00083   }
00084   defaults_.push_back(node);
00085   return true;
00086 }
00087 
00088 vector<Node*> State::RootNodes(string* err) {
00089   vector<Node*> root_nodes;
00090   // Search for nodes with no output.
00091   for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e) {
00092     for (vector<Node*>::iterator out = (*e)->outputs_.begin();
00093          out != (*e)->outputs_.end(); ++out) {
00094       if ((*out)->out_edges_.empty())
00095         root_nodes.push_back(*out);
00096     }
00097   }
00098 
00099   if (!edges_.empty() && root_nodes.empty())
00100     *err = "could not determine root nodes of build graph";
00101 
00102   assert(edges_.empty() || !root_nodes.empty());
00103   return root_nodes;
00104 }
00105 
00106 vector<Node*> State::DefaultNodes(string* err) {
00107   return defaults_.empty() ? RootNodes(err) : defaults_;
00108 }
00109 
00110 void State::Reset() {
00111   stat_cache_.Invalidate();
00112   for (vector<Edge*>::iterator e = edges_.begin(); e != edges_.end(); ++e)
00113     (*e)->outputs_ready_ = false;
00114 }