1 // Copyright 2014 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_TOOL_H_
6 #define TOOLS_GN_TOOL_H_
7 
8 #include <string>
9 
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "gn/label.h"
13 #include "gn/label_ptr.h"
14 #include "gn/scope.h"
15 #include "gn/source_file.h"
16 #include "gn/substitution_list.h"
17 #include "gn/substitution_pattern.h"
18 
19 class ParseNode;
20 class Pool;
21 class Target;
22 class Toolchain;
23 
24 class CTool;
25 class GeneralTool;
26 class RustTool;
27 
28 // To add a new Tool category, create a subclass implementing SetComplete()
29 // Add a new category to ToolCategories
30 // Add a GetAs* function
31 class Tool {
32  public:
33   static const char* kToolNone;
34 
35   virtual ~Tool();
36 
37   // Manual RTTI and required functions ---------------------------------------
38   //
39   // To implement a new tool category to compile binaries in a different way,
40   // inherit this class, implement the following functions, and add the
41   // appropriate ToolTypes and RTTI getters. New tools will also need to
42   // implement a corresponding class inheriting NinjaBinaryTargetWriter that
43   // does the actual rule writing.
44 
45   // Initialize tool from a scope. Child classes should override this function
46   // and call the parent.
47   bool InitTool(Scope* block_scope, Toolchain* toolchain, Err* err);
48 
49   // Validate the char* passed to the creation.
50   virtual bool ValidateName(const char* name) const = 0;
51 
52   // Called when the toolchain is saving this tool, after everything is filled
53   // in.
54   virtual void SetComplete() = 0;
55 
56   // Validate substitutions in this tool.
57   virtual bool ValidateSubstitution(const Substitution* sub_type) const = 0;
58 
59   // Manual RTTI
60   virtual CTool* AsC();
61   virtual const CTool* AsC() const;
62   virtual GeneralTool* AsGeneral();
63   virtual const GeneralTool* AsGeneral() const;
64   virtual RustTool* AsRust();
65   virtual const RustTool* AsRust() const;
66 
67   // Basic information ---------------------------------------------------------
68 
defined_from()69   const ParseNode* defined_from() const { return defined_from_; }
set_defined_from(const ParseNode * df)70   void set_defined_from(const ParseNode* df) { defined_from_ = df; }
71 
name()72   const char* name() const { return name_; }
73 
74   // Getters/setters ----------------------------------------------------------
75   //
76   // After the tool has had its attributes set, the caller must call
77   // SetComplete(), at which point no other changes can be made.
78 
79   // Command to run.
command()80   const SubstitutionPattern& command() const { return command_; }
set_command(SubstitutionPattern cmd)81   void set_command(SubstitutionPattern cmd) {
82     DCHECK(!complete_);
83     command_ = std::move(cmd);
84   }
85 
86   // Launcher for the command (e.g. goma)
command_launcher()87   const std::string& command_launcher() const {
88     return command_launcher_;
89   }
set_command_launcher(std::string l)90   void set_command_launcher(std::string l) {
91     DCHECK(!complete_);
92     command_launcher_ = std::move(l);
93   }
94 
95   // Should include a leading "." if nonempty.
default_output_extension()96   const std::string& default_output_extension() const {
97     return default_output_extension_;
98   }
set_default_output_extension(std::string ext)99   void set_default_output_extension(std::string ext) {
100     DCHECK(!complete_);
101     DCHECK(ext.empty() || ext[0] == '.');
102     default_output_extension_ = std::move(ext);
103   }
104 
default_output_dir()105   const SubstitutionPattern& default_output_dir() const {
106     return default_output_dir_;
107   }
set_default_output_dir(SubstitutionPattern dir)108   void set_default_output_dir(SubstitutionPattern dir) {
109     DCHECK(!complete_);
110     default_output_dir_ = std::move(dir);
111   }
112 
113   // Dependency file (if supported).
depfile()114   const SubstitutionPattern& depfile() const { return depfile_; }
set_depfile(SubstitutionPattern df)115   void set_depfile(SubstitutionPattern df) {
116     DCHECK(!complete_);
117     depfile_ = std::move(df);
118   }
119 
description()120   const SubstitutionPattern& description() const { return description_; }
set_description(SubstitutionPattern desc)121   void set_description(SubstitutionPattern desc) {
122     DCHECK(!complete_);
123     description_ = std::move(desc);
124   }
125 
framework_switch()126   const std::string& framework_switch() const { return framework_switch_; }
set_framework_switch(std::string s)127   void set_framework_switch(std::string s) {
128     DCHECK(!complete_);
129     framework_switch_ = std::move(s);
130   }
131 
weak_framework_switch()132   const std::string& weak_framework_switch() const {
133     return weak_framework_switch_;
134   }
set_weak_framework_switch(std::string s)135   void set_weak_framework_switch(std::string s) {
136     DCHECK(!complete_);
137     weak_framework_switch_ = std::move(s);
138   }
139 
framework_dir_switch()140   const std::string& framework_dir_switch() const {
141     return framework_dir_switch_;
142   }
set_framework_dir_switch(std::string s)143   void set_framework_dir_switch(std::string s) {
144     DCHECK(!complete_);
145     framework_dir_switch_ = std::move(s);
146   }
147 
lib_switch()148   const std::string& lib_switch() const { return lib_switch_; }
set_lib_switch(std::string s)149   void set_lib_switch(std::string s) {
150     DCHECK(!complete_);
151     lib_switch_ = std::move(s);
152   }
153 
lib_dir_switch()154   const std::string& lib_dir_switch() const { return lib_dir_switch_; }
set_lib_dir_switch(std::string s)155   void set_lib_dir_switch(std::string s) {
156     DCHECK(!complete_);
157     lib_dir_switch_ = std::move(s);
158   }
159 
swiftmodule_switch()160   const std::string& swiftmodule_switch() const { return swiftmodule_switch_; }
set_swiftmodule_switch(std::string s)161   void set_swiftmodule_switch(std::string s) {
162     DCHECK(!complete_);
163     swiftmodule_switch_ = std::move(s);
164   }
165 
linker_arg()166   const std::string& linker_arg() const { return linker_arg_; }
set_linker_arg(std::string s)167   void set_linker_arg(std::string s) {
168     DCHECK(!complete_);
169     linker_arg_ = std::move(s);
170   }
171 
outputs()172   const SubstitutionList& outputs() const { return outputs_; }
set_outputs(SubstitutionList out)173   void set_outputs(SubstitutionList out) {
174     DCHECK(!complete_);
175     outputs_ = std::move(out);
176   }
177 
partial_outputs()178   const SubstitutionList& partial_outputs() const { return partial_outputs_; }
set_partial_outputs(SubstitutionList partial_out)179   void set_partial_outputs(SubstitutionList partial_out) {
180     DCHECK(!complete_);
181     partial_outputs_ = std::move(partial_out);
182   }
183 
runtime_outputs()184   const SubstitutionList& runtime_outputs() const { return runtime_outputs_; }
set_runtime_outputs(SubstitutionList run_out)185   void set_runtime_outputs(SubstitutionList run_out) {
186     DCHECK(!complete_);
187     runtime_outputs_ = std::move(run_out);
188   }
189 
output_prefix()190   const std::string& output_prefix() const { return output_prefix_; }
set_output_prefix(std::string s)191   void set_output_prefix(std::string s) {
192     DCHECK(!complete_);
193     output_prefix_ = std::move(s);
194   }
195 
restat()196   bool restat() const { return restat_; }
set_restat(bool r)197   void set_restat(bool r) {
198     DCHECK(!complete_);
199     restat_ = r;
200   }
201 
rspfile()202   const SubstitutionPattern& rspfile() const { return rspfile_; }
set_rspfile(SubstitutionPattern rsp)203   void set_rspfile(SubstitutionPattern rsp) {
204     DCHECK(!complete_);
205     rspfile_ = std::move(rsp);
206   }
207 
rspfile_content()208   const SubstitutionPattern& rspfile_content() const {
209     return rspfile_content_;
210   }
set_rspfile_content(SubstitutionPattern content)211   void set_rspfile_content(SubstitutionPattern content) {
212     DCHECK(!complete_);
213     rspfile_content_ = std::move(content);
214   }
215 
pool()216   const LabelPtrPair<Pool>& pool() const { return pool_; }
set_pool(LabelPtrPair<Pool> pool)217   void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
218 
219   // Other functions ----------------------------------------------------------
220 
221   // Function for the above override to call to complete the tool.
222   void SetToolComplete();
223 
224   // Substitutions required by this tool.
substitution_bits()225   const SubstitutionBits& substitution_bits() const {
226     DCHECK(complete_);
227     return substitution_bits_;
228   }
229 
230   // Create a tool based on given features.
231   static std::unique_ptr<Tool> CreateTool(const std::string& name);
232   static std::unique_ptr<Tool> CreateTool(const ParseNode* function,
233                                           const std::string& name,
234                                           Scope* scope,
235                                           Toolchain* toolchain,
236                                           Err* err);
237 
238   static const char* GetToolTypeForSourceType(SourceFile::Type type);
239   static const char* GetToolTypeForTargetFinalOutput(const Target* target);
240 
241  protected:
242   explicit Tool(const char* t);
243 
244   // Initialization functions -------------------------------------------------
245   //
246   // Initialization methods used by InitTool(). If successful, will set the
247   // field and return true, otherwise will return false. Must be called before
248   // SetComplete().
249   bool IsPatternInOutputList(const SubstitutionList& output_list,
250                              const SubstitutionPattern& pattern) const;
251   bool ValidateSubstitutionList(const std::vector<const Substitution*>& list,
252                                 const Value* origin,
253                                 Err* err) const;
254   bool ValidateOutputs(Err* err) const;
255   bool ReadBool(Scope* scope, const char* var, bool* field, Err* err);
256   bool ReadString(Scope* scope, const char* var, std::string* field, Err* err);
257   bool ReadPattern(Scope* scope,
258                    const char* var,
259                    SubstitutionPattern* field,
260                    Err* err);
261   bool ReadPatternList(Scope* scope,
262                        const char* var,
263                        SubstitutionList* field,
264                        Err* err);
265   bool ReadLabel(Scope* scope,
266                  const char* var,
267                  const Label& current_toolchain,
268                  LabelPtrPair<Pool>* field,
269                  Err* err);
270   bool ReadOutputExtension(Scope* scope, Err* err);
271 
272   const ParseNode* defined_from_ = nullptr;
273   const char* name_ = nullptr;
274 
275   SubstitutionPattern command_;
276   std::string command_launcher_;
277   std::string default_output_extension_;
278   SubstitutionPattern default_output_dir_;
279   SubstitutionPattern depfile_;
280   SubstitutionPattern description_;
281   std::string framework_switch_;
282   std::string weak_framework_switch_;
283   std::string framework_dir_switch_;
284   std::string lib_switch_;
285   std::string lib_dir_switch_;
286   std::string swiftmodule_switch_;
287   std::string linker_arg_;
288   SubstitutionList outputs_;
289   SubstitutionList partial_outputs_;
290   SubstitutionList runtime_outputs_;
291   std::string output_prefix_;
292   bool restat_ = false;
293   SubstitutionPattern rspfile_;
294   SubstitutionPattern rspfile_content_;
295   LabelPtrPair<Pool> pool_;
296 
297   bool complete_ = false;
298 
299   SubstitutionBits substitution_bits_;
300 
301   DISALLOW_COPY_AND_ASSIGN(Tool);
302 };
303 
304 #endif  // TOOLS_GN_TOOL_H_
305