-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide libgcc linker script workaround for NDK >= 23 #67
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
use std::io::{Write, Result}; | ||
use std::path::{Path, PathBuf}; | ||
use std::process::Command; | ||
|
||
use cargo_metadata::Version; | ||
use cargo_metadata::camino::Utf8PathBuf; | ||
|
||
#[cfg(target_os = "macos")] | ||
const ARCH: &str = "darwin-x86_64"; | ||
|
@@ -75,8 +77,19 @@ fn cargo_env_target_cfg(triple: &str, key: &str) -> String { | |
format!("CARGO_TARGET_{}_{}", &triple.replace("-", "_"), key).to_uppercase() | ||
} | ||
|
||
fn create_libgcc_linker_script_workaround(target_dir: &Utf8PathBuf) -> Result<Utf8PathBuf> { | ||
let libgcc_workaround_dir = target_dir.join("cargo-ndk").join("libgcc-workaround"); | ||
std::fs::create_dir_all(&libgcc_workaround_dir)?; | ||
let libgcc_workaround_file = libgcc_workaround_dir.join("libgcc.a"); | ||
let mut file = std::fs::File::create(libgcc_workaround_file)?; | ||
file.write_all(b"INPUT(-lunwind)")?; | ||
|
||
Ok(libgcc_workaround_dir) | ||
} | ||
|
||
pub(crate) fn run( | ||
dir: &Path, | ||
target_dir: &Utf8PathBuf, | ||
ndk_home: &Path, | ||
version: Version, | ||
triple: &str, | ||
|
@@ -123,6 +136,16 @@ pub(crate) fn run( | |
); | ||
log::debug!("Args: {:?}", &cargo_args); | ||
|
||
// Read initial RUSTFLAGS | ||
let mut rustflags = match std::env::var("CARGO_ENCODED_RUSTFLAGS") { | ||
Ok(val) => val, | ||
Err(std::env::VarError::NotPresent) => "".to_string(), | ||
Err(std::env::VarError::NotUnicode(_)) => { | ||
log::error!("RUSTFLAGS environment variable contains non-unicode characters"); | ||
std::process::exit(1); | ||
} | ||
}; | ||
|
||
let mut cargo_cmd = Command::new(cargo_bin); | ||
cargo_cmd | ||
.current_dir(dir) | ||
|
@@ -133,6 +156,42 @@ pub(crate) fn run( | |
.env(cargo_env_target_cfg(triple, "linker"), &target_linker) | ||
.args(cargo_args); | ||
|
||
// NDK releases >= 23 beta3 no longer include libgcc which rust's pre-built | ||
// standard libraries depend on. As a workaround for newer NDKs we redirect | ||
// libgcc to libunwind. | ||
// | ||
// Note: there is a tiny chance of a false positive here while the first two | ||
// beta releases for NDK v23 didn't yet include libunwind for all | ||
// architectures. | ||
Comment on lines
+163
to
+165
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're copying things from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I considered it but it didn't look like Since it doesn't look like you can download the first two betas anymore and also since by their very nature beta releases shouldn't be relied on it seems reasonable in this case to just check the major number. |
||
// | ||
// Note: even though rust-lang merged a fix to support linking the standard | ||
// libraries against newer NDKs they still (up to 1.62.0 at time of writing) | ||
// choose to build binaries (distributed by rustup) against an older NDK | ||
// release (presumably aiming for broader compatibility) which means that | ||
// even the latest versions still require this workaround. | ||
// | ||
// Ref: https://github.com/rust-lang/rust/pull/85806 | ||
if version.major >= 23 { | ||
match create_libgcc_linker_script_workaround(target_dir) { | ||
Ok(libdir) => { | ||
// Note that we don't use `cargo rustc` to pass custom library search paths to | ||
// rustc and instead use `CARGO_ENCODED_RUSTFLAGS` because it affects the building | ||
// of all transitive cdylibs (which all need this workaround). | ||
if !rustflags.is_empty() { // Avoid creating an empty '' rustc argument | ||
rustflags.push_str("\x1f"); | ||
} | ||
rustflags.push_str("-L\x1f"); | ||
rustflags.push_str(libdir.as_str()); | ||
cargo_cmd.env("CARGO_ENCODED_RUSTFLAGS", rustflags); | ||
} | ||
Err(e) => { | ||
log::error!("Failed to create libgcc.a linker script workaround"); | ||
log::error!("{}", e); | ||
std::process::exit(1); | ||
} | ||
} | ||
} | ||
|
||
let extra_include = format!("{}/usr/include/{}", &target_sysroot.display(), triple); | ||
if bindgen { | ||
let bindgen_args = format!( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/RUSTFLAGS/CARGO_ENCODED_RUSTFLAGS
?