|
| 1 | +use crate::{config::Config, pick_best_android_ndk_toolchain, run_command}; |
| 2 | +use std::{fs, io::Write, path::PathBuf, process::Command}; |
| 3 | + |
| 4 | +// The prefix to add to all symbols |
| 5 | +// Using crate name to avoid collisions with other projects |
| 6 | +const PREFIX: &str = env!("CARGO_CRATE_NAME"); |
| 7 | + |
| 8 | +// Callback to add a `link_name` macro with the prefix to all generated bindings |
| 9 | +#[derive(Debug)] |
| 10 | +pub struct PrefixCallback; |
| 11 | + |
| 12 | +impl bindgen::callbacks::ParseCallbacks for PrefixCallback { |
| 13 | + fn generated_link_name_override( |
| 14 | + &self, |
| 15 | + item_info: bindgen::callbacks::ItemInfo<'_>, |
| 16 | + ) -> Option<String> { |
| 17 | + Some(format!("{PREFIX}_{}", item_info.name)) |
| 18 | + } |
| 19 | +} |
| 20 | + |
| 21 | +fn android_toolchain(config: &Config) -> PathBuf { |
| 22 | + let mut android_bin_path = config |
| 23 | + .env |
| 24 | + .android_ndk_home |
| 25 | + .clone() |
| 26 | + .expect("Please set ANDROID_NDK_HOME for Android build"); |
| 27 | + android_bin_path.extend(["toolchains", "llvm", "prebuilt"]); |
| 28 | + android_bin_path.push(pick_best_android_ndk_toolchain(&android_bin_path).unwrap()); |
| 29 | + android_bin_path.push("bin"); |
| 30 | + android_bin_path |
| 31 | +} |
| 32 | + |
| 33 | +pub fn prefix_symbols(config: &Config) { |
| 34 | + // List static libraries to prefix symbols in |
| 35 | + let static_libs: Vec<PathBuf> = [ |
| 36 | + config.out_dir.join("build"), |
| 37 | + config.out_dir.join("build").join("ssl"), |
| 38 | + config.out_dir.join("build").join("crypto"), |
| 39 | + ] |
| 40 | + .iter() |
| 41 | + .flat_map(|dir| { |
| 42 | + ["libssl.a", "libcrypto.a"] |
| 43 | + .into_iter() |
| 44 | + .map(move |file| PathBuf::from(dir).join(file)) |
| 45 | + }) |
| 46 | + .filter(|p| p.exists()) |
| 47 | + .collect(); |
| 48 | + |
| 49 | + // Use `nm` to list symbols in these static libraries |
| 50 | + let nm = match &*config.target_os { |
| 51 | + "android" => android_toolchain(config).join("llvm-nm"), |
| 52 | + _ => PathBuf::from("nm"), |
| 53 | + }; |
| 54 | + let out = run_command(Command::new(nm).args(&static_libs)).unwrap(); |
| 55 | + let mut redefine_syms: Vec<String> = String::from_utf8_lossy(&out.stdout) |
| 56 | + .lines() |
| 57 | + .filter(|l| { |
| 58 | + [" T ", " D ", " B ", " C ", " R ", " W "] |
| 59 | + .iter() |
| 60 | + .any(|s| l.contains(s)) |
| 61 | + }) |
| 62 | + .filter_map(|l| l.split_whitespace().nth(2).map(|s| s.to_string())) |
| 63 | + .filter(|l| !l.starts_with("_")) |
| 64 | + .map(|l| format!("{l} {PREFIX}_{l}")) |
| 65 | + .collect(); |
| 66 | + redefine_syms.sort(); |
| 67 | + redefine_syms.dedup(); |
| 68 | + |
| 69 | + let redefine_syms_path = config.out_dir.join("redefine_syms.txt"); |
| 70 | + let mut f = fs::File::create(&redefine_syms_path).unwrap(); |
| 71 | + for sym in &redefine_syms { |
| 72 | + writeln!(f, "{sym}").unwrap(); |
| 73 | + } |
| 74 | + f.flush().unwrap(); |
| 75 | + |
| 76 | + // Use `objcopy` to prefix symbols in these static libraries |
| 77 | + let objcopy = match &*config.target_os { |
| 78 | + "android" => android_toolchain(config).join("llvm-objcopy"), |
| 79 | + _ => PathBuf::from("objcopy"), |
| 80 | + }; |
| 81 | + for static_lib in &static_libs { |
| 82 | + run_command( |
| 83 | + Command::new(&objcopy) |
| 84 | + .arg(format!("--redefine-syms={}", redefine_syms_path.display())) |
| 85 | + .arg(static_lib), |
| 86 | + ) |
| 87 | + .unwrap(); |
| 88 | + } |
| 89 | +} |
0 commit comments