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