1 // Copyright 2019 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 #include "gn/rust_tool.h"
6
7 #include "gn/rust_substitution_type.h"
8 #include "gn/target.h"
9
10 const char* RustTool::kRsToolBin = "rust_bin";
11 const char* RustTool::kRsToolCDylib = "rust_cdylib";
12 const char* RustTool::kRsToolDylib = "rust_dylib";
13 const char* RustTool::kRsToolMacro = "rust_macro";
14 const char* RustTool::kRsToolRlib = "rust_rlib";
15 const char* RustTool::kRsToolStaticlib = "rust_staticlib";
16
RustTool(const char * n)17 RustTool::RustTool(const char* n) : Tool(n) {
18 CHECK(ValidateName(n));
19 // TODO: should these be settable in toolchain definition?
20 set_framework_switch("-lframework=");
21 set_lib_dir_switch("-Lnative=");
22 set_lib_switch("-l");
23 set_linker_arg("-Clink-arg=");
24 }
25
26 RustTool::~RustTool() = default;
27
AsRust()28 RustTool* RustTool::AsRust() {
29 return this;
30 }
AsRust() const31 const RustTool* RustTool::AsRust() const {
32 return this;
33 }
34
ValidateName(const char * name) const35 bool RustTool::ValidateName(const char* name) const {
36 return name == kRsToolBin || name == kRsToolCDylib || name == kRsToolDylib ||
37 name == kRsToolMacro || name == kRsToolRlib ||
38 name == kRsToolStaticlib;
39 }
40
MayLink() const41 bool RustTool::MayLink() const {
42 return name_ == kRsToolBin || name_ == kRsToolCDylib || name_ == kRsToolDylib ||
43 name_ == kRsToolMacro;
44 }
45
SetComplete()46 void RustTool::SetComplete() {
47 SetToolComplete();
48 }
49
GetSysroot() const50 std::string_view RustTool::GetSysroot() const {
51 return rust_sysroot_;
52 }
53
SetOutputExtension(const Value * value,std::string * var,Err * err)54 bool RustTool::SetOutputExtension(const Value* value,
55 std::string* var,
56 Err* err) {
57 DCHECK(!complete_);
58 if (!value)
59 return true; // Not present is fine.
60 if (!value->VerifyTypeIs(Value::STRING, err))
61 return false;
62 if (value->string_value().empty())
63 return true;
64
65 *var = std::move(value->string_value());
66 return true;
67 }
68
ReadOutputsPatternList(Scope * scope,const char * var,SubstitutionList * field,Err * err)69 bool RustTool::ReadOutputsPatternList(Scope* scope,
70 const char* var,
71 SubstitutionList* field,
72 Err* err) {
73 DCHECK(!complete_);
74 const Value* value = scope->GetValue(var, true);
75 if (!value)
76 return true; // Not present is fine.
77 if (!value->VerifyTypeIs(Value::LIST, err))
78 return false;
79
80 SubstitutionList list;
81 if (!list.Parse(*value, err))
82 return false;
83
84 // Validate the right kinds of patterns are used.
85 if (list.list().empty()) {
86 *err = Err(defined_from(), "\"outputs\" must be specified for this tool.");
87 return false;
88 }
89
90 for (const auto& cur_type : list.required_types()) {
91 if (!IsValidRustSubstitution(cur_type)) {
92 *err = Err(*value, "Pattern not valid here.",
93 "You used the pattern " + std::string(cur_type->name) +
94 " which is not valid\nfor this variable.");
95 return false;
96 }
97 }
98
99 *field = std::move(list);
100 return true;
101 }
102
InitTool(Scope * scope,Toolchain * toolchain,Err * err)103 bool RustTool::InitTool(Scope* scope, Toolchain* toolchain, Err* err) {
104 // Initialize default vars.
105 if (!Tool::InitTool(scope, toolchain, err)) {
106 return false;
107 }
108
109 // All Rust tools should have outputs.
110 if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) {
111 return false;
112 }
113
114 // Check for a sysroot. Sets an empty string when not explicitly set.
115 if (!ReadString(scope, "rust_sysroot", &rust_sysroot_, err)) {
116 return false;
117 }
118 return true;
119 }
120
ValidateSubstitution(const Substitution * sub_type) const121 bool RustTool::ValidateSubstitution(const Substitution* sub_type) const {
122 if (MayLink())
123 return IsValidRustLinkerSubstitution(sub_type);
124 if (ValidateName(name_))
125 return IsValidRustSubstitution(sub_type);
126 NOTREACHED();
127 return false;
128 }
129