[rust project] Extract compiler target
Extract the compiler arguments, and then from them, the compilation
target triple that is being passed to rustc.
This is also a step towards deduplicating targets by compilation
target and options (combining test and non-test, and preferring
cross-compilation targets over the host (default toolchain over
a separate toolchain, if there are multiple listings of the same
rlib/binary/test.
Change-Id: I1af0ef2da5dca41729e9367389048a068efd7959
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/8840
Commit-Queue: Aaron Wood <aaronwood@google.com>
Reviewed-by: Tyler Mandry <tmandry@google.com>
diff --git a/src/gn/rust_project_writer.cc b/src/gn/rust_project_writer.cc
index 21ac261..7bd0561 100644
--- a/src/gn/rust_project_writer.cc
+++ b/src/gn/rust_project_writer.cc
@@ -5,6 +5,7 @@
#include "gn/rust_project_writer.h"
#include <fstream>
+#include <optional>
#include <sstream>
#include <tuple>
@@ -44,7 +45,9 @@
// "unix", // "atomic" value config options
// "rust_panic=\"abort\""", // key="value" config options
// ]
-// "root_module": "absolute path to crate"
+// "root_module": "absolute path to crate",
+// "label": "//path/target:value", // GN target for the crate
+// "target": "x86_64-unknown-linux" // optional rustc target
// },
// }
//
@@ -105,8 +108,62 @@
return deps;
}
-// TODO(bwb) Parse sysroot structure from toml files. This is fragile and might
-// break if upstream changes the dependency structure.
+std::vector<std::string> ExtractCompilerArgs(const Target* target) {
+ std::vector<std::string> args;
+ for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
+ auto rustflags = iter.cur().rustflags();
+ for (auto flag_iter = rustflags.begin(); flag_iter != rustflags.end();
+ flag_iter++) {
+ args.push_back(*flag_iter);
+ }
+ }
+ return args;
+}
+
+std::optional<std::string> FindArgValue(const char* arg,
+ const std::vector<std::string>& args) {
+ for (auto current = args.begin(); current != args.end();) {
+ // capture the current value
+ auto previous = *current;
+ // and increment
+ current++;
+
+ // if the previous argument matches `arg`, and after the above increment the
+ // end hasn't been reached, this current argument is the desired value.
+ if (previous == arg && current != args.end()) {
+ return std::make_optional(*current);
+ }
+ }
+ return std::nullopt;
+}
+
+std::optional<std::string> FindArgValueAfterPrefix(
+ const std::string& prefix,
+ const std::vector<std::string>& args) {
+ for (auto arg : args) {
+ if (!arg.compare(0, prefix.size(), prefix)) {
+ auto value = arg.substr(prefix.size());
+ return std::make_optional(value);
+ }
+ }
+ return std::nullopt;
+}
+
+std::vector<std::string> FindAllArgValuesAfterPrefix(
+ const std::string& prefix,
+ const std::vector<std::string>& args) {
+ std::vector<std::string> values;
+ for (auto arg : args) {
+ if (!arg.compare(0, prefix.size(), prefix)) {
+ auto value = arg.substr(prefix.size());
+ values.push_back(value);
+ }
+ }
+ return values;
+}
+
+// TODO(bwb) Parse sysroot structure from toml files. This is fragile and
+// might break if upstream changes the dependency structure.
const std::string_view sysroot_crates[] = {"std",
"core",
"alloc",
@@ -218,6 +275,9 @@
return;
}
+ auto compiler_args = ExtractCompilerArgs(target);
+ auto compiler_target = FindArgValue("--target", compiler_args);
+
// Check what sysroot this target needs. Add it to the crate list if it
// hasn't already been added.
auto rust_tool =
@@ -243,28 +303,21 @@
SourceFile crate_root = target->rust_values().crate_root();
std::string crate_label = target->label().GetUserVisibleName(false);
- std::string cfg_prefix("--cfg=");
- std::string edition_prefix("--edition=");
- ConfigList cfgs;
-
- std::string edition = "2015"; // default to be overridden as needed
-
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
- for (const auto& flag : iter.cur().rustflags()) {
- // extract the edition of this target
- if (!flag.compare(0, edition_prefix.size(), edition_prefix)) {
- edition = flag.substr(edition_prefix.size());
- }
- if (!flag.compare(0, cfg_prefix.size(), cfg_prefix)) {
- auto cfg = flag.substr(cfg_prefix.size());
- std::string escaped_config;
- base::EscapeJSONString(cfg, false, &escaped_config);
- cfgs.push_back(escaped_config);
- }
- }
+ auto edition =
+ FindArgValueAfterPrefix(std::string("--edition="), compiler_args);
+ if (!edition.has_value()) {
+ edition = FindArgValue("--edition", compiler_args);
}
- Crate crate = Crate(crate_root, crate_id, crate_label, edition);
+ Crate crate =
+ Crate(crate_root, crate_id, crate_label, edition.value_or("2015"));
+
+ crate.SetCompilerArgs(compiler_args);
+ if (compiler_target.has_value())
+ crate.SetCompilerTarget(compiler_target.value());
+
+ ConfigList cfgs =
+ FindAllArgValuesAfterPrefix(std::string("--cfg="), compiler_args);
crate.AddConfigItem("test");
crate.AddConfigItem("debug_assertions");
@@ -293,17 +346,22 @@
void WriteCrates(const BuildSettings* build_settings,
CrateList& crate_list,
std::ostream& rust_project) {
+ // produce a de-duplicated set of source roots:
+ std::set<std::string> roots;
+ for (auto& crate : crate_list) {
+ roots.insert(
+ FilePathToUTF8(build_settings->GetFullPath(crate.root().GetDir())));
+ }
+
rust_project << "{" NEWLINE;
rust_project << " \"roots\": [";
bool first_root = true;
- for (auto& crate : crate_list) {
+ for (auto& root : roots) {
if (!first_root)
rust_project << ",";
first_root = false;
- std::string root_dir =
- FilePathToUTF8(build_settings->GetFullPath(crate.root().GetDir()));
- rust_project << NEWLINE " \"" << root_dir << "\"";
+ rust_project << NEWLINE " \"" << root << "\"";
}
rust_project << NEWLINE " ]," NEWLINE;
rust_project << " \"crates\": [";
@@ -313,14 +371,38 @@
rust_project << ",";
first_crate = false;
- auto crate_root = FilePathToUTF8(build_settings->GetFullPath(crate.root()));
+ auto crate_module =
+ FilePathToUTF8(build_settings->GetFullPath(crate.root()));
rust_project << NEWLINE << " {" NEWLINE
<< " \"crate_id\": " << crate.index() << "," NEWLINE
- << " \"root_module\": \"" << crate_root << "\"," NEWLINE
- << " \"label\": \"" << crate.label() << "\"," NEWLINE
- << " \"deps\": [";
+ << " \"root_module\": \"" << crate_module << "\"," NEWLINE
+ << " \"label\": \"" << crate.label() << "\"," NEWLINE;
+ auto compiler_target = crate.CompilerTarget();
+ if (compiler_target.has_value()) {
+ rust_project << " \"target\": \"" << compiler_target.value()
+ << "\"," NEWLINE;
+ }
+
+ auto compiler_args = crate.CompilerArgs();
+ if (!compiler_args.empty()) {
+ rust_project << " \"compiler_args\": [";
+ bool first_arg = true;
+ for (auto& arg : crate.CompilerArgs()) {
+ if (!first_arg)
+ rust_project << ", ";
+ first_arg = false;
+
+ std::string escaped_arg;
+ base::EscapeJSONString(arg, false, &escaped_arg);
+
+ rust_project << "\"" << escaped_arg << "\"";
+ }
+ rust_project << "]," << NEWLINE;
+ }
+
+ rust_project << " \"deps\": [";
bool first_dep = true;
for (auto& dep : crate.dependencies()) {
if (!first_dep)
@@ -343,8 +425,11 @@
rust_project << ",";
first_cfg = false;
+ std::string escaped_config;
+ base::EscapeJSONString(cfg, false, &escaped_config);
+
rust_project << NEWLINE;
- rust_project << " \"" << cfg << "\"";
+ rust_project << " \"" << escaped_config << "\"";
}
rust_project << NEWLINE;
rust_project << " ]" NEWLINE; // end cfgs
diff --git a/src/gn/rust_project_writer_helpers.h b/src/gn/rust_project_writer_helpers.h
index 25340b3..0020e2c 100644
--- a/src/gn/rust_project_writer_helpers.h
+++ b/src/gn/rust_project_writer_helpers.h
@@ -6,6 +6,7 @@
#define TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
#include <fstream>
+#include <optional>
#include <sstream>
#include <string>
#include <tuple>
@@ -47,6 +48,12 @@
deps_.push_back(std::make_pair(index, name));
}
+ // Set the compiler arguments used to invoke the compilation of this crate
+ void SetCompilerArgs(std::vector<std::string> args) { compiler_args_ = args; }
+
+ // Set the compiler target ("e.g. x86_64-linux-kernel")
+ void SetCompilerTarget(std::string target) { compiler_target_ = target; }
+
// Returns the root file for the crate.
SourceFile& root() { return root_; }
@@ -65,6 +72,14 @@
// Return the set of dependencies for this crate.
DependencyList& dependencies() { return deps_; }
+ // Return the compiler arguments used to invoke the compilation of this crate
+ const std::vector<std::string>& CompilerArgs() { return compiler_args_; }
+
+ // Return the compiler target "triple" from the compiler args
+ const std::optional<std::string>& CompilerTarget() {
+ return compiler_target_;
+ }
+
private:
SourceFile root_;
CrateIndex index_;
@@ -72,6 +87,8 @@
std::string edition_;
ConfigList configs_;
DependencyList deps_;
+ std::optional<std::string> compiler_target_;
+ std::vector<std::string> compiler_args_;
};
using CrateList = std::vector<Crate>;
@@ -97,4 +114,27 @@
CrateList& crate_list,
std::ostream& rust_project);
+// Assemble the compiler arguments for the given GN Target.
+std::vector<std::string> ExtractCompilerArgs(const Target* target);
+
+// Find the value of an argument that's passed to the compiler as two
+// consecutive strings in the list of arguments: ["arg", "value"]
+std::optional<std::string> FindArgValue(const char* arg,
+ const std::vector<std::string>& args);
+
+// Find the first argument that matches the prefix, returning the value after
+// the prefix. e.g. ˝--arg=value", is returned as "value" if the prefix
+// "--arg=" is used.
+std::optional<std::string> FindArgValueAfterPrefix(
+ const std::string& prefix,
+ const std::vector<std::string>& args);
+
+// Find all arguments that match the given prefix, returning the value after
+// the prefix for each one. e.g. "--cfg=value" is returned as "value" if the
+// prefix "--cfg=" is used.
+std::vector<std::string> FindAllArgValuesAfterPrefix(
+ const std::string& prefix,
+ const std::vector<std::string>& args);
+
+
#endif // TOOLS_GN_RUST_PROJECT_WRITER_HELPERS_H_
diff --git a/src/gn/rust_project_writer_helpers_unittest.cc b/src/gn/rust_project_writer_helpers_unittest.cc
index 23657ee..c19e709 100644
--- a/src/gn/rust_project_writer_helpers_unittest.cc
+++ b/src/gn/rust_project_writer_helpers_unittest.cc
@@ -18,11 +18,13 @@
TestWithScope setup;
CrateList crates;
- Crate dep = Crate(SourceFile("/root/tortoise/lib.rs"), 0, "//tortoise:bar", "2015");
- Crate target = Crate(SourceFile("/root/hare/lib.rs"), 1, "//hare:bar", "2015");
+ Crate dep =
+ Crate(SourceFile("/root/tortoise/lib.rs"), 0, "//tortoise:bar", "2015");
+ Crate target =
+ Crate(SourceFile("/root/hare/lib.rs"), 1, "//hare:bar", "2015");
target.AddDependency(0, "tortoise");
target.AddConfigItem("unix");
- target.AddConfigItem("feature=\\\"test\\\"");
+ target.AddConfigItem("feature=\"test\"");
crates.push_back(dep);
crates.push_back(target);
@@ -36,8 +38,8 @@
const char expected_json[] =
"{\n"
" \"roots\": [\n"
- " \"/root/tortoise/\",\n"
- " \"/root/hare/\"\n"
+ " \"/root/hare/\",\n"
+ " \"/root/tortoise/\"\n"
" ],\n"
" \"crates\": [\n"
" {\n"
@@ -88,297 +90,466 @@
base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
#endif
-const char expected_json[] =
- "{\n"
- " \"roots\": [\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcore/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_abort/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libunwind/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcollections/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liblibc/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_unwind/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libproc_macro/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_unicode/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd_unicode/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libtest/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_jemalloc/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_system/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcompiler_builtins/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libgetopts/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libbuild_helper/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_asan/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_lsan/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_msan/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_tsan/\",\n"
- " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libsyntax/\"\n"
- " ],\n"
- " \"crates\": [\n"
- " {\n"
- " \"crate_id\": 0,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcore/lib.rs\",\n"
- " \"label\": \"core\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 1,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc/lib.rs\",\n"
- " \"label\": \"alloc\",\n"
- " \"deps\": [\n"
- " {\n"
- " \"crate\": 0,\n"
- " \"name\": \"core\"\n"
- " }\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 2,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_abort/lib.rs\",\n"
- " \"label\": \"panic_abort\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 3,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libunwind/lib.rs\",\n"
- " \"label\": \"unwind\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 4,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd/lib.rs\",\n"
- " \"label\": \"std\",\n"
- " \"deps\": [\n"
- " {\n"
- " \"crate\": 1,\n"
- " \"name\": \"alloc\"\n"
- " },\n"
- " {\n"
- " \"crate\": 0,\n"
- " \"name\": \"core\"\n"
- " },\n"
- " {\n"
- " \"crate\": 2,\n"
- " \"name\": \"panic_abort\"\n"
- " },\n"
- " {\n"
- " \"crate\": 3,\n"
- " \"name\": \"unwind\"\n"
- " }\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 5,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcollections/lib.rs\",\n"
- " \"label\": \"collections\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 6,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liblibc/lib.rs\",\n"
- " \"label\": \"libc\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 7,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_unwind/lib.rs\",\n"
- " \"label\": \"panic_unwind\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 8,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libproc_macro/lib.rs\",\n"
- " \"label\": \"proc_macro\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 9,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_unicode/lib.rs\",\n"
- " \"label\": \"rustc_unicode\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 10,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd_unicode/lib.rs\",\n"
- " \"label\": \"std_unicode\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 11,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libtest/lib.rs\",\n"
- " \"label\": \"test\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 12,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_jemalloc/lib.rs\",\n"
- " \"label\": \"alloc_jemalloc\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 13,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_system/lib.rs\",\n"
- " \"label\": \"alloc_system\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 14,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcompiler_builtins/lib.rs\",\n"
- " \"label\": \"compiler_builtins\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 15,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libgetopts/lib.rs\",\n"
- " \"label\": \"getopts\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 16,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libbuild_helper/lib.rs\",\n"
- " \"label\": \"build_helper\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 17,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_asan/lib.rs\",\n"
- " \"label\": \"rustc_asan\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 18,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_lsan/lib.rs\",\n"
- " \"label\": \"rustc_lsan\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 19,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_msan/lib.rs\",\n"
- " \"label\": \"rustc_msan\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 20,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_tsan/lib.rs\",\n"
- " \"label\": \"rustc_tsan\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " },\n"
- " {\n"
- " \"crate_id\": 21,\n"
- " \"root_module\": \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libsyntax/lib.rs\",\n"
- " \"label\": \"syntax\",\n"
- " \"deps\": [\n"
- " ],\n"
- " \"edition\": \"2018\",\n"
- " \"cfg\": [\n"
- " \"debug_assertions\"\n"
- " ]\n"
- " }\n"
- " ]\n"
- "}\n";
-;
+ const char expected_json[] =
+ "{\n"
+ " \"roots\": [\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_jemalloc/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_system/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libbuild_helper/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcollections/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcompiler_builtins/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcore/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libgetopts/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liblibc/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_abort/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_unwind/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libproc_macro/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_asan/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_lsan/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_msan/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_tsan/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_unicode/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd_unicode/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libsyntax/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libtest/\",\n"
+ " \"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libunwind/\"\n"
+ " ],\n"
+ " \"crates\": [\n"
+ " {\n"
+ " \"crate_id\": 0,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcore/lib.rs\",\n"
+ " \"label\": \"core\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 1,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc/lib.rs\",\n"
+ " \"label\": \"alloc\",\n"
+ " \"deps\": [\n"
+ " {\n"
+ " \"crate\": 0,\n"
+ " \"name\": \"core\"\n"
+ " }\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 2,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_abort/"
+ "lib.rs\",\n"
+ " \"label\": \"panic_abort\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 3,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libunwind/lib.rs\",\n"
+ " \"label\": \"unwind\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 4,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd/lib.rs\",\n"
+ " \"label\": \"std\",\n"
+ " \"deps\": [\n"
+ " {\n"
+ " \"crate\": 1,\n"
+ " \"name\": \"alloc\"\n"
+ " },\n"
+ " {\n"
+ " \"crate\": 0,\n"
+ " \"name\": \"core\"\n"
+ " },\n"
+ " {\n"
+ " \"crate\": 2,\n"
+ " \"name\": \"panic_abort\"\n"
+ " },\n"
+ " {\n"
+ " \"crate\": 3,\n"
+ " \"name\": \"unwind\"\n"
+ " }\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 5,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcollections/"
+ "lib.rs\",\n"
+ " \"label\": \"collections\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 6,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liblibc/lib.rs\",\n"
+ " \"label\": \"libc\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 7,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libpanic_unwind/"
+ "lib.rs\",\n"
+ " \"label\": \"panic_unwind\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 8,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libproc_macro/"
+ "lib.rs\",\n"
+ " \"label\": \"proc_macro\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 9,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_unicode/"
+ "lib.rs\",\n"
+ " \"label\": \"rustc_unicode\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 10,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libstd_unicode/"
+ "lib.rs\",\n"
+ " \"label\": \"std_unicode\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 11,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libtest/lib.rs\",\n"
+ " \"label\": \"test\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 12,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_jemalloc/"
+ "lib.rs\",\n"
+ " \"label\": \"alloc_jemalloc\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 13,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/liballoc_system/"
+ "lib.rs\",\n"
+ " \"label\": \"alloc_system\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 14,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libcompiler_builtins/"
+ "lib.rs\",\n"
+ " \"label\": \"compiler_builtins\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 15,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libgetopts/"
+ "lib.rs\",\n"
+ " \"label\": \"getopts\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 16,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libbuild_helper/"
+ "lib.rs\",\n"
+ " \"label\": \"build_helper\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 17,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_asan/"
+ "lib.rs\",\n"
+ " \"label\": \"rustc_asan\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 18,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_lsan/"
+ "lib.rs\",\n"
+ " \"label\": \"rustc_lsan\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 19,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_msan/"
+ "lib.rs\",\n"
+ " \"label\": \"rustc_msan\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 20,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/librustc_tsan/"
+ "lib.rs\",\n"
+ " \"label\": \"rustc_tsan\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " },\n"
+ " {\n"
+ " \"crate_id\": 21,\n"
+ " \"root_module\": "
+ "\"/root/out/Debug/sysroot/lib/rustlib/src/rust/src/libsyntax/lib.rs\",\n"
+ " \"label\": \"syntax\",\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}\n";
+
EXPECT_EQ(expected_json, out);
}
+
+TEST_F(RustProjectWriterHelper, ExtractCompilerTargetTupleSimple) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("--target");
+ target.config_values().rustflags().push_back("x86-someos");
+ target.config_values().rustflags().push_back("--edition=2018");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::optional<std::string> result = FindArgValue("--target", args);
+ auto expected = std::optional<std::string>{"x86-someos"};
+ EXPECT_EQ(expected, result);
+}
+
+TEST_F(RustProjectWriterHelper, ExtractCompilerTargetTupleMissing) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back(
+ "--cfg=featur4e=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("x86-someos");
+ target.config_values().rustflags().push_back("--edition=2018");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::optional<std::string> result = FindArgValue("--target", args);
+ auto expected = std::nullopt;
+ EXPECT_EQ(expected, result);
+}
+
+TEST_F(RustProjectWriterHelper, ExtractCompilerTargetTupleDontFallOffEnd) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("--edition=2018");
+ target.config_values().rustflags().push_back("--target");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::optional<std::string> result = FindArgValue("--target", args);
+ auto expected = std::nullopt;
+ EXPECT_EQ(expected, result);
+}
+
+TEST_F(RustProjectWriterHelper, ExtractFirstArgValueWithPrefixMissing) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("--edition=2018");
+ target.config_values().rustflags().push_back("--target");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::optional<std::string> result =
+ FindArgValueAfterPrefix("--missing", args);
+ auto expected = std::nullopt;
+ EXPECT_EQ(expected, result);
+}
+
+TEST_F(RustProjectWriterHelper, ExtractFirstArgValueWithPrefix) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("--edition=2018");
+ target.config_values().rustflags().push_back("--target");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::optional<std::string> result =
+ FindArgValueAfterPrefix("--edition=", args);
+ auto expected = std::optional<std::string>{"2018"};
+ EXPECT_EQ(expected, result);
+}
+
+TEST_F(RustProjectWriterHelper, ExtractAllArgValueWithPrefix) {
+ TestWithScope setup;
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--cfg=feature=\"foo_enabled\"");
+ target.config_values().rustflags().push_back("--edition=2018");
+ target.config_values().rustflags().push_back("--cfg=feature=\"bar_enabled\"");
+ target.config_values().rustflags().push_back("--target");
+
+ auto args = ExtractCompilerArgs(&target);
+ std::vector<std::string> result = FindAllArgValuesAfterPrefix("--cfg=", args);
+ std::vector<std::string> expected = {"feature=\"foo_enabled\"",
+ "feature=\"bar_enabled\""};
+ EXPECT_EQ(expected, result);
+}
\ No newline at end of file
diff --git a/src/gn/rust_project_writer_unittest.cc b/src/gn/rust_project_writer_unittest.cc
index 7891576..9df1ad2 100644
--- a/src/gn/rust_project_writer_unittest.cc
+++ b/src/gn/rust_project_writer_unittest.cc
@@ -50,6 +50,7 @@
" \"crate_id\": 0,\n"
" \"root_module\": \"path/foo/lib.rs\",\n"
" \"label\": \"//foo:bar\",\n"
+ " \"compiler_args\": [\"--cfg=feature=\\\"foo_enabled\\\"\"],\n"
" \"deps\": [\n"
" ],\n"
" \"edition\": \"2015\",\n"
@@ -102,8 +103,8 @@
const char expected_json[] =
"{\n"
" \"roots\": [\n"
- " \"tortoise/\",\n"
- " \"hare/\"\n"
+ " \"hare/\",\n"
+ " \"tortoise/\"\n"
" ],\n"
" \"crates\": [\n"
" {\n"
@@ -188,9 +189,9 @@
const char expected_json[] =
"{\n"
" \"roots\": [\n"
- " \"tortoise/\",\n"
" \"achilles/\",\n"
- " \"hare/\"\n"
+ " \"hare/\",\n"
+ " \"tortoise/\"\n"
" ],\n"
" \"crates\": [\n"
" {\n"
@@ -305,9 +306,9 @@
const char expected_json[] =
"{\n"
" \"roots\": [\n"
+ " \"hare/\",\n"
" \"tortoise/\",\n"
- " \"tortoise/macro/\",\n"
- " \"hare/\"\n"
+ " \"tortoise/macro/\"\n"
" ],\n"
" \"crates\": [\n"
" {\n"
@@ -359,3 +360,156 @@
EXPECT_EQ(expected_json, out);
}
+
+TEST_F(RustProjectJSONWriter, OneRustTargetWithRustcTargetSet) {
+ Err err;
+ TestWithScope setup;
+ setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--target");
+ target.config_values().rustflags().push_back("x86-64_unknown");
+ target.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(target.OnResolved(&err));
+
+ std::ostringstream stream;
+ std::vector<const Target*> targets;
+ targets.push_back(&target);
+ RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
+ std::string out = stream.str();
+#if defined(OS_WIN)
+ base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
+#endif
+ const char expected_json[] =
+ "{\n"
+ " \"roots\": [\n"
+ " \"path/foo/\"\n"
+ " ],\n"
+ " \"crates\": [\n"
+ " {\n"
+ " \"crate_id\": 0,\n"
+ " \"root_module\": \"path/foo/lib.rs\",\n"
+ " \"label\": \"//foo:bar\",\n"
+ " \"target\": \"x86-64_unknown\",\n"
+ " \"compiler_args\": [\"--target\", \"x86-64_unknown\"],\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2015\",\n"
+ " \"cfg\": [\n"
+ " \"test\",\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}\n";
+
+ EXPECT_EQ(expected_json, out);
+}
+
+TEST_F(RustProjectJSONWriter, OneRustTargetWithEditionSet) {
+ Err err;
+ TestWithScope setup;
+ setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--edition=2018");
+ target.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(target.OnResolved(&err));
+
+ std::ostringstream stream;
+ std::vector<const Target*> targets;
+ targets.push_back(&target);
+ RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
+ std::string out = stream.str();
+#if defined(OS_WIN)
+ base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
+#endif
+ const char expected_json[] =
+ "{\n"
+ " \"roots\": [\n"
+ " \"path/foo/\"\n"
+ " ],\n"
+ " \"crates\": [\n"
+ " {\n"
+ " \"crate_id\": 0,\n"
+ " \"root_module\": \"path/foo/lib.rs\",\n"
+ " \"label\": \"//foo:bar\",\n"
+ " \"compiler_args\": [\"--edition=2018\"],\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"test\",\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}\n";
+
+ EXPECT_EQ(expected_json, out);
+}
+
+TEST_F(RustProjectJSONWriter, OneRustTargetWithEditionSetAlternate) {
+ Err err;
+ TestWithScope setup;
+ setup.build_settings()->SetRootPath(UTF8ToFilePath("path"));
+
+ Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
+ target.set_output_type(Target::RUST_LIBRARY);
+ target.visibility().SetPublic();
+ SourceFile lib("//foo/lib.rs");
+ target.sources().push_back(lib);
+ target.source_types_used().Set(SourceFile::SOURCE_RS);
+ target.rust_values().set_crate_root(lib);
+ target.rust_values().crate_name() = "foo";
+ target.config_values().rustflags().push_back("--edition");
+ target.config_values().rustflags().push_back("2018");
+ target.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(target.OnResolved(&err));
+
+ std::ostringstream stream;
+ std::vector<const Target*> targets;
+ targets.push_back(&target);
+ RustProjectWriter::RenderJSON(setup.build_settings(), targets, stream);
+ std::string out = stream.str();
+#if defined(OS_WIN)
+ base::ReplaceSubstringsAfterOffset(&out, 0, "\r\n", "\n");
+#endif
+ const char expected_json[] =
+ "{\n"
+ " \"roots\": [\n"
+ " \"path/foo/\"\n"
+ " ],\n"
+ " \"crates\": [\n"
+ " {\n"
+ " \"crate_id\": 0,\n"
+ " \"root_module\": \"path/foo/lib.rs\",\n"
+ " \"label\": \"//foo:bar\",\n"
+ " \"compiler_args\": [\"--edition\", \"2018\"],\n"
+ " \"deps\": [\n"
+ " ],\n"
+ " \"edition\": \"2018\",\n"
+ " \"cfg\": [\n"
+ " \"test\",\n"
+ " \"debug_assertions\"\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}\n";
+
+ EXPECT_EQ(expected_json, out);
+}
\ No newline at end of file