cd: bundle all runtime dylibs on Windows/macOS; version from workspace
Windows: tooling/package/bundle-dylibs-windows.sh collects the MSYS2 runtime DLLs (libstdc++, libgcc, OpenColorIO, ...) with ntldd -R, iterated to a fixpoint over freshly copied DLLs; a packager resources glob places them next to the executables in the NSIS installer. macOS: tooling/package/bundle-dylibs-macos.sh copies every non-system dylib otool reports into Contents/Frameworks, rewrites the install names to @executable_path/../Frameworks to a fixpoint, and ad-hoc re-signs every modified Mach-O (rewriting invalidates the seal). The CD package version no longer comes from the git tag: the root Cargo.toml gains [workspace.package] version = "0.5.0", the oak package inherits it (version.workspace = true — which cargo-packager also picks up), and the Linux container packaging parses that field.
This commit is contained in:
@@ -120,10 +120,9 @@ jobs:
|
||||
- name: Package
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
if [ "$VERSION" = "$GITHUB_REF_NAME" ]; then
|
||||
VERSION="$(cargo pkgid | sed 's/.*#//' | cut -d@ -f2-)+git"
|
||||
fi
|
||||
# The release version lives in [workspace.package] of the root
|
||||
# Cargo.toml (single source of truth; tags do not carry it).
|
||||
VERSION=$(sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)
|
||||
case "${{ matrix.distro }}" in
|
||||
debian) tooling/package/build-deb.sh "$VERSION" ;;
|
||||
fedora) tooling/package/build-rpm.sh "$VERSION" ;;
|
||||
@@ -274,6 +273,12 @@ jobs:
|
||||
- name: Package .app bundle
|
||||
run: cargo packager --release --formats app
|
||||
|
||||
# Pull the Homebrew dylibs the binaries reference into
|
||||
# Contents/Frameworks and rewrite install names to
|
||||
# @executable_path-relative (the script ad-hoc re-signs the bundle).
|
||||
- name: Bundle dylibs into the .app
|
||||
run: tooling/package/bundle-dylibs-macos.sh target/release/Oak.app
|
||||
|
||||
- name: Create DMG
|
||||
run: |
|
||||
rm -rf dmg-staging
|
||||
@@ -390,6 +395,17 @@ jobs:
|
||||
unset INCLUDE LIB
|
||||
cargo build --release --locked
|
||||
|
||||
# Collect the MSYS2 runtime DLLs (libstdc++/libgcc/OpenColorIO/...)
|
||||
# into target/pkg/win-dlls; the packager `resources` glob then
|
||||
# installs them next to the executables.
|
||||
- name: Bundle runtime DLLs
|
||||
run: |
|
||||
unset INCLUDE LIB
|
||||
pacman -S --needed --noconfirm mingw-w64-ucrt-x86_64-ntldd
|
||||
tooling/package/bundle-dylibs-windows.sh target/pkg/win-dlls \
|
||||
target/release/oak-editor.exe target/release/oak-cli.exe \
|
||||
target/release/oak-worker.exe
|
||||
|
||||
- name: Package (NSIS)
|
||||
run: cargo packager --release --formats nsis
|
||||
|
||||
|
||||
+14
-2
@@ -40,6 +40,11 @@ exclude = ["gpui", "crates/oakengine.bk"]
|
||||
default-members = [".", "crates/oak-cli", "crates/oak-worker"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
# Single source of truth for the release version: the root `oak` package
|
||||
# inherits it, and with it cargo-packager and the CD packaging scripts.
|
||||
version = "0.5.0"
|
||||
|
||||
[profile.release]
|
||||
# FFI discipline: every module crate exports an `extern "C"` ABI whose
|
||||
# entry points must never unwind/abort across the boundary; panics are
|
||||
@@ -51,7 +56,7 @@ panic = "unwind"
|
||||
|
||||
[package]
|
||||
name = "oak"
|
||||
version = "0.5.0"
|
||||
version.workspace = true
|
||||
edition = "2021"
|
||||
description = "Oak Video Editor"
|
||||
license = "GPL-3.0-or-later"
|
||||
@@ -156,7 +161,14 @@ category = "Video"
|
||||
icons = ["icons/icon.png"]
|
||||
# The UI string tables (language packs); users can drop extra
|
||||
# <lang>.yaml files into the installed i18n directory.
|
||||
resources = ["assets/i18n"]
|
||||
# The Windows DLL staging dir is filled by
|
||||
# tooling/package/bundle-dylibs-windows.sh before `cargo packager` runs
|
||||
# (NSIS/WiX place resources next to the executable, which is exactly
|
||||
# where Windows resolves DLLs from). Empty locally = no bundled DLLs.
|
||||
resources = [
|
||||
"assets/i18n",
|
||||
{ src = "target/pkg/win-dlls/*.dll", target = "." },
|
||||
]
|
||||
binaries = [
|
||||
{ path = "oak-editor", main = true },
|
||||
{ path = "oak-cli", main = false },
|
||||
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/bin/bash
|
||||
# Oak Video Editor - Non-Linear Video Editor
|
||||
# Copyright (C) 2026 Oak Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Bundle every non-system dynamic library an .app depends on into
|
||||
# Contents/Frameworks and rewrite the install names to
|
||||
# @executable_path/../Frameworks, so the app runs on machines without
|
||||
# Homebrew. (FFmpeg/OCIO are already static; what remains are the
|
||||
# Homebrew codec/filter dylibs the static FFmpeg references.)
|
||||
#
|
||||
# System libraries (/usr/lib, /System) are never copied. The set is
|
||||
# computed to a fixpoint: freshly copied dylibs can themselves reference
|
||||
# further non-system dylibs. @executable_path resolves to Contents/MacOS
|
||||
# even when the reference lives in a Frameworks dylib, so one rewrite
|
||||
# pattern fits both the executables and the libraries.
|
||||
#
|
||||
# Every modified Mach-O is ad-hoc re-signed afterwards: rewriting install
|
||||
# names invalidates the code signature, and unsigned-but-damaged binaries
|
||||
# are killed at launch on Apple Silicon.
|
||||
#
|
||||
# Usage: tooling/package/bundle-dylibs-macos.sh path/to/Oak.app
|
||||
set -euo pipefail
|
||||
|
||||
APP="${1:?usage: bundle-dylibs-macos.sh path/to/Oak.app}"
|
||||
MACOS_DIR="$APP/Contents/MacOS"
|
||||
FW_DIR="$APP/Contents/Frameworks"
|
||||
[ -d "$MACOS_DIR" ] || { echo "$APP: no Contents/MacOS directory" >&2; exit 1; }
|
||||
mkdir -p "$FW_DIR"
|
||||
|
||||
is_system() {
|
||||
case "$1" in
|
||||
/usr/lib/*|/System/*|@*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Rewrite every non-system reference of the Mach-O file $1 to
|
||||
# @executable_path/../Frameworks, copying the target in when new.
|
||||
collect() {
|
||||
local file="$1" dep base
|
||||
otool -L "$file" | awk 'NR>1 {print $1}' | while read -r dep; do
|
||||
is_system "$dep" && continue
|
||||
[ -f "$dep" ] || continue
|
||||
base=$(basename "$dep")
|
||||
if [ ! -f "$FW_DIR/$base" ]; then
|
||||
cp -L "$dep" "$FW_DIR/$base" # -L: follow Homebrew's symlinks
|
||||
chmod u+w "$FW_DIR/$base"
|
||||
echo "bundled $base"
|
||||
fi
|
||||
install_name_tool -change "$dep" "@executable_path/../Frameworks/$base" "$file"
|
||||
done
|
||||
}
|
||||
|
||||
# Fixpoint over the executables plus whatever the previous round copied.
|
||||
prev=-1
|
||||
for round in 1 2 3 4 5; do
|
||||
count=$(find "$FW_DIR" -name '*.dylib' | wc -l | tr -d ' ')
|
||||
[ "$count" = "$prev" ] && break
|
||||
prev=$count
|
||||
for f in "$MACOS_DIR"/*; do
|
||||
[ -f "$f" ] && collect "$f"
|
||||
done
|
||||
for f in "$FW_DIR"/*.dylib; do
|
||||
[ -f "$f" ] && collect "$f"
|
||||
done
|
||||
done
|
||||
|
||||
# Re-sign: install_name_tool invalidates the seal. Per-file signing
|
||||
# instead of `codesign --deep` (deprecated and unreliable with dylibs).
|
||||
find "$FW_DIR" "$MACOS_DIR" -type f -exec codesign --force --sign - {} \;
|
||||
codesign --force --sign - "$APP"
|
||||
|
||||
echo "bundled $prev dylibs into $FW_DIR"
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
# Oak Video Editor - Non-Linear Video Editor
|
||||
# Copyright (C) 2026 Oak Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Collect every MSYS2/MinGW runtime DLL the given executables depend on
|
||||
# into a staging directory. cargo packager's NSIS/WiX resources then
|
||||
# place them next to the .exe — the first place Windows resolves DLLs
|
||||
# from — so the installer works on machines without MSYS2.
|
||||
#
|
||||
# ntldd -R already recurses through a binary's own dependency tree; the
|
||||
# outer loop reaches the fixpoint for DLLs copied in earlier rounds (a
|
||||
# freshly copied DLL can itself reference further MSYS2 DLLs that the
|
||||
# initial scan did not surface through the executables alone).
|
||||
# C:\Windows\System32 entries are filtered out by the mingw/ucrt/clang
|
||||
# path match — only the toolchain runtime lands in the package.
|
||||
#
|
||||
# Must run inside the MSYS2 UCRT64 shell with
|
||||
# mingw-w64-ucrt-x86_64-ntldd installed.
|
||||
#
|
||||
# Usage: tooling/package/bundle-dylibs-windows.sh <out-dir> <exe>...
|
||||
set -euo pipefail
|
||||
|
||||
OUT="${1:?usage: bundle-dylibs-windows.sh <out-dir> <exe>...}"
|
||||
shift
|
||||
[ "$#" -ge 1 ] || { echo "no executables given" >&2; exit 1; }
|
||||
mkdir -p "$OUT"
|
||||
|
||||
if ! command -v ntldd >/dev/null; then
|
||||
echo "ntldd not found; install with: pacman -S mingw-w64-ucrt-x86_64-ntldd" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for round in 1 2 3 4 5; do
|
||||
changed=0
|
||||
# shellcheck disable=SC2046
|
||||
while IFS= read -r dep; do
|
||||
[ -n "$dep" ] || continue
|
||||
unix_dep=$(cygpath -u "$dep")
|
||||
base=$(basename "$unix_dep")
|
||||
if [ ! -f "$OUT/$base" ]; then
|
||||
cp -v "$unix_dep" "$OUT/$base"
|
||||
changed=1
|
||||
fi
|
||||
done < <(ntldd -R "$@" $(ls "$OUT"/*.dll 2>/dev/null) 2>/dev/null \
|
||||
| grep -E 'mingw|ucrt|clang' | cut -d'>' -f2 | cut -d' ' -f2 | sort -u)
|
||||
[ "$changed" = 1 ] || break
|
||||
done
|
||||
|
||||
echo "bundled $(ls "$OUT" | wc -l | tr -d ' ') DLLs into $OUT"
|
||||
Reference in New Issue
Block a user