Ninja: Always pass linker flags to rlib-generating command.
This is a partial rollback of [1] to restore all linker args in
the Ninja command that builds Rust rlib artifacts.
The Fuchsia build system supports remote builders with a wrapper
script that looks at the command-line arguments of the rustc
invocation to determine which input files to send to remote
builders. This is done with a custom toolchain tool() definition.
For example, the final command looks like:
```
<wrapper_script> <wrapper_args> -- <rustc_invocation>
```
And it is crucial that `<rustc_invocation>` lists all linker inputs
(even with `-Lnative=<dir>` and `-Clink-arg=libfoo.a`) to ensure
they can be detected properly.
A recent GN change [1] removed such inputs, which broke the Fuchsia
build (or more accurately, prevents rolling upstream GN into the
Fuchsia tree). For more information, see https://fxbug.dev/130206.
Note that this does not revert the CL entirely, in particular to keep
the fix for `framework_dirs` as described in the original bug
description.
+ Update variables.cc to avoid losing a docs/reference.md change
that was applied manually in [1].
[1] https://gn-review.googlesource.com/c/gn/+/15580
Fixed: 340
Change-Id: Ibd65494a9b180037f21a666da5e6d905751b9c61
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/15760
Commit-Queue: David Turner <digit@google.com>
Reviewed-by: Takuto Ikuta <tikuta@google.com>
diff --git a/src/gn/ninja_rust_binary_target_writer.cc b/src/gn/ninja_rust_binary_target_writer.cc
index 21ae6d0..a400cf7 100644
--- a/src/gn/ninja_rust_binary_target_writer.cc
+++ b/src/gn/ninja_rust_binary_target_writer.cc
@@ -209,8 +209,8 @@
std::copy(classified_deps.non_linkable_deps.begin(),
classified_deps.non_linkable_deps.end(),
std::back_inserter(extern_deps));
- WriteExternsAndDeps(target_->IsFinal(), extern_deps, transitive_crates,
- rustdeps, nonrustdeps);
+
+ WriteExternsAndDeps(extern_deps, transitive_crates, rustdeps, nonrustdeps);
WriteSourcesAndInputs();
WritePool(out_);
}
@@ -256,7 +256,6 @@
}
void NinjaRustBinaryTargetWriter::WriteExternsAndDeps(
- bool target_is_final,
const std::vector<const Target*>& deps,
const std::vector<ExternCrate>& transitive_rust_deps,
const std::vector<OutputFile>& rustdeps,
@@ -365,17 +364,16 @@
// If rustc will invoke a linker, then pass linker arguments to include those
// non-Rust native dependencies in the linking step.
- if (target_is_final) {
- // Before outputting any libraries to link, ensure the linker is in a mode
- // that allows dynamic linking, as rustc may have previously put it into
- // static-only mode.
- if (nonrustdeps.size() > 0) {
- out_ << " " << tool_->dynamic_link_switch();
- }
- for (const auto& nonrustdep : nonrustdeps) {
- out_ << " -Clink-arg=";
- path_output_.WriteFile(out_, nonrustdep);
- }
+
+ // Before outputting any libraries to link, ensure the linker is in a mode
+ // that allows dynamic linking, as rustc may have previously put it into
+ // static-only mode.
+ if (nonrustdeps.size() > 0) {
+ out_ << " " << tool_->dynamic_link_switch();
+ }
+ for (const auto& nonrustdep : nonrustdeps) {
+ out_ << " -Clink-arg=";
+ path_output_.WriteFile(out_, nonrustdep);
}
// Library search paths are required to find system libraries named in #[link]
@@ -383,15 +381,13 @@
WriteLibrarySearchPath(out_, tool_);
// If rustc will invoke a linker, all libraries need the passed through to the
// linker.
- if (target_is_final) {
- WriteLibs(out_, tool_);
- }
+ WriteLibs(out_, tool_);
+
out_ << std::endl;
out_ << " ldflags =";
// If rustc will invoke a linker, linker flags need to be forwarded through to
// the linker.
- if (target_is_final) {
- WriteCustomLinkerFlags(out_, tool_);
- }
+ WriteCustomLinkerFlags(out_, tool_);
+
out_ << std::endl;
}
diff --git a/src/gn/ninja_rust_binary_target_writer.h b/src/gn/ninja_rust_binary_target_writer.h
index 470a899..69ec916 100644
--- a/src/gn/ninja_rust_binary_target_writer.h
+++ b/src/gn/ninja_rust_binary_target_writer.h
@@ -28,8 +28,7 @@
void WriteCompilerVars();
void WriteSources(const OutputFile& input_dep,
const std::vector<OutputFile>& order_only_deps);
- void WriteExternsAndDeps(bool target_is_final,
- const std::vector<const Target*>& deps,
+ void WriteExternsAndDeps(const std::vector<const Target*>& deps,
const std::vector<ExternCrate>& transitive_rust_deps,
const std::vector<OutputFile>& rustdeps,
const std::vector<OutputFile>& nonrustdeps);
diff --git a/src/gn/ninja_rust_binary_target_writer_unittest.cc b/src/gn/ninja_rust_binary_target_writer_unittest.cc
index deb2bb6..9a21c1f 100644
--- a/src/gn/ninja_rust_binary_target_writer_unittest.cc
+++ b/src/gn/ninja_rust_binary_target_writer_unittest.cc
@@ -896,7 +896,8 @@
" source_file_part = lib.rs\n"
" source_name_part = lib\n"
" externs =\n"
- " rustdeps = -Lnative=obj/foo\n"
+ " rustdeps = -Lnative=obj/foo -Clink-arg=-Balternative-dynamic "
+ "-Clink-arg=obj/foo/libstatic.a\n"
" ldflags =\n"
" sources = ../../baz/lib.rs\n";
std::string out_str = out.str();
@@ -1255,8 +1256,7 @@
// requesting a system library. The path to that library must be specified
// separately with `-L` in ldflags, the library does not appear in the
// rustc compilation of an rlib.
- rlib.config_values().libs().push_back(
- LibFile(SourceFile("//dir1/ar.a")));
+ rlib.config_values().libs().push_back(LibFile(SourceFile("//dir1/ar.a")));
// 2. A dependency on a library name as happens with a `libs` rule. Libraries
// need only be named when linking, they do not need to appear in an rlib
// compilation.
@@ -1295,12 +1295,15 @@
"target_out_dir = obj/foo\n"
"target_output_name = librlibcrate\n"
"\n"
- "build obj/foo/librlibcrate.rlib: rust_rlib ../../foo/input.rs | ../../foo/input.rs obj/bar/libpubliclib.rlib obj/clib/libstatic.a\n"
+ "build obj/foo/librlibcrate.rlib: rust_rlib ../../foo/input.rs | "
+ "../../foo/input.rs obj/bar/libpubliclib.rlib obj/clib/libstatic.a\n"
" source_file_part = input.rs\n"
" source_name_part = input\n"
" externs = --extern publiccrate=obj/bar/libpubliclib.rlib\n"
" rustdeps = -Ldependency=obj/bar -Lnative=obj/clib "
-"-Lnative=../../baz -Lframework=../../fwdir\n"
+ "-Clink-arg=-Bdynamic -Clink-arg=obj/clib/libstatic.a "
+ "-Lnative=../../baz -Lframework=../../fwdir -Clink-arg=../../dir1/ar.a "
+ "-lquux\n"
" ldflags =\n"
" sources = ../../foo/input.rs\n";
std::string out_str = out.str();
diff --git a/src/gn/setup.cc b/src/gn/setup.cc
index 139a919..68acd43 100644
--- a/src/gn/setup.cc
+++ b/src/gn/setup.cc
@@ -191,6 +191,7 @@
required version is 1.7.2. Specifying a higher version might enable the
use of some of newer features that can make the build more efficient.
+
Example .gn file contents
buildconfig = "//build/config/BUILDCONFIG.gn"
diff --git a/src/gn/variables.cc b/src/gn/variables.cc
index 5015df5..8eb2a99 100644
--- a/src/gn/variables.cc
+++ b/src/gn/variables.cc
@@ -1177,6 +1177,10 @@
of targets, and public_configs are always propagated across public deps of
all types of targets.
+ For Rust targets, deps ensures that Rust code can refer to the dependency
+ target. If the dependency is a C/C++ target, the path to that target will
+ be made available to Rust for `#[link]` directives.
+
Data dependencies are propagated differently. See "gn help data_deps" and
"gn help runtime_deps".