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 framework_dir_switch()132 const std::string& framework_dir_switch() const { 133 return framework_dir_switch_; 134 } set_framework_dir_switch(std::string s)135 void set_framework_dir_switch(std::string s) { 136 DCHECK(!complete_); 137 framework_dir_switch_ = std::move(s); 138 } 139 lib_switch()140 const std::string& lib_switch() const { return lib_switch_; } set_lib_switch(std::string s)141 void set_lib_switch(std::string s) { 142 DCHECK(!complete_); 143 lib_switch_ = std::move(s); 144 } 145 lib_dir_switch()146 const std::string& lib_dir_switch() const { return lib_dir_switch_; } set_lib_dir_switch(std::string s)147 void set_lib_dir_switch(std::string s) { 148 DCHECK(!complete_); 149 lib_dir_switch_ = std::move(s); 150 } 151 linker_arg()152 const std::string& linker_arg() const { return linker_arg_; } set_linker_arg(std::string s)153 void set_linker_arg(std::string s) { 154 DCHECK(!complete_); 155 linker_arg_ = std::move(s); 156 } 157 outputs()158 const SubstitutionList& outputs() const { return outputs_; } set_outputs(SubstitutionList out)159 void set_outputs(SubstitutionList out) { 160 DCHECK(!complete_); 161 outputs_ = std::move(out); 162 } 163 runtime_outputs()164 const SubstitutionList& runtime_outputs() const { return runtime_outputs_; } set_runtime_outputs(SubstitutionList run_out)165 void set_runtime_outputs(SubstitutionList run_out) { 166 DCHECK(!complete_); 167 runtime_outputs_ = std::move(run_out); 168 } 169 output_prefix()170 const std::string& output_prefix() const { return output_prefix_; } set_output_prefix(std::string s)171 void set_output_prefix(std::string s) { 172 DCHECK(!complete_); 173 output_prefix_ = std::move(s); 174 } 175 restat()176 bool restat() const { return restat_; } set_restat(bool r)177 void set_restat(bool r) { 178 DCHECK(!complete_); 179 restat_ = r; 180 } 181 rspfile()182 const SubstitutionPattern& rspfile() const { return rspfile_; } set_rspfile(SubstitutionPattern rsp)183 void set_rspfile(SubstitutionPattern rsp) { 184 DCHECK(!complete_); 185 rspfile_ = std::move(rsp); 186 } 187 rspfile_content()188 const SubstitutionPattern& rspfile_content() const { 189 return rspfile_content_; 190 } set_rspfile_content(SubstitutionPattern content)191 void set_rspfile_content(SubstitutionPattern content) { 192 DCHECK(!complete_); 193 rspfile_content_ = std::move(content); 194 } 195 pool()196 const LabelPtrPair<Pool>& pool() const { return pool_; } set_pool(LabelPtrPair<Pool> pool)197 void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); } 198 199 // Other functions ---------------------------------------------------------- 200 201 // Function for the above override to call to complete the tool. 202 void SetToolComplete(); 203 204 // Substitutions required by this tool. substitution_bits()205 const SubstitutionBits& substitution_bits() const { 206 DCHECK(complete_); 207 return substitution_bits_; 208 } 209 210 // Create a tool based on given features. 211 static std::unique_ptr<Tool> CreateTool(const std::string& name); 212 static std::unique_ptr<Tool> CreateTool(const ParseNode* function, 213 const std::string& name, 214 Scope* scope, 215 Toolchain* toolchain, 216 Err* err); 217 218 static const char* GetToolTypeForSourceType(SourceFile::Type type); 219 static const char* GetToolTypeForTargetFinalOutput(const Target* target); 220 221 protected: 222 explicit Tool(const char* t); 223 224 // Initialization functions ------------------------------------------------- 225 // 226 // Initialization methods used by InitTool(). If successful, will set the 227 // field and return true, otherwise will return false. Must be called before 228 // SetComplete(). 229 bool IsPatternInOutputList(const SubstitutionList& output_list, 230 const SubstitutionPattern& pattern) const; 231 bool ValidateSubstitutionList(const std::vector<const Substitution*>& list, 232 const Value* origin, 233 Err* err) const; 234 bool ValidateOutputs(Err* err) const; 235 bool ReadBool(Scope* scope, const char* var, bool* field, Err* err); 236 bool ReadString(Scope* scope, const char* var, std::string* field, Err* err); 237 bool ReadPattern(Scope* scope, 238 const char* var, 239 SubstitutionPattern* field, 240 Err* err); 241 bool ReadPatternList(Scope* scope, 242 const char* var, 243 SubstitutionList* field, 244 Err* err); 245 bool ReadLabel(Scope* scope, 246 const char* var, 247 const Label& current_toolchain, 248 LabelPtrPair<Pool>* field, 249 Err* err); 250 bool ReadOutputExtension(Scope* scope, Err* err); 251 252 const ParseNode* defined_from_ = nullptr; 253 const char* name_ = nullptr; 254 255 SubstitutionPattern command_; 256 std::string command_launcher_; 257 std::string default_output_extension_; 258 SubstitutionPattern default_output_dir_; 259 SubstitutionPattern depfile_; 260 SubstitutionPattern description_; 261 std::string framework_switch_; 262 std::string framework_dir_switch_; 263 std::string lib_switch_; 264 std::string lib_dir_switch_; 265 std::string linker_arg_; 266 SubstitutionList outputs_; 267 SubstitutionList runtime_outputs_; 268 std::string output_prefix_; 269 bool restat_ = false; 270 SubstitutionPattern rspfile_; 271 SubstitutionPattern rspfile_content_; 272 LabelPtrPair<Pool> pool_; 273 274 bool complete_ = false; 275 276 SubstitutionBits substitution_bits_; 277 278 DISALLOW_COPY_AND_ASSIGN(Tool); 279 }; 280 281 #endif // TOOLS_GN_TOOL_H_ 282