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