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;
}