• 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   // Helper function that extracts the file and toolchain name from the given
54   // label, and calls Load().
55   void Load(const Label& label, const LocationRange& origin);
56 
57   // Returns the build file that the given label references.
58   static SourceFile BuildFileForLabel(const Label& label);
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 
91   // Sets the task runner corresponding to the main thread. By default this
92   // class will use the thread active during construction, but there is not
93   // a task runner active during construction all the time.
set_task_runner(MsgLoop * task_runner)94   void set_task_runner(MsgLoop* task_runner) { task_runner_ = task_runner; }
95 
96   // The complete callback is called whenever there are no more pending loads.
97   // Called on the main thread only. This may be called more than once if the
98   // queue is drained, but then more stuff gets added.
set_complete_callback(std::function<void ()> cb)99   void set_complete_callback(std::function<void()> cb) {
100     complete_callback_ = std::move(cb);
101   }
102 
103   // This callback is used when the loader finds it wants to load a file.
set_async_load_file(AsyncLoadFileCallback cb)104   void set_async_load_file(AsyncLoadFileCallback cb) {
105     async_load_file_ = std::move(cb);
106   }
107 
default_toolchain_label()108   const Label& default_toolchain_label() const {
109     return default_toolchain_label_;
110   }
111 
112  private:
113   struct LoadID;
114   struct ToolchainRecord;
115 
116   ~LoaderImpl() override;
117 
118   // Schedules the input file manager to load the given file.
119   void ScheduleLoadFile(const Settings* settings,
120                         const LocationRange& origin,
121                         const SourceFile& file);
122   void ScheduleLoadBuildConfig(Settings* settings,
123                                const Scope::KeyValueMap& toolchain_overrides);
124 
125   // Runs the given file on the background thread. These are called by the
126   // input file manager.
127   void BackgroundLoadFile(const Settings* settings,
128                           const SourceFile& file_name,
129                           const LocationRange& origin,
130                           const ParseNode* root);
131   void BackgroundLoadBuildConfig(Settings* settings,
132                                  const Scope::KeyValueMap& toolchain_overrides,
133                                  const ParseNode* root);
134 
135   // Posted to the main thread when any file other than a build config file
136   // file has completed running.
137   void DidLoadFile();
138 
139   // Posted to the main thread when any build config file has completed
140   // running. The label should be the name of the toolchain.
141   //
142   // If there is no defauled toolchain loaded yet, we'll assume that the first
143   // call to this indicates to the default toolchain, and this function will
144   // set the default toolchain name to the given label.
145   void DidLoadBuildConfig(const Label& label);
146 
147   // Decrements the pending_loads_ variable and issues the complete callback if
148   // necessary.
149   void DecrementPendingLoads();
150 
151   // Forwards to the appropriate location to load the file.
152   bool AsyncLoadFile(const LocationRange& origin,
153                      const BuildSettings* build_settings,
154                      const SourceFile& file_name,
155                      std::function<void(const ParseNode*)> callback,
156                      Err* err);
157 
158   MsgLoop* task_runner_;
159 
160   int pending_loads_;
161   std::function<void()> complete_callback_;
162 
163   // When non-null, use this callback instead of the InputFileManager for
164   // mocking purposes.
165   AsyncLoadFileCallback async_load_file_;
166 
167   using LoadIDSet = std::set<LoadID>;
168   LoadIDSet invocations_;
169 
170   const BuildSettings* build_settings_;
171   Label default_toolchain_label_;
172 
173   // Records for the build config file loads.
174   using ToolchainRecordMap = std::map<Label, std::unique_ptr<ToolchainRecord>>;
175   ToolchainRecordMap toolchain_records_;
176 };
177 
178 #endif  // TOOLS_GN_LOADER_H_
179