Skip to content

Commit f8704d8

Browse files
committed
Fix Koharu enum ABI in release builds
1 parent d02bedb commit f8704d8

2 files changed

Lines changed: 86 additions & 0 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""Patch koharu-diffusion's C enum wrappers for the current target ABI."""
2+
3+
from __future__ import annotations
4+
5+
import json
6+
import subprocess
7+
from pathlib import Path
8+
9+
10+
def koharu_enums_path() -> Path:
11+
metadata = subprocess.run(
12+
["cargo", "metadata", "--locked", "--format-version", "1"],
13+
check=True,
14+
stdout=subprocess.PIPE,
15+
text=True,
16+
encoding="utf-8",
17+
)
18+
packages = json.loads(metadata.stdout)["packages"]
19+
matches = [
20+
package
21+
for package in packages
22+
if package["name"] == "koharu-diffusion"
23+
and package["source"].startswith("git+")
24+
]
25+
if len(matches) != 1:
26+
raise RuntimeError(
27+
f"expected one Git koharu-diffusion package, found {len(matches)}"
28+
)
29+
return Path(matches[0]["manifest_path"]).parent / "src" / "enums.rs"
30+
31+
32+
path = koharu_enums_path()
33+
source = path.read_text(encoding="utf-8")
34+
35+
if "type FfiEnumRepr" not in source:
36+
anchor = "use crate::{Error, Result, ffi::NativeCall, sys};\n"
37+
replacement = anchor + """
38+
39+
// Clang uses an unsigned C enum representation for these non-negative values,
40+
// while MSVC uses a signed representation. Match bindgen's target ABI.
41+
#[cfg(target_env = "msvc")]
42+
type FfiEnumRepr = i32;
43+
#[cfg(not(target_env = "msvc"))]
44+
type FfiEnumRepr = u32;
45+
"""
46+
if source.count(anchor) != 1:
47+
raise RuntimeError("koharu-diffusion import anchor changed")
48+
source = source.replace(anchor, replacement)
49+
50+
replacements = {
51+
" #[repr(i32)]\n": (
52+
" #[cfg_attr(target_env = \"msvc\", repr(i32))]\n"
53+
" #[cfg_attr(not(target_env = \"msvc\"), repr(u32))]\n"
54+
),
55+
"pub const fn as_raw(self) -> i32": "pub const fn as_raw(self) -> FfiEnumRepr",
56+
"impl TryFrom<i32> for $name": "impl TryFrom<FfiEnumRepr> for $name",
57+
"fn try_from(value: i32) -> Result<Self>": (
58+
"fn try_from(value: FfiEnumRepr) -> Result<Self>"
59+
),
60+
"value => Err(Error::InvalidEnum { kind: $kind, value }),": (
61+
"value => Err(Error::InvalidEnum { kind: $kind, value: value as i32 }),"
62+
),
63+
}
64+
65+
expected_counts = {
66+
" #[repr(i32)]\n": 2,
67+
"pub const fn as_raw(self) -> i32": 2,
68+
"impl TryFrom<i32> for $name": 2,
69+
"fn try_from(value: i32) -> Result<Self>": 2,
70+
"value => Err(Error::InvalidEnum { kind: $kind, value }),": 2,
71+
}
72+
73+
for old, new in replacements.items():
74+
count = source.count(old)
75+
if count == 0 and new in source:
76+
continue
77+
if count != expected_counts[old]:
78+
raise RuntimeError(f"unexpected occurrence count for {old!r}: {count}")
79+
source = source.replace(old, new)
80+
81+
path.write_text(source, encoding="utf-8")
82+
print(f"patched {path}")

.github/workflows/release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ jobs:
5555
- name: Install Rust toolchain
5656
uses: dtolnay/rust-toolchain@stable
5757

58+
- name: Patch Koharu C enum ABI compatibility
59+
working-directory: flint
60+
run: python .github/scripts/patch-koharu-diffusion.py
61+
5862
- name: Preload Unix LibTorch
5963
if: runner.os != 'Windows'
6064
working-directory: flint

0 commit comments

Comments
 (0)