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 "gn/label.h" 12 #include "gn/label_ptr.h" 13 #include "gn/scope.h" 14 #include "gn/source_file.h" 15 #include "gn/substitution_list.h" 16 #include "gn/substitution_pattern.h" 17 18 class ParseNode; 19 class Pool; 20 class Target; 21 class Toolchain; 22 23 class CTool; 24 class GeneralTool; 25 class RustTool; 26 class BuiltinTool; 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 virtual BuiltinTool* AsBuiltin(); 67 virtual const BuiltinTool* AsBuiltin() const; 68 69 // Basic information --------------------------------------------------------- 70 defined_from()71 const ParseNode* defined_from() const { return defined_from_; } set_defined_from(const ParseNode * df)72 void set_defined_from(const ParseNode* df) { defined_from_ = df; } 73 name()74 const char* name() const { return name_; } 75 76 // Getters/setters ---------------------------------------------------------- 77 // 78 // After the tool has had its attributes set, the caller must call 79 // SetComplete(), at which point no other changes can be made. 80 81 // Command to run. command()82 const SubstitutionPattern& command() const { return command_; } set_command(SubstitutionPattern cmd)83 void set_command(SubstitutionPattern cmd) { 84 DCHECK(!complete_); 85 command_ = std::move(cmd); 86 } 87 88 // Launcher for the command (e.g. goma) command_launcher()89 const std::string& command_launcher() const { return command_launcher_; } 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 240 static const char* GetToolTypeForTargetFinalOutput(const Target* target); 241 242 protected: 243 explicit Tool(const char* t); 244 245 // Initialization functions ------------------------------------------------- 246 // 247 // Initialization methods used by InitTool(). If successful, will set the 248 // field and return true, otherwise will return false. Must be called before 249 // SetComplete(). 250 bool IsPatternInOutputList(const SubstitutionList& output_list, 251 const SubstitutionPattern& pattern) const; 252 bool ValidateSubstitutionList(const std::vector<const Substitution*>& list, 253 const Value* origin, 254 Err* err) const; 255 bool ValidateOutputs(Err* err) const; 256 bool ReadBool(Scope* scope, const char* var, bool* field, Err* err); 257 bool ReadString(Scope* scope, const char* var, std::string* field, Err* err); 258 bool ReadPattern(Scope* scope, 259 const char* var, 260 SubstitutionPattern* field, 261 Err* err); 262 bool ReadPatternList(Scope* scope, 263 const char* var, 264 SubstitutionList* field, 265 Err* err); 266 bool ReadLabel(Scope* scope, 267 const char* var, 268 const Label& current_toolchain, 269 LabelPtrPair<Pool>* field, 270 Err* err); 271 bool ReadOutputExtension(Scope* scope, Err* err); 272 273 const ParseNode* defined_from_ = nullptr; 274 const char* name_ = nullptr; 275 276 SubstitutionPattern command_; 277 std::string command_launcher_; 278 std::string default_output_extension_; 279 SubstitutionPattern default_output_dir_; 280 SubstitutionPattern depfile_; 281 SubstitutionPattern description_; 282 std::string framework_switch_; 283 std::string weak_framework_switch_; 284 std::string framework_dir_switch_; 285 std::string lib_switch_; 286 std::string lib_dir_switch_; 287 std::string swiftmodule_switch_; 288 std::string linker_arg_; 289 SubstitutionList outputs_; 290 SubstitutionList partial_outputs_; 291 SubstitutionList runtime_outputs_; 292 std::string output_prefix_; 293 bool restat_ = false; 294 SubstitutionPattern rspfile_; 295 SubstitutionPattern rspfile_content_; 296 LabelPtrPair<Pool> pool_; 297 298 bool complete_ = false; 299 300 SubstitutionBits substitution_bits_; 301 302 Tool(const Tool&) = delete; 303 Tool& operator=(const Tool&) = delete; 304 }; 305 306 #endif // TOOLS_GN_TOOL_H_ 307