- cross-compilation to macOS
Publish / Publish (crates.io) (push) Failing after 1m47s

This commit is contained in:
w.pomp
2026-07-14 18:10:43 +02:00
parent c8d3699e55
commit 9eefa1016d
2 changed files with 107 additions and 64 deletions
+105 -63
View File
@@ -8,8 +8,6 @@ use std::fmt::Debug;
#[cfg(not(feature = "dynamic"))]
use bindgen::callbacks::ItemInfo;
#[cfg(not(feature = "dynamic"))]
use regex::Regex;
#[cfg(not(feature = "dynamic"))]
use std::collections::HashMap;
use std::fmt::{Display, Formatter};
@@ -42,7 +40,9 @@ fn lib_name_from_path(lib_path: &Path) -> Result<String, Box<dyn std::error::Err
.ok_or(Error::msg("cannot get file stem"))?
.to_str()
.ok_or(Error::msg("cannot into string"))?;
Ok(file_name.to_string())
// cargo::rustc-link-lib=static=NAME tells the linker to find libNAME.a / NAME.lib,
// so strip any leading "lib" prefix to avoid liblibNAME.
Ok(file_name.strip_prefix("lib").unwrap_or(file_name).to_string())
}
struct Error(String);
@@ -135,28 +135,38 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.define("LIBCZI_BUILD_PREFER_EXTERNALPACKAGE_RAPIDJSON", "OFF")
.define("LIBCZI_BUILD_LIBCZIAPI", "ON");
if is_cross && is_windows {
cmake_config
.define("CMAKE_SYSTEM_NAME", "Windows")
.define("CRASH_ON_UNALIGNED_ACCESS", "FALSE")
.define("ADDITIONAL_LIBS_REQUIRED_FOR_ATOMIC", "");
let has_toolchain_file = env::var("TARGET_CMAKE_TOOLCHAIN_FILE").is_ok()
|| env::var(format!(
"CMAKE_TOOLCHAIN_FILE_{}",
target.replace('-', "_")
))
.is_ok()
|| env::var("CMAKE_TOOLCHAIN_FILE").is_ok();
if !has_toolchain_file {
if is_cross {
if is_windows {
cmake_config
.define("CMAKE_C_COMPILER", "clang")
.define("CMAKE_CXX_COMPILER", "clang++")
.define("CMAKE_RC_COMPILER", "llvm-rc");
}
.define("CMAKE_SYSTEM_NAME", "Windows")
.define("CRASH_ON_UNALIGNED_ACCESS", "FALSE")
.define("ADDITIONAL_LIBS_REQUIRED_FOR_ATOMIC", "");
fix_xwin_lib_case()?;
let has_toolchain_file = env::var("TARGET_CMAKE_TOOLCHAIN_FILE").is_ok()
|| env::var(format!(
"CMAKE_TOOLCHAIN_FILE_{}",
target.replace('-', "_")
))
.is_ok()
|| env::var("CMAKE_TOOLCHAIN_FILE").is_ok();
if !has_toolchain_file {
cmake_config
.define("CMAKE_C_COMPILER", "clang")
.define("CMAKE_CXX_COMPILER", "clang++")
.define("CMAKE_RC_COMPILER", "llvm-rc");
}
fix_xwin_lib_case()?;
} else if target.contains("apple") {
cmake_config
.define("CMAKE_SYSTEM_NAME", "Darwin")
.define("ADDITIONAL_LIBS_REQUIRED_FOR_ATOMIC", "")
.define("CRASH_ON_UNALIGNED_ACCESS", "OFF");
if target.contains("aarch64") {
cmake_config.define("NEON_INTRINSICS_CAN_BE_USED", "ON");
}
}
}
if is_cross && is_windows {
@@ -340,54 +350,86 @@ impl DeMangler {
.arg("--defined-only")
.arg(&a_file)
.output()?;
let itanium_pat = Regex::new(r"^[\da-f]*\s[A-Z]\s(.*_Z(\d+)(libCZI_.*))$")?;
let msvc_pat = Regex::new(r"^[\da-f]*\s[TDB]\s(\?(libCZI_\w+)@@.*)$")?;
let mut map = HashMap::new();
for line in std::str::from_utf8(&cmd.stdout)?.lines() {
let line = line.trim();
if let Some(caps) = itanium_pat.captures(line) {
if let (Some(symbol), Some(n), Some(name)) = (caps.get(1), caps.get(2), caps.get(3))
{
let n: usize = n.as_str().parse()?;
let name = name.as_str();
let demangled = name[..n].to_string();
let mangled = symbol.as_str().to_string();
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, mangled);
}
}
} else if let Some(caps) = msvc_pat.captures(line) {
let mangled = caps.get(1).unwrap().as_str().to_string();
if let Some(name_match) = caps.get(2) {
let demangled = name_match.as_str().to_string();
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, mangled);
}
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"))]