From 03b5270bc2f601aeada53d2dbca66f7954dff4b1 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 27 Apr 2026 01:27:11 +0200 Subject: [PATCH] ci(build): enhance macOS runtime build process with git source management for libplacebo Entire-Checkpoint: c6e522b4276c --- docs/architecture/embedded-mpv-native.md | 2 +- tools/embedded-mpv/README.md | 4 +- tools/embedded-mpv/build-macos-runtime.mjs | 109 +++++++++++++++++++-- 3 files changed, 106 insertions(+), 9 deletions(-) diff --git a/docs/architecture/embedded-mpv-native.md b/docs/architecture/embedded-mpv-native.md index e87e989b0..86c93c44d 100644 --- a/docs/architecture/embedded-mpv-native.md +++ b/docs/architecture/embedded-mpv-native.md @@ -122,7 +122,7 @@ pnpm embedded-mpv:build-runtime -- arm64 /tmp/embedded-mpv-prefix pnpm embedded-mpv:stage-runtime -- arm64 /tmp/embedded-mpv-prefix ``` -The CI builder pins FFmpeg `8.1`, mpv `0.41.0`, libplacebo `7.360.1`, libass `0.17.3`, FreeType `2.13.3`, FriBidi `1.0.16`, and HarfBuzz `8.5.0`. FFmpeg disables autodetected external libraries so Homebrew libraries cannot silently enter the runtime. The generated manifest records source URLs, SHA-256 values, FFmpeg configure flags, and mpv Meson flags. The staging step normalizes that manifest to `origin: vendored-lgpl`, which release package validation requires. +The CI builder pins FFmpeg `8.1`, mpv `0.41.0`, libplacebo `7.360.1`, libass `0.17.3`, FreeType `2.13.3`, FriBidi `1.0.16`, and HarfBuzz `8.5.0`. FFmpeg disables autodetected external libraries so Homebrew libraries cannot silently enter the runtime. Libplacebo is checked out from git with the OpenGL-related submodules required by its Meson build because the generated GitHub archive does not include submodule contents. The generated manifest records source URLs, archive SHA-256 values where applicable, libplacebo git commit/submodule metadata, FFmpeg configure flags, and mpv Meson flags. The staging step normalizes that manifest to `origin: vendored-lgpl`, which release package validation requires. The Electron backend build consumes the staged runtime, copies Mach-O runtime files into the native build output, and rewrites Mach-O paths so `embedded_mpv.node` loads `@loader_path/lib/libmpv.2.dylib` instead of a machine-local Homebrew path. After `install_name_tool` rewrites any addon or runtime binary, the build re-signs that binary with an ad-hoc signature for local development. Release packaging still performs the normal app signing and notarization later. diff --git a/tools/embedded-mpv/README.md b/tools/embedded-mpv/README.md index eb49e9b98..1e711bec3 100644 --- a/tools/embedded-mpv/README.md +++ b/tools/embedded-mpv/README.md @@ -61,10 +61,10 @@ The builder currently pins: - FFmpeg `8.1`, configured without `--enable-gpl` or `--enable-nonfree`, and with autodetected external libraries disabled - mpv `0.41.0`, configured with `-Dlibmpv=true -Dgpl=false` -- libplacebo `7.360.1` +- libplacebo `7.360.1`, checked out from git with the OpenGL-related submodules required by its Meson build - libass `0.17.3` plus FreeType, FriBidi, and HarfBuzz -The build manifest records source URLs, downloaded source SHA-256 values, and the exact FFmpeg/mpv flags. The staged manifest is normalized to `origin: vendored-lgpl`, which is the only embedded MPV runtime origin allowed in required macOS release packaging. +The build manifest records source URLs, downloaded archive SHA-256 values where applicable, libplacebo git commit/submodule metadata, and the exact FFmpeg/mpv flags. The staged manifest is normalized to `origin: vendored-lgpl`, which is the only embedded MPV runtime origin allowed in required macOS release packaging. ## Build Integration diff --git a/tools/embedded-mpv/build-macos-runtime.mjs b/tools/embedded-mpv/build-macos-runtime.mjs index 853ba1e7f..5520bf505 100644 --- a/tools/embedded-mpv/build-macos-runtime.mjs +++ b/tools/embedded-mpv/build-macos-runtime.mjs @@ -47,7 +47,8 @@ const sourcePackages = [ { id: 'libplacebo', version: '7.360.1', - url: 'https://github.com/haasn/libplacebo/archive/refs/tags/v7.360.1.tar.gz', + tag: 'v7.360.1', + gitUrl: 'https://github.com/haasn/libplacebo.git', license: 'LGPL-2.1-or-later', }, { @@ -196,6 +197,7 @@ function ensureTools() { 'meson', 'ninja', 'pkg-config', + 'git', ]; const missing = requiredCommands.filter((command) => !commandExists(command)); @@ -224,11 +226,86 @@ function sha256File(filePath) { return hash.digest('hex'); } +function runCapture(command, commandArgs, options = {}) { + const result = spawnSync(command, commandArgs, { + cwd: options.cwd ?? workspaceRoot, + env: options.env ?? buildEnv(), + encoding: 'utf8', + stdio: 'pipe', + ...options, + }); + + if (result.status !== 0) { + const stderr = result.stderr ? `\n${result.stderr}` : ''; + throw new Error( + `${command} ${commandArgs.join(' ')} failed with status ${ + result.status ?? 1 + }.${stderr}` + ); + } + + return result.stdout.trim(); +} + +function cloneGitSource(sourcePackage) { + const packageSourcePath = sourcePathFor(sourcePackage.id); + fs.rmSync(packageSourcePath, { recursive: true, force: true }); + + run('git', [ + 'clone', + '--depth', + '1', + '--branch', + sourcePackage.tag, + sourcePackage.gitUrl, + packageSourcePath, + ]); + run( + 'git', + [ + 'submodule', + 'update', + '--init', + '--depth', + '1', + '3rdparty/glad', + '3rdparty/jinja', + '3rdparty/markupsafe', + '3rdparty/fast_float', + ], + { cwd: packageSourcePath } + ); + + sourcePackage.gitCommit = runCapture('git', ['rev-parse', 'HEAD'], { + cwd: packageSourcePath, + }); + sourcePackage.submodules = runCapture( + 'git', + [ + 'submodule', + 'status', + '3rdparty/glad', + '3rdparty/jinja', + '3rdparty/markupsafe', + '3rdparty/fast_float', + ], + { cwd: packageSourcePath } + ) + .split(/\r?\n/) + .map((line) => line.trim()) + .filter(Boolean); +} + function downloadSources() { fs.mkdirSync(archiveRoot, { recursive: true }); fs.mkdirSync(sourceRoot, { recursive: true }); for (const sourcePackage of sourcePackages) { + if (sourcePackage.gitUrl) { + cloneGitSource(sourcePackage); + continue; + } + const archivePath = archivePathFor(sourcePackage); if (!fs.existsSync(archivePath)) { run('curl', [ @@ -414,8 +491,17 @@ function sourceMetadata(packageId) { const sourcePackage = packageById.get(packageId); return { version: sourcePackage.version, - sourceUrl: sourcePackage.url, - sourceSha256: sourcePackage.sha256, + sourceUrl: sourcePackage.url ?? sourcePackage.gitUrl, + ...(sourcePackage.tag ? { sourceTag: sourcePackage.tag } : {}), + ...(sourcePackage.sha256 + ? { sourceSha256: sourcePackage.sha256 } + : {}), + ...(sourcePackage.gitCommit + ? { sourceGitCommit: sourcePackage.gitCommit } + : {}), + ...(sourcePackage.submodules + ? { sourceSubmodules: sourcePackage.submodules } + : {}), license: sourcePackage.license, }; } @@ -435,8 +521,19 @@ function writeManifest() { sourcePackage.id, { version: sourcePackage.version, - sourceUrl: sourcePackage.url, - sourceSha256: sourcePackage.sha256, + sourceUrl: sourcePackage.url ?? sourcePackage.gitUrl, + ...(sourcePackage.tag + ? { sourceTag: sourcePackage.tag } + : {}), + ...(sourcePackage.sha256 + ? { sourceSha256: sourcePackage.sha256 } + : {}), + ...(sourcePackage.gitCommit + ? { sourceGitCommit: sourcePackage.gitCommit } + : {}), + ...(sourcePackage.submodules + ? { sourceSubmodules: sourcePackage.submodules } + : {}), license: sourcePackage.license, }, ]) @@ -453,7 +550,7 @@ function writeManifest() { mesonFlags: mpvMesonFlags, }, sourceDistribution: - 'Attach the downloaded source archives, this manifest, and any local patches with the macOS binary release.', + 'Attach the downloaded source archives, the libplacebo git checkout metadata, this manifest, and any local patches with the macOS binary release.', }; fs.writeFileSync(