blob: e4e127d2ddc81fb2d2d84c570a2afc587acf996b [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 "tools/gn/rust_tool.h"
#include "tools/gn/rust_substitution_type.h"
#include "tools/gn/target.h"
const char* RustTool::kRsToolRustc = "rustc";
RustTool::RustTool(const char* n) : Tool(n), rlib_output_extension_(".rlib") {
CHECK(ValidateName(n));
}
RustTool::~RustTool() = default;
RustTool* RustTool::AsRust() {
return this;
}
const RustTool* RustTool::AsRust() const {
return this;
}
bool RustTool::ValidateName(const char* name) const {
return name_ == kRsToolRustc;
}
void RustTool::SetComplete() {
SetToolComplete();
}
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::ReadOutputExtensions(Scope* scope, Err* err) {
if (!SetOutputExtension(scope->GetValue("exe_output_extension", true),
&exe_output_extension_, err))
return false;
if (!SetOutputExtension(scope->GetValue("rlib_output_extension", true),
&rlib_output_extension_, err))
return false;
if (!SetOutputExtension(scope->GetValue("dylib_output_extension", true),
&dylib_output_extension_, err))
return false;
if (!SetOutputExtension(scope->GetValue("cdylib_output_extension", true),
&cdylib_output_extension_, err))
return false;
if (!SetOutputExtension(scope->GetValue("staticlib_output_extension", true),
&staticlib_output_extension_, err))
return false;
if (!SetOutputExtension(scope->GetValue("proc_macro_output_extension", true),
&proc_macro_output_extension_, err))
return false;
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;
}
if (!ReadOutputExtensions(scope, err)) {
return false;
}
// All Rust tools should have outputs.
if (!ReadOutputsPatternList(scope, "outputs", &outputs_, err)) {
return false;
}
return true;
}
bool RustTool::ValidateSubstitution(const Substitution* sub_type) const {
if (name_ == kRsToolRustc)
return IsValidRustSubstitution(sub_type);
NOTREACHED();
return false;
}
const std::string& RustTool::rustc_output_extension(
Target::OutputType type,
const RustValues::CrateType crate_type) const {
switch (crate_type) {
case RustValues::CRATE_AUTO: {
switch (type) {
case Target::EXECUTABLE:
return exe_output_extension_;
case Target::STATIC_LIBRARY:
return staticlib_output_extension_;
case Target::RUST_LIBRARY:
return rlib_output_extension_;
default:
NOTREACHED();
return exe_output_extension_;
}
}
case RustValues::CRATE_DYLIB:
return dylib_output_extension_;
case RustValues::CRATE_CDYLIB:
return cdylib_output_extension_;
case RustValues::CRATE_PROC_MACRO:
return proc_macro_output_extension_;
default:
NOTREACHED();
return exe_output_extension_;
}
}