| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gn/rust_tool.h" |
| |
| #include "gn/rust_substitution_type.h" |
| #include "gn/target.h" |
| |
| const char* RustTool::kRsToolBin = "rust_bin"; |
| const char* RustTool::kRsToolCDylib = "rust_cdylib"; |
| const char* RustTool::kRsToolDylib = "rust_dylib"; |
| const char* RustTool::kRsToolMacro = "rust_macro"; |
| const char* RustTool::kRsToolRlib = "rust_rlib"; |
| const char* RustTool::kRsToolStaticlib = "rust_staticlib"; |
| |
| RustTool::RustTool(const char* n) : Tool(n) { |
| CHECK(ValidateName(n)); |
| // TODO: should these be settable in toolchain definition? |
| set_framework_switch("-lframework="); |
| set_framework_dir_switch("-Lframework="); |
| set_lib_dir_switch("-Lnative="); |
| set_lib_switch("-l"); |
| set_linker_arg("-Clink-arg="); |
| set_dynamic_link_switch("-Clink-arg=-Bdynamic"); |
| } |
| |
| RustTool::~RustTool() = default; |
| |
| RustTool* RustTool::AsRust() { |
| return this; |
| } |
| const RustTool* RustTool::AsRust() const { |
| return this; |
| } |
| |
| bool RustTool::ValidateName(const char* name) const { |
| return name == kRsToolBin || name == kRsToolCDylib || name == kRsToolDylib || |
| name == kRsToolMacro || name == kRsToolRlib || |
| name == kRsToolStaticlib; |
| } |
| |
| bool RustTool::MayLink() const { |
| return name_ == kRsToolBin || name_ == kRsToolCDylib || name_ == kRsToolDylib || |
| name_ == kRsToolMacro; |
| } |
| |
| void RustTool::SetComplete() { |
| SetToolComplete(); |
| } |
| |
| std::string_view RustTool::GetSysroot() const { |
| return rust_sysroot_; |
| } |
| |
| bool RustTool::SetOutputExtension(const Value* value, |
| std::string* var, |
| Err* err) { |
| DCHECK(!complete_); |
| if (!value) |
| return true; // Not present is fine. |
| if (!value->VerifyTypeIs(Value::STRING, err)) |
| return false; |
| if (value->string_value().empty()) |
| return true; |
| |
| *var = std::move(value->string_value()); |
| return true; |
| } |
| |
| bool RustTool::ReadOutputsPatternList(Scope* scope, |
| const char* var, |
| SubstitutionList* field, |
| Err* err) { |
| DCHECK(!complete_); |
| const Value* value = scope->GetValue(var, true); |
| if (!value) |
| return true; // Not present is fine. |
| if (!value->VerifyTypeIs(Value::LIST, err)) |
| return false; |
| |
| SubstitutionList list; |
| if (!list.Parse(*value, err)) |
| return false; |
| |
| // Validate the right kinds of patterns are used. |
| if (list.list().empty()) { |
| *err = Err(defined_from(), "\"outputs\" must be specified for this tool."); |
| return false; |
| } |
| |
| for (const auto& cur_type : list.required_types()) { |
| if (!IsValidRustSubstitution(cur_type)) { |
| *err = Err(*value, "Pattern not valid here.", |
| "You used the pattern " + std::string(cur_type->name) + |
| " which is not valid\nfor this variable."); |
| return false; |
| } |
| } |
| |
| *field = std::move(list); |
| return true; |
| } |
| |
| bool RustTool::InitTool(Scope* scope, Toolchain* toolchain, Err* err) { |
| // Initialize default vars. |
| if (!Tool::InitTool(scope, toolchain, err)) { |
| return false; |
| } |
| |
| // All Rust tools should have outputs. |
| if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) { |
| return false; |
| } |
| |
| // Check for a sysroot. Sets an empty string when not explicitly set. |
| if (!ReadString(scope, "rust_sysroot", &rust_sysroot_, err)) { |
| return false; |
| } |
| |
| if (MayLink()) { |
| if (!ReadString(scope, "dynamic_link_switch", &dynamic_link_switch_, err)) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| bool RustTool::ValidateSubstitution(const Substitution* sub_type) const { |
| if (MayLink()) |
| return IsValidRustLinkerSubstitution(sub_type); |
| if (ValidateName(name_)) |
| return IsValidRustSubstitution(sub_type); |
| NOTREACHED(); |
| return false; |
| } |