1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_LOADER_H_ 6 #define TOOLS_GN_LOADER_H_ 7 8 #include <functional> 9 #include <map> 10 #include <memory> 11 #include <set> 12 13 #include "base/memory/ref_counted.h" 14 #include "gn/label.h" 15 #include "gn/scope.h" 16 #include "util/msg_loop.h" 17 18 class BuildSettings; 19 class LocationRange; 20 class Settings; 21 class SourceFile; 22 class Toolchain; 23 24 // The loader manages execution of the different build files. It receives 25 // requests (normally from the Builder) when new references are found, and also 26 // manages loading the build config files. 27 // 28 // This loader class is abstract so it can be mocked out for testing the 29 // Builder. 30 class Loader : public base::RefCountedThreadSafe<Loader> { 31 public: 32 Loader(); 33 34 // Loads the given file in the conext of the given toolchain. The initial 35 // call to this (the one that actually starts the generation) should have an 36 // empty toolchain name, which will trigger the load of the default build 37 // config. 38 virtual void Load(const SourceFile& file, 39 const LocationRange& origin, 40 const Label& toolchain_name) = 0; 41 42 // Notification that the given toolchain has loaded. This will unblock files 43 // waiting on this definition. 44 virtual void ToolchainLoaded(const Toolchain* toolchain) = 0; 45 46 // Returns the label of the default toolchain. 47 virtual Label GetDefaultToolchain() const = 0; 48 49 // Returns information about the toolchain with the given label. Will return 50 // false if we haven't processed this toolchain yet. 51 virtual const Settings* GetToolchainSettings(const Label& label) const = 0; 52 53 // Returns the build file that the given label references. 54 virtual SourceFile BuildFileForLabel(const Label& label) const = 0; 55 56 // Helper function that extracts the file and toolchain name from the given 57 // label, and calls Load(). 58 void Load(const Label& label, const LocationRange& origin); 59 60 // When processing the default build config, we want to capture the argument 61 // of set_default_build_config. The implementation of that function uses this 62 // constant as a property key to get the Label* out of the scope where the 63 // label should be stored. 64 static const void* const kDefaultToolchainKey; 65 66 protected: 67 friend class base::RefCountedThreadSafe<Loader>; 68 virtual ~Loader(); 69 }; 70 71 class LoaderImpl : public Loader { 72 public: 73 // Callback to emulate InputFileManager::AsyncLoadFile. 74 using AsyncLoadFileCallback = 75 std::function<bool(const LocationRange&, 76 const BuildSettings*, 77 const SourceFile&, 78 std::function<void(const ParseNode*)>, 79 Err*)>; 80 81 explicit LoaderImpl(const BuildSettings* build_settings); 82 83 // Loader implementation. 84 void Load(const SourceFile& file, 85 const LocationRange& origin, 86 const Label& toolchain_name) override; 87 void ToolchainLoaded(const Toolchain* toolchain) override; 88 Label GetDefaultToolchain() const override; 89 const Settings* GetToolchainSettings(const Label& label) const override; 90 SourceFile BuildFileForLabel(const Label& label) const override; 91 92 // Sets the task runner corresponding to the main thread. By default this 93 // class will use the thread active during construction, but there is not 94 // a task runner active during construction all the time. set_task_runner(MsgLoop * task_runner)95 void set_task_runner(MsgLoop* task_runner) { task_runner_ = task_runner; } 96 97 // The complete callback is called whenever there are no more pending loads. 98 // Called on the main thread only. This may be called more than once if the 99 // queue is drained, but then more stuff gets added. set_complete_callback(std::function<void ()> cb)100 void set_complete_callback(std::function<void()> cb) { 101 complete_callback_ = std::move(cb); 102 } 103 104 // This callback is used when the loader finds it wants to load a file. set_async_load_file(AsyncLoadFileCallback cb)105 void set_async_load_file(AsyncLoadFileCallback cb) { 106 async_load_file_ = std::move(cb); 107 } 108 109 // Sets the additional extension for build files in this build. 110 // The resulting file name will be "BUILD.<extension>.gn". set_build_file_extension(std::string extension)111 void set_build_file_extension(std::string extension) { 112 build_file_extension_ = "." + extension; 113 } 114 default_toolchain_label()115 const Label& default_toolchain_label() const { 116 return default_toolchain_label_; 117 } 118 119 private: 120 struct LoadID; 121 struct ToolchainRecord; 122 123 ~LoaderImpl() override; 124 125 // Schedules the input file manager to load the given file. 126 void ScheduleLoadFile(const Settings* settings, 127 const LocationRange& origin, 128 const SourceFile& file); 129 void ScheduleLoadBuildConfig(Settings* settings, 130 const Scope::KeyValueMap& toolchain_overrides); 131 132 // Runs the given file on the background thread. These are called by the 133 // input file manager. 134 void BackgroundLoadFile(const Settings* settings, 135 const SourceFile& file_name, 136 const LocationRange& origin, 137 const ParseNode* root); 138 void BackgroundLoadBuildConfig(Settings* settings, 139 const Scope::KeyValueMap& toolchain_overrides, 140 const ParseNode* root); 141 142 // Posted to the main thread when any file other than a build config file 143 // file has completed running. 144 void DidLoadFile(); 145 146 // Posted to the main thread when any build config file has completed 147 // running. The label should be the name of the toolchain. 148 // 149 // If there is no defauled toolchain loaded yet, we'll assume that the first 150 // call to this indicates to the default toolchain, and this function will 151 // set the default toolchain name to the given label. 152 void DidLoadBuildConfig(const Label& label); 153 154 // Decrements the pending_loads_ variable and issues the complete callback if 155 // necessary. 156 void DecrementPendingLoads(); 157 158 // Forwards to the appropriate location to load the file. 159 bool AsyncLoadFile(const LocationRange& origin, 160 const BuildSettings* build_settings, 161 const SourceFile& file_name, 162 std::function<void(const ParseNode*)> callback, 163 Err* err); 164 165 MsgLoop* task_runner_; 166 167 int pending_loads_; 168 std::function<void()> complete_callback_; 169 170 // When non-null, use this callback instead of the InputFileManager for 171 // mocking purposes. 172 AsyncLoadFileCallback async_load_file_; 173 174 using LoadIDSet = std::set<LoadID>; 175 LoadIDSet invocations_; 176 177 const BuildSettings* build_settings_; 178 Label default_toolchain_label_; 179 180 // Records for the build config file loads. 181 using ToolchainRecordMap = std::map<Label, std::unique_ptr<ToolchainRecord>>; 182 ToolchainRecordMap toolchain_records_; 183 184 std::string build_file_extension_; 185 }; 186 187 #endif // TOOLS_GN_LOADER_H_ 188