Home | History | Annotate | Download | only in gn
      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.
     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.
    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.
    106   void set_async_load_file(const AsyncLoadFileCallback& cb) {
    107     async_load_file_ = cb;
    108   }
    109 
    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