rust_library and Rust-specific variables Introduces a `rust_library` target that will generate `.rlib` files, and some associated Rust variables. Change-Id: I93b9dfeac17a7b21bf48bb792e7ca83c475707d8 Reviewed-on: https://gn-review.googlesource.com/c/gn/+/4882 Commit-Queue: Julie Hockett <juliehockett@google.com> Reviewed-by: Brett Wilson <brettw@google.com>
diff --git a/build/gen.py b/build/gen.py index 943f2e8..00752ee 100755 --- a/build/gen.py +++ b/build/gen.py
@@ -516,6 +516,8 @@ 'tools/gn/qt_creator_writer.cc', 'tools/gn/runtime_deps.cc', 'tools/gn/rust_substitution_type.cc', + 'tools/gn/rust_values.cc', + 'tools/gn/rust_variables.cc', 'tools/gn/scheduler.cc', 'tools/gn/scope.cc', 'tools/gn/scope_per_file_provider.cc',
diff --git a/tools/gn/binary_target_generator.cc b/tools/gn/binary_target_generator.cc index 1f568b4..5b01b62 100644 --- a/tools/gn/binary_target_generator.cc +++ b/tools/gn/binary_target_generator.cc
@@ -87,6 +87,7 @@ case SourceFile::SOURCE_O: case SourceFile::SOURCE_DEF: case SourceFile::SOURCE_GO: + case SourceFile::SOURCE_RS: case SourceFile::SOURCE_RC: // These are allowed. break;
diff --git a/tools/gn/rust_values.cc b/tools/gn/rust_values.cc new file mode 100644 index 0000000..08f3e5e --- /dev/null +++ b/tools/gn/rust_values.cc
@@ -0,0 +1,9 @@ +// 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_values.h" + +RustValues::RustValues() : crate_type_(RustValues::CRATE_AUTO) {} + +RustValues::~RustValues() = default; \ No newline at end of file
diff --git a/tools/gn/rust_values.h b/tools/gn/rust_values.h new file mode 100644 index 0000000..a4762fb --- /dev/null +++ b/tools/gn/rust_values.h
@@ -0,0 +1,63 @@ +// 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. + +#ifndef TOOLS_GN_RUST_TARGET_VALUES_H_ +#define TOOLS_GN_RUST_TARGET_VALUES_H_ + +#include <map> + +#include "base/containers/flat_map.h" +#include "tools/gn/label.h" +#include "tools/gn/source_file.h" + +// Holds the values (outputs, args, script name, etc.) for either an action or +// an action_foreach target. +class RustValues { + public: + RustValues(); + ~RustValues(); + + // Shared library crate types are specified here, all other crate types are + // automatically deduced from the target type (e.g. executables use crate_type + // = "bin", static_libraries use crate_type = "staticlib"). + enum CrateType { + CRATE_AUTO = 0, + CRATE_DYLIB, + CRATE_CDYLIB, + CRATE_PROC_MACRO, + }; + + // Name of this crate. + std::string& crate_name() { return crate_name_; } + const std::string& crate_name() const { return crate_name_; } + + // Main source file for this crate. + const SourceFile& crate_root() const { return crate_root_; } + void set_crate_root(SourceFile& s) { crate_root_ = s; } + + // Crate type for compilation. + CrateType crate_type() { return crate_type_; } + const CrateType crate_type() const { return crate_type_; } + void set_crate_type(CrateType s) { crate_type_ = s; } + + std::string& edition() { return edition_; } + const std::string& edition() const { return edition_; } + + // Any renamed dependencies for the `extern` flags. + const std::map<Label, std::string>& aliased_deps() const { + return aliased_deps_; + } + std::map<Label, std::string>& aliased_deps() { return aliased_deps_; } + + private: + std::string crate_name_; + SourceFile crate_root_; + CrateType crate_type_ = CRATE_AUTO; + std::string edition_; + std::map<Label, std::string> aliased_deps_; + + DISALLOW_COPY_AND_ASSIGN(RustValues); +}; + +#endif // TOOLS_GN_RUST_TARGET_VALUES_H_
diff --git a/tools/gn/rust_variables.cc b/tools/gn/rust_variables.cc new file mode 100644 index 0000000..67018c7 --- /dev/null +++ b/tools/gn/rust_variables.cc
@@ -0,0 +1,129 @@ +// 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_variables.h" + +namespace variables { + +// Rust target variables ------------------------------------------------------ + +const char kRustAliasedDeps[] = "aliased_deps"; +const char kRustAliasedDeps_HelpShort[] = + "aliased_deps: [scope] Set of crate-dependency pairs."; +const char kRustAliasedDeps_Help[] = + R"(aliased_deps: [scope] Set of crate-dependency pairs. + + Valid for `rust_library` targets and `executable`, `static_library`, and + `shared_library` targets that contain Rust sources. + + A scope, each key indicating the renamed crate and the corresponding value + specifying the label of the dependency producing the relevant binary. + + All dependencies listed in this field *must* be listed as deps of the target. + + executable("foo") { + sources = [ "main.rs" ] + deps = [ "//bar" ] + } + + This target would compile the `foo` crate with the following `extern` flag: + `rustc ...command... --extern bar=<build_out_dir>/obj/bar` + + executable("foo") { + sources = [ "main.rs" ] + deps = [ ":bar" ] + aliased_deps = { + bar_renamed = ":bar" + } + } + + With the addition of `aliased_deps`, above target would instead compile with: + `rustc ...command... --extern bar_renamed=<build_out_dir>/obj/bar` +)"; + +const char kRustCrateName[] = "crate_name"; +const char kRustCrateName_HelpShort[] = + "crate_name: [string] The name for the compiled crate."; +const char kRustCrateName_Help[] = + R"(crate_name: [string] The name for the compiled crate. + + Valid for `rust_library` targets and `executable`, `static_library`, + `shared_library`, and `source_set` targets that contain Rust sources. + + If crate_name is not set, then this rule will use the target name. +)"; + +const char kRustCrateType[] = "crate_type"; +const char kRustCrateType_HelpShort[] = + "crate_type: [string] The type of linkage to use on a shared_library."; +const char kRustCrateType_Help[] = + R"(crate_type: [string] The type of linkage to use on a shared_library. + + Valid for `rust_library` targets and `executable`, `static_library`, + `shared_library`, and `source_set` targets that contain Rust sources. + + Options for this field are "cdylib", "staticlib", "proc-macro", and "dylib". + This field sets the `crate-type` attribute for the `rustc` tool on static + libraries, as well as the appropiate output extension in the + `rust_output_extension` attribute. Since outputs must be explicit, the `lib` + crate type (where the Rust compiler produces what it thinks is the + appropriate library type) is not supported. + + It should be noted that the "dylib" crate type in Rust is unstable in the set + of symbols it exposes, and most usages today are potentially wrong and will + be broken in the future. + + Static libraries, rust libraries, and executables have this field set + automatically. +)"; + +const char kRustCrateRoot[] = "crate_root"; +const char kRustCrateRoot_HelpShort[] = + "crate_root: [string] The root source file for a binary or library."; +const char kRustCrateRoot_Help[] = + R"(crate_root: [string] The root source file for a binary or library. + + Valid for `rust_library` targets and `executable`, `static_library`, + `shared_library`, and `source_set` targets that contain Rust sources. + + This file is usually the `main.rs` or `lib.rs` for binaries and libraries, + respectively. + + If crate_root is not set, then this rule will look for a lib.rs file (or + main.rs for executable) or a single file in sources, if sources contains + only one file. +)"; + +const char kRustEdition[] = "edition"; +const char kRustEdition_HelpShort[] = + "edition: [string] The rustc edition to use in compiliation."; +const char kRustEdition_Help[] = + R"(edition: [string] The rustc edition to use in compiliation. + + Valid for `rust_library` targets and `executable`, `static_library`, + `shared_library`, and `source_set` targets that contain Rust sources. + + This indicates the compiler edition to use in compilition. Should be a value + like "2015" or "2018", indiicating the appropriate value to pass to the + `--edition=<>` flag in rustc. +)"; + +void InsertRustVariables(VariableInfoMap* info_map) { + info_map->insert(std::make_pair( + kRustAliasedDeps, + VariableInfo(kRustAliasedDeps_HelpShort, kRustAliasedDeps_Help))); + info_map->insert(std::make_pair( + kRustCrateName, + VariableInfo(kRustCrateName_HelpShort, kRustCrateName_Help))); + info_map->insert(std::make_pair( + kRustCrateType, + VariableInfo(kRustCrateType_HelpShort, kRustCrateType_Help))); + info_map->insert(std::make_pair( + kRustCrateRoot, + VariableInfo(kRustCrateRoot_HelpShort, kRustCrateRoot_Help))); + info_map->insert(std::make_pair( + kRustEdition, VariableInfo(kRustEdition_HelpShort, kRustEdition_Help))); +} + +} // namespace variables
diff --git a/tools/gn/rust_variables.h b/tools/gn/rust_variables.h new file mode 100644 index 0000000..c9ae4a0 --- /dev/null +++ b/tools/gn/rust_variables.h
@@ -0,0 +1,38 @@ +// 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. + +#ifndef TOOLS_GN_RUST_VARIABLES_H_ +#define TOOLS_GN_RUST_VARIABLES_H_ + +#include "tools/gn/variables.h" + +namespace variables { + +// Rust target vars ------------------------------------------------------ + +extern const char kRustAliasedDeps[]; +extern const char kRustAliasedDeps_HelpShort[]; +extern const char kRustAliasedDeps_Help[]; + +extern const char kRustCrateName[]; +extern const char kRustCrateName_HelpShort[]; +extern const char kRustCrateName_Help[]; + +extern const char kRustCrateType[]; +extern const char kRustCrateType_HelpShort[]; +extern const char kRustCrateType_Help[]; + +extern const char kRustCrateRoot[]; +extern const char kRustCrateRoot_HelpShort[]; +extern const char kRustCrateRoot_Help[]; + +extern const char kRustEdition[]; +extern const char kRustEdition_HelpShort[]; +extern const char kRustEdition_Help[]; + +void InsertRustVariables(VariableInfoMap* info_map); + +} // namespace variables + +#endif // TOOLS_GN_RUST_VARIABLES_H_ \ No newline at end of file
diff --git a/tools/gn/target.cc b/tools/gn/target.cc index 1afd22b..d48ffd9 100644 --- a/tools/gn/target.cc +++ b/tools/gn/target.cc
@@ -407,11 +407,12 @@ bool Target::IsBinary() const { return output_type_ == EXECUTABLE || output_type_ == SHARED_LIBRARY || output_type_ == LOADABLE_MODULE || output_type_ == STATIC_LIBRARY || - output_type_ == SOURCE_SET; + output_type_ == SOURCE_SET || output_type_ == RUST_LIBRARY; } bool Target::IsLinkable() const { - return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY; + return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY || + output_type_ == RUST_LIBRARY; } bool Target::IsFinal() const { @@ -419,7 +420,8 @@ output_type_ == LOADABLE_MODULE || output_type_ == ACTION || output_type_ == ACTION_FOREACH || output_type_ == COPY_FILES || output_type_ == CREATE_BUNDLE || - (output_type_ == STATIC_LIBRARY && complete_static_lib_); + (output_type_ == STATIC_LIBRARY && complete_static_lib_) || + output_type_ == RUST_LIBRARY; } DepsIteratorRange Target::GetDeps(DepsIterationType type) const { @@ -464,18 +466,18 @@ // Tool not specified for this target type. if (err) { - *err = Err( - defined_from(), "This target uses an undefined tool.", - base::StringPrintf( - "The target %s\n" - "of type \"%s\"\n" - "uses toolchain %s\n" - "which doesn't have the tool \"%s\" defined.\n\n" - "Alas, I can not continue.", - label().GetUserVisibleName(false).c_str(), - GetStringForOutputType(output_type_), - label().GetToolchainLabel().GetUserVisibleName(false).c_str(), - Tool::GetToolTypeForTargetFinalOutput(this))); + *err = + Err(defined_from(), "This target uses an undefined tool.", + base::StringPrintf( + "The target %s\n" + "of type \"%s\"\n" + "uses toolchain %s\n" + "which doesn't have the tool \"%s\" defined.\n\n" + "Alas, I can not continue.", + label().GetUserVisibleName(false).c_str(), + GetStringForOutputType(output_type_), + label().GetToolchainLabel().GetUserVisibleName(false).c_str(), + Tool::GetToolTypeForTargetFinalOutput(this))); } return false; } @@ -525,7 +527,8 @@ void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) { // Direct dependent libraries. if (dep->output_type() == STATIC_LIBRARY || - dep->output_type() == SHARED_LIBRARY || dep->output_type() == SOURCE_SET) + dep->output_type() == SHARED_LIBRARY || + dep->output_type() == SOURCE_SET || dep->output_type() == RUST_LIBRARY) inherited_libraries_.Append(dep, is_public); if (dep->output_type() == SHARED_LIBRARY) { @@ -550,7 +553,7 @@ // library. inherited_libraries_.AppendPublicSharedLibraries(dep->inherited_libraries(), is_public); - } else if (!dep->IsFinal()) { + } else if (!dep->IsFinal() || dep->output_type() == RUST_LIBRARY) { // The current target isn't linked, so propogate linked deps and // libraries up the dependency tree. inherited_libraries_.AppendInherited(dep->inherited_libraries(), is_public); @@ -571,7 +574,8 @@ } // Library settings are always inherited across static library boundaries. - if (!dep->IsFinal() || dep->output_type() == STATIC_LIBRARY) { + if (!dep->IsFinal() || dep->output_type() == STATIC_LIBRARY || + dep->output_type() == RUST_LIBRARY) { all_lib_dirs_.append(dep->all_lib_dirs()); all_libs_.append(dep->all_libs()); } @@ -667,6 +671,7 @@ this, tool, tool->runtime_outputs(), &runtime_outputs_); } break; + case RUST_LIBRARY: case STATIC_LIBRARY: // Static libraries both have dependencies and linking going off of the // first output.
diff --git a/tools/gn/target.h b/tools/gn/target.h index 1256818..60014d7 100644 --- a/tools/gn/target.h +++ b/tools/gn/target.h
@@ -23,6 +23,7 @@ #include "tools/gn/metadata.h" #include "tools/gn/ordered_set.h" #include "tools/gn/output_file.h" +#include "tools/gn/rust_values.h" #include "tools/gn/source_file.h" #include "tools/gn/toolchain.h" #include "tools/gn/unique_vector.h" @@ -47,6 +48,7 @@ BUNDLE_DATA, CREATE_BUNDLE, GENERATED_FILE, + RUST_LIBRARY, }; enum DepsIterationType { @@ -268,6 +270,9 @@ ActionValues& action_values() { return action_values_; } const ActionValues& action_values() const { return action_values_; } + RustValues& rust_values() { return rust_values_; } + const RustValues& rust_values() const { return rust_values_; } + const OrderedSet<SourceDir>& all_lib_dirs() const { return all_lib_dirs_; } const OrderedSet<LibFile>& all_libs() const { return all_libs_; } @@ -417,6 +422,9 @@ // Used for action[_foreach] targets. ActionValues action_values_; + // Used for Rust targets. + RustValues rust_values_; + // Toolchain used by this target. Null until target is resolved. const Toolchain* toolchain_;
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc index 234a2ca..43ef8a0 100644 --- a/tools/gn/variables.cc +++ b/tools/gn/variables.cc
@@ -4,6 +4,8 @@ #include "tools/gn/variables.h" +#include "tools/gn/rust_variables.h" + namespace variables { // Built-in variables ---------------------------------------------------------- @@ -1917,6 +1919,10 @@ static library or source set will have no effect on the executable or shared library they're linked into). + For Rust targets that do not specify a crate_root, then the crate_root will + look for a lib.rs file (or main.rs for executable) or a single file in + sources, if sources contains only one file. + Sources for non-binary targets action_foreach @@ -2203,6 +2209,7 @@ INSERT_VARIABLE(WriteValueContents) INSERT_VARIABLE(WriteRuntimeDeps) INSERT_VARIABLE(XcodeExtraAttributes) + InsertRustVariables(&info_map); } return info_map; }