• 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 <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