- replace demangling with never mangling
This commit is contained in:
@@ -1,56 +0,0 @@
|
|||||||
name: Publish
|
|
||||||
|
|
||||||
on: [push, pull_request, workflow_call]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
crates_io_publish:
|
|
||||||
name: Publish (crates.io)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 25
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
submodules: 'true'
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
|
|
||||||
- name: cargo-release Cache
|
|
||||||
id: cargo_release_cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.cargo/bin/cargo-release
|
|
||||||
key: ${{ runner.os }}-cargo-release
|
|
||||||
|
|
||||||
- run: cargo install cargo-release
|
|
||||||
if: steps.cargo_release_cache.outputs.cache-hit != 'true'
|
|
||||||
|
|
||||||
- name: cargo login
|
|
||||||
run: cargo login ${{ secrets.CRATES_IO_API_TOKEN }}
|
|
||||||
|
|
||||||
# allow-branch HEAD is because GitHub actions switches
|
|
||||||
# to the tag while building, which is a detached head
|
|
||||||
|
|
||||||
# Publishing is currently messy, because:
|
|
||||||
#
|
|
||||||
# * `peace_rt_model_core` exports `NativeError` or `WebError` depending on the target.
|
|
||||||
# * `peace_rt_model_web` fails to build when publishing the workspace for a native target.
|
|
||||||
# * `peace_rt_model_web` still needs its dependencies to be published before it can be
|
|
||||||
# published.
|
|
||||||
# * `peace_rt_model_hack` needs `peace_rt_model_web` to be published before it can be
|
|
||||||
# published.
|
|
||||||
#
|
|
||||||
# We *could* pass through `--no-verify` so `cargo` doesn't build the crate before publishing,
|
|
||||||
# which is reasonable, since this job only runs after the Linux, Windows, and WASM builds
|
|
||||||
# have passed.
|
|
||||||
- name: "cargo release publish"
|
|
||||||
run: |-
|
|
||||||
cargo release \
|
|
||||||
publish \
|
|
||||||
--workspace \
|
|
||||||
--all-features \
|
|
||||||
--allow-branch "main" \
|
|
||||||
--no-confirm \
|
|
||||||
--no-verify \
|
|
||||||
--execute
|
|
||||||
@@ -22,8 +22,6 @@ thiserror = "2"
|
|||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = "0.72"
|
bindgen = "0.72"
|
||||||
cmake = "0.1"
|
cmake = "0.1"
|
||||||
cpp_demangle = "0.5"
|
|
||||||
msvc-demangler = "0.11"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
dynamic = []
|
dynamic = []
|
||||||
@@ -5,11 +5,6 @@ use std::path::{Path, PathBuf};
|
|||||||
|
|
||||||
use std::fmt::Debug;
|
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};
|
use std::fmt::{Display, Formatter};
|
||||||
|
|
||||||
fn find_static_lib(dir: &Path, base_name: &str, target_is_windows: bool) -> Option<PathBuf> {
|
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>> {
|
fn fix_xwin_lib_case() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let toolchain_key = format!(
|
let toolchain_key = format!(
|
||||||
"CMAKE_TOOLCHAIN_FILE_{}",
|
"CMAKE_TOOLCHAIN_FILE_{}",
|
||||||
@@ -120,7 +155,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
if env::var("DOCS_RS").is_err() {
|
if env::var("DOCS_RS").is_err() {
|
||||||
let host = env::var("HOST")?;
|
let host = env::var("HOST")?;
|
||||||
let target = env::var("TARGET")?;
|
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_windows = target.contains("windows");
|
||||||
let _is_macos = target.contains("apple");
|
let _is_macos = target.contains("apple");
|
||||||
|
|
||||||
@@ -177,6 +219,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
if target.contains("aarch64") {
|
if target.contains("aarch64") {
|
||||||
cmake_config.define("NEON_INTRINSICS_CAN_BE_USED", "ON");
|
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");
|
cmake_config.build_target("libCZIAPIStatic");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _importexport_guard = patch_importexport(&libcziapi_inc)?;
|
||||||
let dst = cmake_config.build();
|
let dst = cmake_config.build();
|
||||||
|
|
||||||
#[cfg(not(feature = "dynamic"))]
|
#[cfg(not(feature = "dynamic"))]
|
||||||
let bindings = {
|
let bindings = bindgen::Builder::default();
|
||||||
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,
|
|
||||||
)?))
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(feature = "dynamic")]
|
#[cfg(feature = "dynamic")]
|
||||||
let bindings = bindgen::Builder::default();
|
let bindings = bindgen::Builder::default();
|
||||||
@@ -346,106 +381,3 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
println!("cargo::rerun-if-changed=build.rs");
|
println!("cargo::rerun-if-changed=build.rs");
|
||||||
Ok(())
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1127,6 +1127,7 @@ impl CompositionChannelInfo {
|
|||||||
pub fn get_look_up_table_element_count(&self) -> i32 {
|
pub fn get_look_up_table_element_count(&self) -> i32 {
|
||||||
self.0.look_up_table_element_count
|
self.0.look_up_table_element_count
|
||||||
}
|
}
|
||||||
|
#[allow(clippy::unnecessary_cast)]
|
||||||
pub fn get_look_up_table(&self) -> Vec<u8> {
|
pub fn get_look_up_table(&self) -> Vec<u8> {
|
||||||
unsafe {
|
unsafe {
|
||||||
Vec::from_raw_parts(
|
Vec::from_raw_parts(
|
||||||
|
|||||||
Reference in New Issue
Block a user