Skip to content

Commit

Permalink
Provide libgcc linker script workaround for NDK >= 23
Browse files Browse the repository at this point in the history
libgcc was removed from NDK v23 which breaks Rust builds against
pre-built standard libraries that were linked against libgcc
instead of libunwind.

As a workaround this ensures that there is a libgcc.a in the
library search paths which is a linker script that will redirect
to link with libunwind instead.

The libgcc.a linker script is created under:

 target/cargo-ndk/libgcc_workaround/libgcc.a

Fixes: bbqsrc#22
  • Loading branch information
rib committed Jul 23, 2022
1 parent 04b03e8 commit 0b4a77f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/cargo.rs
@@ -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";
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -133,6 +146,22 @@ pub(crate) fn run(
.env(cargo_env_target_cfg(triple, "linker"), &target_linker)
.args(cargo_args);

// NDK releases >= 23 no longer include libgcc which rust's pre-built standard libraries
// depend on. As a workaround for newer NDKs we redirect libgcc to libunwind.
// Ref: https://github.com/rust-lang/rust/pull/85806
if version.major >= 23 {
match create_libgcc_linker_script_workaround(target_dir) {
Ok(libdir) => {
cargo_cmd.env("RUSTFLAGS", format!("-L{libdir}"));
}
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!(
Expand Down
1 change: 1 addition & 0 deletions src/cli.rs
Expand Up @@ -272,6 +272,7 @@ pub(crate) fn run(args: Vec<String>) {

let status = crate::cargo::run(
&working_dir,
&metadata.target_directory,
&ndk_home,
ndk_version.clone(),
triple,
Expand Down

0 comments on commit 0b4a77f

Please sign in to comment.