From 4aa11ffec268084919da823a71032920d9e6ca71 Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Wed, 11 May 2022 16:10:27 +0200 Subject: [PATCH] cargo-apk: Reimplement NDK r23 `-lgcc` workaround using `RUSTFLAGS` Any flags passed directly to `cargo rustc` will only be passed _to the final compiler invocation_. However `cdylib` library targets in transitive (dependency) crates will still be built (despite not being used in the final binary, that's what `rlib`s are for), but our NDK r23 workaround flags will not reach these compiler invocations rendering b912a6b ("cargo-apk: Work around missing libgcc on NDK r23 with linker script (#189)") ineffective. [The same page] that documents this discrepancy suggests to resort to `RUSTFLAGS` if arguments are intended for all compiler invocations, which is our intended use-case and unblocks builds with transitive `cdylib` dependencies such as `hyper` in [#265]. [The same page]: https://doc.rust-lang.org/cargo/commands/cargo-rustc.html#description [#265]: https://github.com/rust-windowing/android-ndk-rs/issues/265 --- cargo-apk/CHANGELOG.md | 2 ++ cargo-apk/src/apk.rs | 24 +++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/cargo-apk/CHANGELOG.md b/cargo-apk/CHANGELOG.md index 4f94e216..75a39ca3 100644 --- a/cargo-apk/CHANGELOG.md +++ b/cargo-apk/CHANGELOG.md @@ -1,5 +1,7 @@ # Unreleased +- Reimplement NDK r23 `-lgcc` workaround using `RUSTFLAGS`, to apply to transitive `cdylib` compilations (#270) + # 0.9.0 (2022-05-07) - **Breaking:** Use `min_sdk_version` to select compiler target instead of `target_sdk_version`. ([#197](https://github.com/rust-windowing/android-ndk-rs/pull/197)) diff --git a/cargo-apk/src/apk.rs b/cargo-apk/src/apk.rs index 92a010f2..5e9d0286 100644 --- a/cargo-apk/src/apk.rs +++ b/cargo-apk/src/apk.rs @@ -175,7 +175,7 @@ impl<'a> ApkBuilder<'a> { .join(artifact.file_name(CrateType::Cdylib, triple)); let mut cargo = cargo_ndk(&config.ndk, *target, self.min_sdk_version())?; - cargo.arg("rustc"); + cargo.arg("build"); if self.cmd.target().is_none() { cargo.arg("--target").arg(triple); } @@ -188,9 +188,6 @@ impl<'a> ApkBuilder<'a> { // is still required even after replacing it with libunwind in the source. // XXX: Add an upper-bound on the Rust version whenever this is not necessary anymore. if self.ndk.build_tag() > 7272597 { - if !self.cmd.args().contains(&"--".to_owned()) { - cargo.arg("--"); - } let cargo_apk_link_dir = self .cmd .target_dir() @@ -198,7 +195,24 @@ impl<'a> ApkBuilder<'a> { std::fs::create_dir_all(&cargo_apk_link_dir)?; std::fs::write(cargo_apk_link_dir.join("libgcc.a"), "INPUT(-lunwind)") .expect("Failed to write"); - cargo.arg("-L").arg(cargo_apk_link_dir); + + // cdylibs in transitive dependencies still get built and also need this + // workaround linker flag, yet arguments passed to `cargo rustc` are only + // forwarded to the final compiler invocation rendering our workaround ineffective. + // The cargo page documenting this discrepancy (https://doc.rust-lang.org/cargo/commands/cargo-rustc.html) + // suggests to resort to RUSTFLAGS, which are updated below: + let mut rustflags = match std::env::var("RUSTFLAGS") { + Ok(val) => val, + Err(std::env::VarError::NotPresent) => "".to_string(), + Err(std::env::VarError::NotUnicode(_)) => { + panic!("RUSTFLAGS environment variable contains non-unicode characters") + } + }; + rustflags += " -L "; + rustflags += cargo_apk_link_dir + .to_str() + .expect("Target dir must be valid UTF-8"); + cargo.env("RUSTFLAGS", rustflags); } if !cargo.status()?.success() {