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".