- replace demangling with never mangling
This commit is contained in:
@@ -5,11 +5,6 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
use bindgen::callbacks::ItemInfo;
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
fn find_static_lib(dir: &Path, base_name: &str, target_is_windows: bool) -> Option<PathBuf> {
|
||||
@@ -76,6 +71,46 @@ impl Error {
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_importexport(libcziapi_inc: &Path) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let header = libcziapi_inc.join("importexport.h");
|
||||
let relative = header.strip_prefix("libczi").unwrap_or(&header);
|
||||
let status = std::process::Command::new("git")
|
||||
.args(["checkout", "HEAD", "--", relative.to_str().unwrap()])
|
||||
.current_dir("libczi")
|
||||
.status()?;
|
||||
if !status.success() {
|
||||
return Err(Error::msg("failed to restore importexport.h"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct ImportExportGuard<'a> {
|
||||
libcziapi_inc: &'a Path,
|
||||
}
|
||||
|
||||
impl<'a> Drop for ImportExportGuard<'a> {
|
||||
fn drop(&mut self) {
|
||||
if let Err(e) = restore_importexport(self.libcziapi_inc) {
|
||||
eprintln!("warning: failed to restore importexport.h: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn patch_importexport(
|
||||
libcziapi_inc: &Path,
|
||||
) -> Result<ImportExportGuard<'_>, Box<dyn std::error::Error>> {
|
||||
let path = libcziapi_inc.join("importexport.h");
|
||||
let original = std::fs::read_to_string(&path)?;
|
||||
let patched = original.replace(
|
||||
"#define EXTERNALLIBCZIAPI_API(_returntype_) _returntype_",
|
||||
"#define EXTERNALLIBCZIAPI_API(_returntype_) extern \"C\" _returntype_",
|
||||
);
|
||||
if patched != original {
|
||||
std::fs::write(&path, &patched)?;
|
||||
}
|
||||
Ok(ImportExportGuard { libcziapi_inc })
|
||||
}
|
||||
|
||||
fn fix_xwin_lib_case() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let toolchain_key = format!(
|
||||
"CMAKE_TOOLCHAIN_FILE_{}",
|
||||
@@ -120,7 +155,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if env::var("DOCS_RS").is_err() {
|
||||
let host = env::var("HOST")?;
|
||||
let target = env::var("TARGET")?;
|
||||
let is_cross = host != target;
|
||||
let is_cross = host != target
|
||||
|| env::var(format!(
|
||||
"CMAKE_TOOLCHAIN_FILE_{}",
|
||||
target.replace('-', "_")
|
||||
))
|
||||
.is_ok()
|
||||
|| env::var("TARGET_CMAKE_TOOLCHAIN_FILE").is_ok()
|
||||
|| env::var("CMAKE_TOOLCHAIN_FILE").is_ok();
|
||||
let is_windows = target.contains("windows");
|
||||
let _is_macos = target.contains("apple");
|
||||
|
||||
@@ -177,6 +219,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if target.contains("aarch64") {
|
||||
cmake_config.define("NEON_INTRINSICS_CAN_BE_USED", "ON");
|
||||
}
|
||||
} else {
|
||||
cmake_config
|
||||
.define("CRASH_ON_UNALIGNED_ACCESS", "OFF")
|
||||
.define("_UNALIGNED_ACCESS_RESULT_EXITCODE", "0");
|
||||
if target.contains("aarch64") {
|
||||
cmake_config.define("_NEON_INTRINSICS_RESULT_EXITCODE", "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,25 +233,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
cmake_config.build_target("libCZIAPIStatic");
|
||||
}
|
||||
|
||||
let _importexport_guard = patch_importexport(&libcziapi_inc)?;
|
||||
let dst = cmake_config.build();
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
let bindings = {
|
||||
let libcziapi_search_dirs = [
|
||||
dst.join("build/Src/libCZIAPI"),
|
||||
dst.join("Src/libCZIAPI"),
|
||||
dst.join("lib"),
|
||||
dst.join("lib64"),
|
||||
];
|
||||
let libcziapi_static = libcziapi_search_dirs
|
||||
.iter()
|
||||
.find_map(|dir| find_static_lib(dir, "libCZIAPIStatic", is_windows))
|
||||
.ok_or(Error::msg("cannot find libCZIAPIStatic library"))?;
|
||||
bindgen::Builder::default().parse_callbacks(Box::new(DeMangler::new(
|
||||
libcziapi_static,
|
||||
is_cross && is_windows,
|
||||
)?))
|
||||
};
|
||||
let bindings = bindgen::Builder::default();
|
||||
|
||||
#[cfg(feature = "dynamic")]
|
||||
let bindings = bindgen::Builder::default();
|
||||
@@ -346,106 +381,3 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("cargo::rerun-if-changed=build.rs");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
#[derive(Debug)]
|
||||
struct DeMangler {
|
||||
map: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
impl DeMangler {
|
||||
fn new(a_file: PathBuf, use_llvm_nm: bool) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let nm_cmd = if use_llvm_nm { "llvm-nm" } else { "nm" };
|
||||
let cmd = std::process::Command::new(nm_cmd)
|
||||
.arg("--defined-only")
|
||||
.arg(&a_file)
|
||||
.output()?;
|
||||
let mut map = HashMap::new();
|
||||
for line in std::str::from_utf8(&cmd.stdout)?.lines() {
|
||||
let line = line.trim();
|
||||
let mangled = if let Some(sym) = line.split_whitespace().last() {
|
||||
sym
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let plain_name = Self::demangle(mangled);
|
||||
if let Some(name) = plain_name {
|
||||
if name.starts_with("libCZI_") {
|
||||
Self::insert_mapping(&mut map, &name, mangled, &a_file)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Self { map })
|
||||
}
|
||||
|
||||
fn demangle(symbol: &str) -> Option<String> {
|
||||
// Only demangle actual function symbols, not catch/dtor/cppxdata metadata
|
||||
if let Some(rest) = symbol.strip_prefix('?') {
|
||||
// MSVC: real functions start with "libCZI_", not "catch$", "dtor$", etc.
|
||||
if !rest.starts_with("libCZI_") {
|
||||
return None;
|
||||
}
|
||||
let flags = msvc_demangler::DemangleFlags::llvm();
|
||||
let demangled = msvc_demangler::demangle(symbol, flags).ok()?;
|
||||
Self::extract_msvc_name(&demangled)
|
||||
} else if symbol.starts_with("_Z") {
|
||||
// Itanium: demangle and extract the function name
|
||||
let sym = cpp_demangle::Symbol::new(symbol.as_bytes()).ok()?;
|
||||
let demangled = sym.demangle().ok()?;
|
||||
// e.g. "libCZI_Foo(int, bool)" -> "libCZI_Foo"
|
||||
// e.g. "ns::libCZI_Foo(int)" -> "libCZI_Foo"
|
||||
demangled.split('(').next().and_then(|s| {
|
||||
let s = s.trim();
|
||||
if let Some(name) = s.rsplit("::").next() {
|
||||
Some(name.to_string())
|
||||
} else {
|
||||
Some(s.to_string())
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_msvc_name(demangled: &str) -> Option<String> {
|
||||
// Find the identifier that looks like a function name.
|
||||
// MSVC demangled output: "return_type calling_conv name(params)"
|
||||
for word in demangled.split_whitespace() {
|
||||
if let Some(rest) = word.strip_prefix("libCZI_") {
|
||||
let name = format!("libCZI_{}", rest.split('(').next().unwrap_or(rest));
|
||||
return Some(name);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn insert_mapping(
|
||||
map: &mut HashMap<String, String>,
|
||||
demangled: &str,
|
||||
mangled: &str,
|
||||
a_file: &Path,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if let Some(existing_mangled) = map.get(demangled) {
|
||||
if existing_mangled != mangled {
|
||||
return Err(Error::msg(format!(
|
||||
"conflicting mangled symbols for {} in {}: {}, {}",
|
||||
demangled,
|
||||
a_file.to_string_lossy(),
|
||||
existing_mangled,
|
||||
mangled
|
||||
)));
|
||||
}
|
||||
} else {
|
||||
map.insert(demangled.to_string(), mangled.to_string());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "dynamic"))]
|
||||
impl bindgen::callbacks::ParseCallbacks for DeMangler {
|
||||
fn generated_link_name_override(&self, item_info: ItemInfo<'_>) -> Option<String> {
|
||||
self.map.get(item_info.name).cloned()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user