// 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_LOADER_H_ #define TOOLS_GN_LOADER_H_ #include <map> #include <set> #include "base/callback.h" #include "base/memory/ref_counted.h" #include "tools/gn/label.h" #include "tools/gn/scope.h" namespace base { class MessageLoop; } class BuildSettings; class Settings; class SourceFile; class Toolchain; // The loader manages execution of the different build files. It receives // requests (normally from the Builder) when new references are found, and also // manages loading the build config files. // // This loader class is abstract so it can be mocked out for testing the // Builder. class Loader : public base::RefCountedThreadSafe<Loader> { public: Loader(); // Loads the given file in the conext of the given toolchain. The initial // call to this (the one that actually starts the generation) should have an // empty toolchain name, which will trigger the load of the default build // config. virtual void Load(const SourceFile& file, const Label& toolchain_name) = 0; // Notification that the given toolchain has loaded. This will unblock files // waiting on this definition. virtual void ToolchainLoaded(const Toolchain* toolchain) = 0; // Returns the label of the default toolchain. virtual Label GetDefaultToolchain() const = 0; // Returns information about the toolchain with the given label. Will return // false if we haven't processed this toolchain yet. virtual const Settings* GetToolchainSettings(const Label& label) const = 0; // Helper function that extracts the file and toolchain name from the given // label, and calls Load(). void Load(const Label& label); // Returns the build file that the given label references. static SourceFile BuildFileForLabel(const Label& label); // When processing the default build config, we want to capture the argument // of set_default_build_config. The implementation of that function uses this // constant as a property key to get the Label* out of the scope where the // label should be stored. static const void* kDefaultToolchainKey; protected: friend class base::RefCountedThreadSafe<Loader>; virtual ~Loader(); }; class LoaderImpl : public Loader { public: // Callback to emulate InputFileManager::AsyncLoadFile. typedef base::Callback<bool(const LocationRange&, const BuildSettings*, const SourceFile&, const base::Callback<void(const ParseNode*)>&, Err*)> AsyncLoadFileCallback; LoaderImpl(const BuildSettings* build_settings); // Loader implementation. virtual void Load(const SourceFile& file, const Label& toolchain_name) OVERRIDE; virtual void ToolchainLoaded(const Toolchain* toolchain) OVERRIDE; virtual Label GetDefaultToolchain() const OVERRIDE; virtual const Settings* GetToolchainSettings( const Label& label) const OVERRIDE; // Sets the message loop corresponding to the main thread. By default this // class will use the thread active during construction, but there is not // a message loop active during construction all the time. void set_main_loop(base::MessageLoop* loop) { main_loop_ = loop; } // The complete callback is called whenever there are no more pending loads. // Called on the main thread only. This may be called more than once if the // queue is drained, but then more stuff gets added. void set_complete_callback(const base::Closure& cb) { complete_callback_ = cb; } // This callback is used when the loader finds it wants to load a file. void set_async_load_file(const AsyncLoadFileCallback& cb) { async_load_file_ = cb; } const Label& default_toolchain_label() const { return default_toolchain_label_; } private: struct LoadID; struct ToolchainRecord; virtual ~LoaderImpl(); // Schedules the input file manager to load the given file. void ScheduleLoadFile(const Settings* settings, const SourceFile& file); void ScheduleLoadBuildConfig( Settings* settings, const Scope::KeyValueMap& toolchain_overrides); // Runs the given file on the background thread. These are called by the // input file manager. void BackgroundLoadFile(const Settings* settings, const SourceFile& file_name, const ParseNode* root); void BackgroundLoadBuildConfig( Settings* settings, const Scope::KeyValueMap& toolchain_overrides, const ParseNode* root); // Posted to the main thread when any file other than a build config file // file has completed running. void DidLoadFile(); // Posted to the main thread when any build config file has completed // running. The label should be the name of the toolchain. // // If there is no defauled toolchain loaded yet, we'll assume that the first // call to this indicates to the default toolchain, and this function will // set the default toolchain name to the given label. void DidLoadBuildConfig(const Label& label); // Decrements the pending_loads_ variable and issues the complete callback if // necessary. void DecrementPendingLoads(); // Forwards to the appropriate location to load the file. bool AsyncLoadFile(const LocationRange& origin, const BuildSettings* build_settings, const SourceFile& file_name, const base::Callback<void(const ParseNode*)>& callback, Err* err); base::MessageLoop* main_loop_; int pending_loads_; base::Closure complete_callback_; // When non-null, use this callback instead of the InputFileManager for // mocking purposes. AsyncLoadFileCallback async_load_file_; typedef std::set<LoadID> LoadIDSet; LoadIDSet invocations_; const BuildSettings* build_settings_; Label default_toolchain_label_; // Records for the build config file loads. // Owning pointers. typedef std::map<Label, ToolchainRecord*> ToolchainRecordMap; ToolchainRecordMap toolchain_records_; }; #endif // TOOLS_GN_LOADER_H_