// 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.
#ifndef TOOLS_GN_BUILDER_H_
#define TOOLS_GN_BUILDER_H_
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/memory/ref_counted.h"
#include "tools/gn/builder_record.h"
#include "tools/gn/label.h"
#include "tools/gn/label_ptr.h"
class Config;
class Err;
class Loader;
class ParseNode;
class Builder : public base::RefCountedThreadSafe<Builder> {
public:
typedef base::Callback<void(const Item*)> ResolvedCallback;
Builder(Loader* loader);
// The resolved callback is called whenever a target has been resolved. This
// will be executed only on the main thread.
void set_resolved_callback(const ResolvedCallback& cb) {
resolved_callback_ = cb;
}
Loader* loader() const { return loader_; }
void ItemDefined(scoped_ptr<Item> item);
// Returns NULL if there is not a thing with the corresponding label.
const Item* GetItem(const Label& label) const;
const Toolchain* GetToolchain(const Label& label) const;
std::vector<const BuilderRecord*> GetAllRecords() const;
// Returns targets which should be generated and which are defined.
std::vector<const Target*> GetAllResolvedTargets() const;
// Returns the record for the given label, or NULL if it doesn't exist.
// Mostly used for unit tests.
const BuilderRecord* GetRecord(const Label& label) const;
BuilderRecord* GetRecord(const Label& label);
// If there are any undefined references, returns false and sets the error.
bool CheckForBadItems(Err* err) const;
private:
friend class base::RefCountedThreadSafe<Builder>;
virtual ~Builder();
bool TargetDefined(BuilderRecord* record, Err* err);
// Returns the record associated with the given label. This function checks
// that if we already have references for it, the type matches. If no record
// exists yet, a new one will be created.
//
// If any of the conditions fail, the return value will be null and the error
// will be set. request_from is used as the source of the error.
BuilderRecord* GetOrCreateRecordOfType(const Label& label,
const ParseNode* request_from,
BuilderRecord::ItemType type,
Err* err);
// Returns the record associated with the given label. This function checks
// that it's already been resolved to the correct type.
//
// If any of the conditions fail, the return value will be null and the error
// will be set. request_from is used as the source of the error.
BuilderRecord* GetResolvedRecordOfType(const Label& label,
const ParseNode* request_from,
BuilderRecord::ItemType type,
Err* err);
bool AddDeps(BuilderRecord* record,
const LabelConfigVector& configs,
Err* err);
bool AddDeps(BuilderRecord* record,
const LabelTargetVector& targets,
Err* err);
bool AddToolchainDep(BuilderRecord* record,
const Target* target,
Err* err);
// Given a target, sets the "should generate" bit and pushes it through the
// dependency tree. Any time the bit it set, we ensure that the given item is
// scheduled to be loaded.
//
// If the force flag is set, we'll ignore the current state of the record's
// should_generate flag, and set it on the dependents every time. This is
// used when defining a target: the "should generate" may have been set
// before the item was defined (if it is required by something that is
// required). In this case, we need to re-push the "should generate" flag
// to the item's dependencies.
void RecursiveSetShouldGenerate(BuilderRecord* record, bool force);
void ScheduleItemLoadIfNecessary(BuilderRecord* record);
// This takes a BuilderRecord with resolved depdencies, and fills in the
// target's Label*Vectors with the resolved pointers.
bool ResolveItem(BuilderRecord* record, Err* err);
// Fills in the pointers in the given vector based on the labels. We assume
// that everything should be resolved by this point, so will return an error
// if anything isn't found or if the type doesn't match.
bool ResolveDeps(LabelTargetVector* deps, Err* err);
bool ResolveConfigs(LabelConfigVector* configs, Err* err);
bool ResolveForwardDependentConfigs(Target* target, Err* err);
// Given a list of unresolved records, tries to find any circular
// dependencies and returns the string describing the problem. If no circular
// deps were found, returns the empty string.
std::string CheckForCircularDependencies(
const std::vector<const BuilderRecord*>& bad_records) const;
// Non owning pointer.
Loader* loader_;
// Owning pointers.
typedef base::hash_map<Label, BuilderRecord*> RecordMap;
RecordMap records_;
ResolvedCallback resolved_callback_;
DISALLOW_COPY_AND_ASSIGN(Builder);
};
#endif // TOOLS_GN_BUILDER_H_