| // 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 <functional> | |
| #include <map> | |
| #include <memory> | |
| #include <set> | |
| #include "base/memory/ref_counted.h" | |
| #include "tools/gn/label.h" | |
| #include "tools/gn/scope.h" | |
| #include "util/msg_loop.h" | |
| class BuildSettings; | |
| class LocationRange; | |
| 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 LocationRange& origin, | |
| 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, const LocationRange& origin); | |
| // 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* const kDefaultToolchainKey; | |
| protected: | |
| friend class base::RefCountedThreadSafe<Loader>; | |
| virtual ~Loader(); | |
| }; | |
| class LoaderImpl : public Loader { | |
| public: | |
| // Callback to emulate InputFileManager::AsyncLoadFile. | |
| using AsyncLoadFileCallback = | |
| std::function<bool(const LocationRange&, | |
| const BuildSettings*, | |
| const SourceFile&, | |
| std::function<void(const ParseNode*)>, | |
| Err*)>; | |
| explicit LoaderImpl(const BuildSettings* build_settings); | |
| // Loader implementation. | |
| void Load(const SourceFile& file, | |
| const LocationRange& origin, | |
| const Label& toolchain_name) override; | |
| void ToolchainLoaded(const Toolchain* toolchain) override; | |
| Label GetDefaultToolchain() const override; | |
| const Settings* GetToolchainSettings(const Label& label) const override; | |
| // Sets the task runner corresponding to the main thread. By default this | |
| // class will use the thread active during construction, but there is not | |
| // a task runner active during construction all the time. | |
| void set_task_runner(MsgLoop* task_runner) { task_runner_ = task_runner; } | |
| // 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(std::function<void()> cb) { | |
| complete_callback_ = std::move(cb); | |
| } | |
| // This callback is used when the loader finds it wants to load a file. | |
| void set_async_load_file(AsyncLoadFileCallback cb) { | |
| async_load_file_ = std::move(cb); | |
| } | |
| const Label& default_toolchain_label() const { | |
| return default_toolchain_label_; | |
| } | |
| private: | |
| struct LoadID; | |
| struct ToolchainRecord; | |
| ~LoaderImpl() override; | |
| // Schedules the input file manager to load the given file. | |
| void ScheduleLoadFile(const Settings* settings, | |
| const LocationRange& origin, | |
| 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 LocationRange& origin, | |
| 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, | |
| std::function<void(const ParseNode*)> callback, | |
| Err* err); | |
| MsgLoop* task_runner_; | |
| int pending_loads_; | |
| std::function<void()> complete_callback_; | |
| // When non-null, use this callback instead of the InputFileManager for | |
| // mocking purposes. | |
| AsyncLoadFileCallback async_load_file_; | |
| using LoadIDSet = std::set<LoadID>; | |
| LoadIDSet invocations_; | |
| const BuildSettings* build_settings_; | |
| Label default_toolchain_label_; | |
| // Records for the build config file loads. | |
| using ToolchainRecordMap = std::map<Label, std::unique_ptr<ToolchainRecord>>; | |
| ToolchainRecordMap toolchain_records_; | |
| }; | |
| #endif // TOOLS_GN_LOADER_H_ |