blob: 65ed27a22feb4668e83ee73dc7ee43c5792bb7ec [file] [log] [blame]
// 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;
}