mirror of
https://github.com/citron-neo/CI.git
synced 2026-07-05 15:21:59 -07:00
Fix macOS SDL3 workflow dependency
This commit is contained in:
@@ -66,7 +66,7 @@ jobs:
|
||||
|
||||
- name: Install System Dependencies via Homebrew
|
||||
run: |
|
||||
brew install ninja boost catch2 cmake enet fmt ffmpeg glslang hidapi libvpx lld llvm nasm nlohmann-json openal-soft sdl2 molten-vk vulkan-headers vulkan-loader webp lz4 zstd openssl@3 pkg-config libusb opus python@3.12
|
||||
brew install ninja boost catch2 cmake enet fmt ffmpeg glslang hidapi libvpx lld llvm nasm nlohmann-json openal-soft sdl2 sdl3 molten-vk vulkan-headers vulkan-loader webp lz4 zstd openssl@3 pkg-config libusb opus python@3.12
|
||||
|
||||
- name: Clone Citron Source
|
||||
shell: bash
|
||||
@@ -192,6 +192,8 @@ jobs:
|
||||
"$MACDEPLOYQT_PATH" "$APP_BUNDLE_PATH" -libpath="$QT_LIB_PATH" -verbose=1 -always-overwrite
|
||||
|
||||
FRAMEWORKS_PATH="$APP_BUNDLE_PATH/Contents/Frameworks"
|
||||
EXECUTABLE_PATH="$APP_BUNDLE_PATH/Contents/MacOS/citron"
|
||||
mkdir -p "$FRAMEWORKS_PATH"
|
||||
|
||||
# Create Vulkan ICD json to ensure bundled MoltenVK is used (not homebrew's)
|
||||
echo "Setting up Vulkan ICD for bundled MoltenVK..."
|
||||
@@ -209,40 +211,62 @@ jobs:
|
||||
ICDEOF
|
||||
echo "Created MoltenVK ICD at $VULKAN_ICD_DIR/MoltenVK_icd.json"
|
||||
|
||||
# Copy missing transitive dependencies (like libsharpyuv from webp, liblcms2 from jxl)
|
||||
# Copy missing transitive dependencies (like libsharpyuv from webp, liblcms2 from jxl).
|
||||
# Scan the main executable too; macdeployqt can miss non-Qt Homebrew libraries linked by citron.
|
||||
echo "Checking for missing transitive dependencies..."
|
||||
copy_missing_deps() {
|
||||
find_bundled_binaries() {
|
||||
printf '%s\n' "$EXECUTABLE_PATH"
|
||||
find "$FRAMEWORKS_PATH" -name "*.dylib" -type f | while read -r dylib; do
|
||||
# Handle @rpath/ references
|
||||
otool -L "$dylib" 2>/dev/null | grep -E "^\s+@rpath/" | awk '{print $1}' | sed 's|@rpath/||' | while read -r dep; do
|
||||
if [ ! -f "$FRAMEWORKS_PATH/$dep" ]; then
|
||||
HOMEBREW_LIB=$(find /opt/homebrew/lib /opt/homebrew/Cellar /usr/local/lib -name "$dep" 2>/dev/null | head -1)
|
||||
if [ -n "$HOMEBREW_LIB" ] && [ -f "$HOMEBREW_LIB" ]; then
|
||||
echo "Copying missing @rpath dependency: $dep"
|
||||
cp "$HOMEBREW_LIB" "$FRAMEWORKS_PATH/"
|
||||
chmod u+w "$FRAMEWORKS_PATH/$dep"
|
||||
install_name_tool -id "@rpath/$dep" "$FRAMEWORKS_PATH/$dep" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
# Handle absolute homebrew path references (critical for portability!)
|
||||
otool -L "$dylib" 2>/dev/null | grep -E "^\s+(/opt/homebrew|/usr/local)" | awk '{print $1}' | while read -r abs_dep; do
|
||||
dep_name=$(basename "$abs_dep")
|
||||
if [ ! -f "$FRAMEWORKS_PATH/$dep_name" ] && [ -f "$abs_dep" ]; then
|
||||
echo "Copying missing absolute-path dependency: $dep_name (from $abs_dep)"
|
||||
cp "$abs_dep" "$FRAMEWORKS_PATH/"
|
||||
chmod u+w "$FRAMEWORKS_PATH/$dep_name"
|
||||
install_name_tool -id "@rpath/$dep_name" "$FRAMEWORKS_PATH/$dep_name" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
printf '%s\n' "$dylib"
|
||||
done
|
||||
find "$FRAMEWORKS_PATH" -name "*.framework" -type d | while read -r framework_dir; do
|
||||
framework_name=$(basename "$framework_dir" .framework)
|
||||
framework_binary="$framework_dir/Versions/A/$framework_name"
|
||||
[ ! -f "$framework_binary" ] && framework_binary="$framework_dir/$framework_name"
|
||||
[ -f "$framework_binary" ] && printf '%s\n' "$framework_binary"
|
||||
done
|
||||
}
|
||||
|
||||
copy_deps_for_binary() {
|
||||
local binary="$1"
|
||||
[ -f "$binary" ] || return 0
|
||||
|
||||
# Handle @rpath/ references
|
||||
otool -L "$binary" 2>/dev/null | grep -E "^\s+@rpath/" | awk '{print $1}' | sed 's|@rpath/||' | while read -r dep; do
|
||||
if [ ! -f "$FRAMEWORKS_PATH/$dep" ]; then
|
||||
HOMEBREW_LIB=$(find /opt/homebrew/lib /opt/homebrew/Cellar /usr/local/lib -name "$dep" 2>/dev/null | head -1)
|
||||
if [ -n "$HOMEBREW_LIB" ] && [ -f "$HOMEBREW_LIB" ]; then
|
||||
echo "Copying missing @rpath dependency for $(basename "$binary"): $dep"
|
||||
cp "$HOMEBREW_LIB" "$FRAMEWORKS_PATH/"
|
||||
chmod u+w "$FRAMEWORKS_PATH/$dep"
|
||||
install_name_tool -id "@rpath/$dep" "$FRAMEWORKS_PATH/$dep" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Handle absolute homebrew path references (critical for portability!)
|
||||
otool -L "$binary" 2>/dev/null | grep -E "^\s+(/opt/homebrew|/usr/local)" | awk '{print $1}' | while read -r abs_dep; do
|
||||
dep_name=$(basename "$abs_dep")
|
||||
if [ ! -f "$FRAMEWORKS_PATH/$dep_name" ] && [ -f "$abs_dep" ]; then
|
||||
echo "Copying missing absolute-path dependency for $(basename "$binary"): $dep_name (from $abs_dep)"
|
||||
cp "$abs_dep" "$FRAMEWORKS_PATH/"
|
||||
chmod u+w "$FRAMEWORKS_PATH/$dep_name"
|
||||
install_name_tool -id "@rpath/$dep_name" "$FRAMEWORKS_PATH/$dep_name" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
copy_missing_deps() {
|
||||
find_bundled_binaries | while read -r binary; do
|
||||
copy_deps_for_binary "$binary"
|
||||
done
|
||||
}
|
||||
|
||||
# Run multiple passes to catch nested dependencies
|
||||
for i in 1 2 3 4 5; do
|
||||
echo "Pass $i: checking dependencies..."
|
||||
copy_missing_deps
|
||||
done
|
||||
EXECUTABLE_PATH="$APP_BUNDLE_PATH/Contents/MacOS/citron"
|
||||
|
||||
install_name_tool -add_rpath "@executable_path/../Frameworks" "$EXECUTABLE_PATH" 2>/dev/null || true
|
||||
|
||||
@@ -299,8 +323,50 @@ jobs:
|
||||
[ -f "$framework_binary" ] && install_name_tool -id "@rpath/$framework_name.framework/Versions/A/$framework_name" "$framework_binary" 2>/dev/null || true
|
||||
done
|
||||
|
||||
find_bundled_binaries | while read -r binary; do
|
||||
otool -L "$binary" 2>/dev/null | grep -E "^\s+/" | awk '{print $1}' | while read -r dep; do
|
||||
dep_name=$(basename "$dep")
|
||||
if [ -f "$FRAMEWORKS_PATH/$dep_name" ]; then
|
||||
install_name_tool -change "$dep" "@rpath/$dep_name" "$binary" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Some SDL3 consumers load "libSDL3.dylib" dynamically at runtime, so it will not
|
||||
# necessarily appear in otool output. Homebrew/macdeployqt may only leave
|
||||
# "libSDL3.0.dylib" in Frameworks, which makes that dlopen path fail.
|
||||
SDL3_BREW_PREFIX="$(brew --prefix sdl3 2>/dev/null || true)"
|
||||
if [ ! -f "$FRAMEWORKS_PATH/libSDL3.dylib" ]; then
|
||||
if [ -n "$SDL3_BREW_PREFIX" ] && [ -f "$SDL3_BREW_PREFIX/lib/libSDL3.dylib" ]; then
|
||||
echo "Copying libSDL3.dylib from Homebrew for runtime dlopen compatibility"
|
||||
cp "$SDL3_BREW_PREFIX/lib/libSDL3.dylib" "$FRAMEWORKS_PATH/libSDL3.dylib"
|
||||
elif [ -f "$FRAMEWORKS_PATH/libSDL3.0.dylib" ]; then
|
||||
echo "Creating libSDL3.dylib from bundled libSDL3.0.dylib for runtime dlopen compatibility"
|
||||
cp "$FRAMEWORKS_PATH/libSDL3.0.dylib" "$FRAMEWORKS_PATH/libSDL3.dylib"
|
||||
fi
|
||||
fi
|
||||
if [ -f "$FRAMEWORKS_PATH/libSDL3.dylib" ]; then
|
||||
chmod u+w "$FRAMEWORKS_PATH/libSDL3.dylib"
|
||||
install_name_tool -id "@rpath/libSDL3.dylib" "$FRAMEWORKS_PATH/libSDL3.dylib" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
chmod -R u+w "$APP_BUNDLE_PATH"
|
||||
codesign --force --deep -s - "$APP_BUNDLE_PATH"
|
||||
codesign --verify --deep --strict --verbose=2 "$APP_BUNDLE_PATH"
|
||||
|
||||
echo "Final executable SDL dependencies:"
|
||||
otool -L "$EXECUTABLE_PATH" | grep -i SDL || true
|
||||
|
||||
echo "Final executable rpaths:"
|
||||
otool -l "$EXECUTABLE_PATH" | grep -A2 LC_RPATH || true
|
||||
|
||||
echo "Checking for remaining Homebrew library references..."
|
||||
if find_bundled_binaries | while read -r binary; do
|
||||
otool -L "$binary" 2>/dev/null | grep -E "^\s+(/opt/homebrew|/usr/local)" && echo " in $binary"
|
||||
done | tee /tmp/citron-homebrew-refs.txt; [ -s /tmp/citron-homebrew-refs.txt ]; then
|
||||
echo "::error::Packaged app still contains Homebrew library references."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Step 8: Create the final DMG
|
||||
echo "Creating final DMG..."
|
||||
|
||||
Reference in New Issue
Block a user