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 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.
     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.
     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.
    102   void set_async_load_file(const AsyncLoadFileCallback& cb) {
    103     async_load_file_ = cb;
    104   }
    105 
    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