// 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_