• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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