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