From 61da70ecf8915851780ab60354f4f2df0459f730 Mon Sep 17 00:00:00 2001 From: Mike Solar Date: Mon, 17 Aug 2026 19:42:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(build):=20launch=20crash=20=E2=80=94=20@rpa?= =?UTF-8?q?th/libz.1.dylib=20had=20no=20LC=5FRPATH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The static FFmpeg's external codec libs pull in -lz, which on this toolchain resolves to a copy whose install name is @rpath/libz.1.dylib (zlib-ng-compat); without an LC_RPATH entry all three binaries died in dyld at startup. The app/cli/worker build scripts now emit -Wl,-rpath,/usr/lib. Also: FFMPEG_DIR moves into the committed .cargo/config.toml as a workspace-relative [env] entry — ffmpeg-sys-next's build script cannot read .env files, and without it the crate silently linked the shared Homebrew FFmpeg while oakffmpeg-link emitted the static transitive flags (mixed linkage). docs/build.md updated. --- .cargo/config.toml | 24 +++++++++++++++++++++++ build.rs | 6 ++++++ crates/oak-cli/build.rs | 28 +++++++++++++++++++++++++++ crates/oak-worker/build.rs | 28 +++++++++++++++++++++++++++ crates/oakffmpeg-link/build.rs | 8 ++++++++ docs/build.md | 6 +++++- docs/zh/plans/riir/M14-direct-rlib.md | 2 +- 7 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 crates/oak-cli/build.rs create mode 100644 crates/oak-worker/build.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000..024cc9b58 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,24 @@ +# 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 . + +# The project FFmpeg (built by tooling/ffmpeg/build-ffmpeg.sh into +# .cache/ffmpeg) is the only supported FFmpeg: ffmpeg-sys-next reads +# FFMPEG_DIR at build-script time, which cannot come from a .env file — +# a relative [env] entry here is the only machine-agnostic way to set +# it. Run tooling/ffmpeg/build-ffmpeg.sh once before the first build. + +[env] +FFMPEG_DIR = { value = ".cache/ffmpeg", relative = true } diff --git a/build.rs b/build.rs index 4f58758a1..d42e1e376 100644 --- a/build.rs +++ b/build.rs @@ -30,5 +30,11 @@ fn main() { let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); if os == "macos" { println!("cargo:rustc-link-lib=framework=IOSurface"); + // The static FFmpeg's external codec libraries pull in `-lz`, and + // on some machines that resolves to a package-manager copy whose + // install name is @rpath/libz.1.dylib; without an LC_RPATH entry + // the binary dies at launch ("Library not loaded"). Map the rpath + // at the real system library. + println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/lib"); } } diff --git a/crates/oak-cli/build.rs b/crates/oak-cli/build.rs new file mode 100644 index 000000000..6f0ed76a7 --- /dev/null +++ b/crates/oak-cli/build.rs @@ -0,0 +1,28 @@ +// 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 . + +//! Build-time link configuration. + +fn main() { + if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") { + // The static FFmpeg's external codec libraries pull in `-lz`, and + // on some machines that resolves to a package-manager copy whose + // install name is @rpath/libz.1.dylib; without an LC_RPATH entry + // the binary dies at launch ("Library not loaded"). Map the rpath + // at the real system library. + println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/lib"); + } +} diff --git a/crates/oak-worker/build.rs b/crates/oak-worker/build.rs new file mode 100644 index 000000000..6f0ed76a7 --- /dev/null +++ b/crates/oak-worker/build.rs @@ -0,0 +1,28 @@ +// 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 . + +//! Build-time link configuration. + +fn main() { + if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") { + // The static FFmpeg's external codec libraries pull in `-lz`, and + // on some machines that resolves to a package-manager copy whose + // install name is @rpath/libz.1.dylib; without an LC_RPATH entry + // the binary dies at launch ("Library not loaded"). Map the rpath + // at the real system library. + println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/lib"); + } +} diff --git a/crates/oakffmpeg-link/build.rs b/crates/oakffmpeg-link/build.rs index bd6fda6a1..5ffc1e68f 100644 --- a/crates/oakffmpeg-link/build.rs +++ b/crates/oakffmpeg-link/build.rs @@ -90,6 +90,14 @@ fn main() { ); } + // System libraries (z, m, bz2, iconv) must come from the OS, not from + // a package manager's keg: Homebrew's zlib carries an @rpath install + // name, and linking it without an rpath entry breaks the binary at + // launch (dyld: Library not loaded: @rpath/libz.1.dylib). Put /usr/lib + // first in the search order so -lz resolves to the system copy. + #[cfg(target_os = "macos")] + println!("cargo:rustc-link-search=native=/usr/lib"); + for token in String::from_utf8_lossy(&output.stdout).split_whitespace() { if let Some(path) = token.strip_prefix("-L") { println!("cargo:rustc-link-search=native={path}"); diff --git a/docs/build.md b/docs/build.md index cf9c4004c..f5eeb3768 100644 --- a/docs/build.md +++ b/docs/build.md @@ -23,10 +23,14 @@ This document describes how to build Oak Video Editor from source on Windows, Li > ```sh > tooling/install-deps.sh # Homebrew / MSYS2 UCRT64 / Debian / Fedora / Arch > tooling/ffmpeg/build-ffmpeg.sh # clones release/8.0, installs into .cache/ffmpeg -> export FFMPEG_DIR="$(pwd)/.cache/ffmpeg" > cargo build > ``` > +> `FFMPEG_DIR` no longer needs exporting: the committed +> `.cargo/config.toml` sets it relative to the workspace root (the +> ffmpeg-sys-next build script cannot read `.env` files — this is the +> only machine-agnostic way). +> > External libraries are probed with `pkg-config` and silently skipped > when missing. `FFMPEG_DIR` is mandatory (the `oakffmpeg-link` build > script panics without it): silently binding a system FFmpeg risks diff --git a/docs/zh/plans/riir/M14-direct-rlib.md b/docs/zh/plans/riir/M14-direct-rlib.md index ca24ea969..49e1a9bbf 100644 --- a/docs/zh/plans/riir/M14-direct-rlib.md +++ b/docs/zh/plans/riir/M14-direct-rlib.md @@ -1,4 +1,4 @@ -# M14:前端绕过 facade 直链 rlib(纯 Rust ABI) + # M14:前端绕过 facade 直链 rlib(纯 Rust ABI) > 前置:单库化(single-lib.md)+ 模块 bridge/ffi 清除已完成; > liboakengine.dylib 的 C ABI 冻结,专供插件/外部消费者。