• 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 Settings;
22 class SourceFile;
23 class Toolchain;
24 
25 // The loader manages execution of the different build files. It receives
26 // requests (normally from the Builder) when new references are found, and also
27 // manages loading the build config files.
28 //
29 // This loader class is abstract so it can be mocked out for testing the
30 // Builder.
31 class Loader : public base::RefCountedThreadSafe<Loader> {
32  public:
33   Loader();
34 
35   // Loads the given file in the conext of the given toolchain. The initial
36   // call to this (the one that actually starts the generation) should have an
37   // empty toolchain name, which will trigger the load of the default build
38   // config.
39   virtual void Load(const SourceFile& file,
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) = 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);
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* 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   typedef base::Callback<bool(const LocationRange&,
75                               const BuildSettings*,
76                               const SourceFile&,
77                               const base::Callback<void(const ParseNode*)>&,
78                               Err*)> AsyncLoadFileCallback;
79 
80   LoaderImpl(const BuildSettings* build_settings);
81 
82   // Loader implementation.
83   virtual void Load(const SourceFile& file,
84                     const Label& toolchain_name) OVERRIDE;
85   virtual void ToolchainLoaded(const Toolchain* toolchain) OVERRIDE;
86   virtual Label GetDefaultToolchain() const OVERRIDE;
87   virtual const Settings* GetToolchainSettings(const Label& label) OVERRIDE;
88 
89   // Sets the message loop corresponding to the main thread. By default this
90   // class will use the thread active during construction, but there is not
91   // a message loop active during construction all the time.
set_main_loop(base::MessageLoop * loop)92   void set_main_loop(base::MessageLoop* loop) { main_loop_ = loop; }
93 
94   // The complete callback is called whenever there are no more pending loads.
95   // Called on the main thread only. This may be called more than once if the
96   // queue is drained, but then more stuff gets added.
set_complete_callback(const base::Closure & cb)97   void set_complete_callback(const base::Closure& cb) {
98     complete_callback_ = cb;
99   }
100 
101   // This callback is used when the loader finds it wants to load a file.
set_async_load_file(const AsyncLoadFileCallback & cb)102   void set_async_load_file(const AsyncLoadFileCallback& cb) {
103     async_load_file_ = cb;
104   }
105 
default_toolchain_label()106   const Label& default_toolchain_label() const {
107     return default_toolchain_label_;
108   }
109 
110  private:
111   struct LoadID;
112   struct ToolchainRecord;
113 
114   virtual ~LoaderImpl();
115 
116   // Schedules the input file manager to load the given file.
117   void ScheduleLoadFile(const Settings* settings,
118                         const SourceFile& file);
119   void ScheduleLoadBuildConfig(
120       Settings* settings,
121       const Scope::KeyValueMap& toolchain_overrides);
122 
123   // Runs the given file on the background thread. These are called by the
124   // input file manager.
125   void BackgroundLoadFile(const Settings* settings,
126                           const SourceFile& file_name,
127                           const ParseNode* root);
128   void BackgroundLoadBuildConfig(
129       Settings* settings,
130       const Scope::KeyValueMap& toolchain_overrides,
131       const ParseNode* root);
132 
133   // Posted to the main thread when any file other than a build config file
134   // file has completed running.
135   void DidLoadFile();
136 
137   // Posted to the main thread when any build config file has completed
138   // running. The label should be the name of the toolchain.
139   //
140   // If there is no defauled toolchain loaded yet, we'll assume that the first
141   // call to this indicates to the default toolchain, and this function will
142   // set the default toolchain name to the given label.
143   void DidLoadBuildConfig(const Label& label);
144 
145   // Decrements the pending_loads_ variable and issues the complete callback if
146   // necessary.
147   void DecrementPendingLoads();
148 
149   // Forwards to the appropriate location to load the file.
150   bool AsyncLoadFile(const LocationRange& origin,
151                      const BuildSettings* build_settings,
152                      const SourceFile& file_name,
153                      const base::Callback<void(const ParseNode*)>& callback,
154                      Err* err);
155 
156   base::MessageLoop* main_loop_;
157 
158   int pending_loads_;
159   base::Closure complete_callback_;
160 
161   // When non-null, use this callback instead of the InputFileManager for
162   // mocking purposes.
163   AsyncLoadFileCallback async_load_file_;
164 
165   typedef std::set<LoadID> LoadIDSet;
166   LoadIDSet invocations_;
167 
168   const BuildSettings* build_settings_;
169   Label default_toolchain_label_;
170 
171   // Records for the build config file loads.
172   // Owning pointers.
173   typedef std::map<Label, ToolchainRecord*> ToolchainRecordMap;
174   ToolchainRecordMap toolchain_records_;
175 };
176 
177 #endif  // TOOLS_GN_LOADER_H_
178