ci(macos): restore LibTorch.framework's symlinks before signing

torch_dart's prebuilt tarball stores the framework's Versions/Current,
top-level binary and Resources as copies of Versions/A, and codesign
refuses the result as an ambiguous bundle, failing the app's signature.
relink_framework.sh puts the three symlinks back, after checking that
every copy it replaces matches Versions/A byte for byte.
This commit is contained in:
jwinterm
2026-10-27 15:34:33 -04:00
parent 6bd8f64ed7
commit bf7a47becd
2 changed files with 52 additions and 0 deletions
+4
View File
@@ -169,6 +169,10 @@ jobs:
tar -xzf torch_dart.tar.gz -C torch_dart
rm torch_dart.tar.gz
popd
# The tarball is packed on Linux with the framework's symlinks stored
# as copies, which codesign refuses as an ambiguous bundle.
scripts/macos/relink_framework.sh \
scripts/torch_dart/macos/LibTorch.xcframework/macos-arm64_x86_64/LibTorch.framework
- name: Fetch prebuilt reown_flutter
run: |
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Restore the symlinks of a versioned macOS framework whose archive flattened them.
#
# Usage: relink_framework.sh <Name.framework>
#
# torch_dart's prebuilt tarball is packed on Linux, and tar there stores
# Versions/Current, the top-level binary and Resources as full copies of
# Versions/A. codesign then calls the bundle "ambiguous (could be app or
# framework)" and refuses to sign the app around it. A versioned framework
# needs exactly:
# Versions/Current -> A
# <Name> -> Versions/Current/<Name>
# Resources -> Versions/Current/Resources
# Every copy is compared with Versions/A before it is replaced, so this never
# throws away a file that differs.
set -euo pipefail
[ $# -eq 1 ] || { echo "usage: $0 <Name.framework>" >&2; exit 64; }
fw=${1%/}
name=$(basename "$fw" .framework)
[ -f "$fw/Versions/A/$name" ] || {
echo "FATAL: $fw has no Versions/A/$name; not a versioned framework" >&2; exit 1; }
same() { # same <path> <reference>: the copy exists and matches Versions/A
[ -L "$1" ] && return 1
diff -r "$1" "$2" >/dev/null || {
echo "FATAL: $1 differs from $2; refusing to replace it with a symlink" >&2; exit 1; }
}
relink() { # relink <path> <target>
if [ -L "$fw/$1" ]; then
[ "$(readlink "$fw/$1")" = "$2" ] || {
echo "FATAL: $fw/$1 points at $(readlink "$fw/$1"), not $2" >&2; exit 1; }
return
fi
rm -rf "${fw:?}/$1"
ln -s "$2" "$fw/$1"
echo "relinked $fw/$1 -> $2"
}
[ -e "$fw/Versions/Current" ] && ! [ -L "$fw/Versions/Current" ] && same "$fw/Versions/Current" "$fw/Versions/A"
relink Versions/Current A
[ -e "$fw/$name" ] && ! [ -L "$fw/$name" ] && same "$fw/$name" "$fw/Versions/A/$name"
relink "$name" "Versions/Current/$name"
if [ -d "$fw/Versions/A/Resources" ]; then
[ -e "$fw/Resources" ] && ! [ -L "$fw/Resources" ] && same "$fw/Resources" "$fw/Versions/A/Resources"
relink Resources Versions/Current/Resources
fi