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_framework_dir_switch("-Lframework=");
22 set_lib_dir_switch("-Lnative=");
23 set_lib_switch("-l");
24 set_linker_arg("-Clink-arg=");
25 set_dynamic_link_switch("-Clink-arg=-Bdynamic");
26 }
27
28 RustTool::~RustTool() = default;
29
AsRust()30 RustTool* RustTool::AsRust() {
31 return this;
32 }
AsRust() const33 const RustTool* RustTool::AsRust() const {
34 return this;
35 }
36
ValidateName(const char * name) const37 bool RustTool::ValidateName(const char* name) const {
38 return name == kRsToolBin || name == kRsToolCDylib || name == kRsToolDylib ||
39 name == kRsToolMacro || name == kRsToolRlib ||
40 name == kRsToolStaticlib;
41 }
42
MayLink() const43 bool RustTool::MayLink() const {
44 return name_ == kRsToolBin || name_ == kRsToolCDylib ||
45 name_ == kRsToolDylib || name_ == kRsToolMacro;
46 }
47
SetComplete()48 void RustTool::SetComplete() {
49 SetToolComplete();
50 }
51
GetSysroot() const52 std::string_view RustTool::GetSysroot() const {
53 return rust_sysroot_;
54 }
55
SetOutputExtension(const Value * value,std::string * var,Err * err)56 bool RustTool::SetOutputExtension(const Value* value,
57 std::string* var,
58 Err* err) {
59 DCHECK(!complete_);
60 if (!value)
61 return true; // Not present is fine.
62 if (!value->VerifyTypeIs(Value::STRING, err))
63 return false;
64 if (value->string_value().empty())
65 return true;
66
67 *var = std::move(value->string_value());
68 return true;
69 }
70
ReadOutputsPatternList(Scope * scope,const char * var,SubstitutionList * field,Err * err)71 bool RustTool::ReadOutputsPatternList(Scope* scope,
72 const char* var,
73 SubstitutionList* field,
74 Err* err) {
75 DCHECK(!complete_);
76 const Value* value = scope->GetValue(var, true);
77 if (!value)
78 return true; // Not present is fine.
79 if (!value->VerifyTypeIs(Value::LIST, err))
80 return false;
81
82 SubstitutionList list;
83 if (!list.Parse(*value, err))
84 return false;
85
86 // Validate the right kinds of patterns are used.
87 if (list.list().empty()) {
88 *err = Err(defined_from(), "\"outputs\" must be specified for this tool.");
89 return false;
90 }
91
92 for (const auto& cur_type : list.required_types()) {
93 if (!IsValidRustSubstitution(cur_type)) {
94 *err = Err(*value, "Pattern not valid here.",
95 "You used the pattern " + std::string(cur_type->name) +
96 " which is not valid\nfor this variable.");
97 return false;
98 }
99 }
100
101 *field = std::move(list);
102 return true;
103 }
104
InitTool(Scope * scope,Toolchain * toolchain,Err * err)105 bool RustTool::InitTool(Scope* scope, Toolchain* toolchain, Err* err) {
106 // Initialize default vars.
107 if (!Tool::InitTool(scope, toolchain, err)) {
108 return false;
109 }
110
111 // All Rust tools should have outputs.
112 if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) {
113 return false;
114 }
115
116 // Check for a sysroot. Sets an empty string when not explicitly set.
117 if (!ReadString(scope, "rust_sysroot", &rust_sysroot_, err)) {
118 return false;
119 }
120
121 if (MayLink()) {
122 if (!ReadString(scope, "dynamic_link_switch", &dynamic_link_switch_, err)) {
123 return false;
124 }
125 }
126
127 return true;
128 }
129
ValidateSubstitution(const Substitution * sub_type) const130 bool RustTool::ValidateSubstitution(const Substitution* sub_type) const {
131 if (MayLink())
132 return IsValidRustLinkerSubstitution(sub_type);
133 if (ValidateName(name_))
134 return IsValidRustSubstitution(sub_type);
135 NOTREACHED();
136 return false;
137 }
138