feat(nix): implemented wayland screencast support and restructured package builder

- Added `withWaylandScreencast` package override option to selectively link libpipewire for Wayland screencast support.
- Refactored Nix package builder structure to eliminate wrapper scripts and directly install binary outputs.
- Updated home-manager module description to clarify declarative settings file behavior and symlink rules.
This commit is contained in:
can1357
2026-08-13 05:25:22 +02:00
parent a53e4e790d
commit dc7784e4b4
6 changed files with 143 additions and 145 deletions
+6 -1
View File
@@ -23,7 +23,12 @@ in
settings = lib.mkOption {
type = lib.types.nullOr yaml.type;
default = null;
description = "Settings written declaratively to ~/.omp/agent/config.yml.";
description = ''
Settings written declaratively to {file}`~/.omp/agent/config.yml`.
The file is a read-only store symlink: changes made from inside OMP
(`/settings`, onboarding) replace it but revert on the next
`home-manager switch`.
'';
example = {
theme.dark = "titanium";
startup.quiet = true;
+132 -139
View File
@@ -1,17 +1,13 @@
{
autoPatchelfHook ? null,
autoSignDarwinBinariesHook ? null,
autoPatchelfHook,
bun,
bun2nix,
cmake,
darwin,
lib,
libopus,
libpulseaudio ? null,
makeWrapper,
ninja,
openssl,
pcre2,
pipewire ? null,
pipewire,
pkg-config,
rustPlatform,
rustToolchain,
@@ -19,8 +15,10 @@
stdenv,
stdenvNoCC,
unzip,
zig,
zlib,
# Wayland screencast support links libpipewire, whose runtime closure adds
# ~750 MB (gstreamer, ffmpeg, systemd, ...). Official npm/Bazel addons ship
# without it, so default to the lean build; opt in via `.override`.
withWaylandScreencast ? false,
}:
let
packageJson = lib.importJSON ../packages/coding-agent/package.json;
@@ -68,142 +66,137 @@ let
'';
};
in
stdenv.mkDerivation (
{
pname = "omp";
inherit (packageJson) version;
src = source;
stdenv.mkDerivation {
pname = "omp";
inherit (packageJson) version;
src = source;
cargoDeps = rustPlatform.importCargoLock { lockFile = ../Cargo.lock; };
bunDeps = bun2nix.fetchBunDeps {
bunNix = ./bun.nix;
overrides = patchOverrides;
};
cargoDeps = rustPlatform.importCargoLock { lockFile = ../Cargo.lock; };
bunDeps = bun2nix.fetchBunDeps {
bunNix = ./bun.nix;
overrides = patchOverrides;
};
nativeBuildInputs = [
bun
bun2nix.hook
cmake
makeWrapper
ninja
pkg-config
rustPlatform.bindgenHook
rustPlatform.cargoSetupHook
rustToolchain
zig
]
++ lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]
++ lib.optionals stdenv.hostPlatform.isDarwin [ autoSignDarwinBinariesHook ];
nativeBuildInputs = [
bun
bun2nix.hook
cmake
ninja
pkg-config
rustPlatform.bindgenHook
rustPlatform.cargoSetupHook
rustToolchain
]
++ lib.optionals stdenv.hostPlatform.isLinux [ autoPatchelfHook ]
++ lib.optionals stdenv.hostPlatform.isDarwin [ darwin.autoSignDarwinBinariesHook ];
buildInputs = [
libopus
openssl
pcre2
]
++ lib.optionals stdenv.hostPlatform.isLinux [
libpulseaudio
pipewire
stdenv.cc.cc.lib
zlib
];
# pcre2 is vendored via PCRE2_SYS_STATIC, but opus must link the nixpkgs
# library: audiopus_sys' bundled cmake build installs to lib64 while its
# link-search hardcodes lib, so the pkg-config path is the one that works.
# libgcc_s is resolved from the compiler's lib output during autoPatchelf.
# All dynamic store paths are pinned into the closure via nix-support (see
# installPhase).
buildInputs = [
libopus
]
++ lib.optionals stdenv.hostPlatform.isLinux [ stdenv.cc.cc.lib ]
++ lib.optionals withWaylandScreencast [ pipewire ];
strictDeps = true;
# Nix builders cannot reliably hardlink cache files into node_modules
# (and Darwin's clonefile backend also rejects store permissions).
bunInstallFlags = [
"--linker=isolated"
"--backend=copyfile"
];
dontConfigure = true;
dontRunLifecycleScripts = true;
dontUseBunBuild = true;
dontUseBunCheck = true;
dontUseBunInstall = true;
dontStrip = true;
strictDeps = true;
# Nix builders cannot reliably hardlink cache files into node_modules
# (and Darwin's clonefile backend also rejects store permissions).
bunInstallFlags = [
"--linker=isolated"
"--backend=copyfile"
];
dontConfigure = true;
dontRunLifecycleScripts = true;
dontUseBunBuild = true;
dontUseBunCheck = true;
dontUseBunInstall = true;
dontStrip = true;
env = {
CMAKE_POLICY_VERSION_MINIMUM = "3.5";
PCRE2_SYS_STATIC = "1";
SOURCE_DATE_EPOCH = "1";
env = {
CMAKE_POLICY_VERSION_MINIMUM = "3.5";
PCRE2_SYS_STATIC = "1";
SOURCE_DATE_EPOCH = "1";
}
// lib.optionalAttrs (platform ? rustFlags) { RUSTFLAGS = platform.rustFlags; }
// lib.optionalAttrs stdenv.hostPlatform.isDarwin { BUN_NO_CODESIGN_MACHO_BINARY = "1"; };
buildPhase = ''
runHook preBuild
echo "Building pi-natives"
cargo build --release -p pi-natives ${lib.optionalString withWaylandScreencast "--features wayland-pipewire"}
install -Dm755 "target/release/${platform.nativeLibrary}" \
"packages/natives/native/${platform.addon}"
${lib.optionalString stdenv.hostPlatform.isLinux ''
# The loader extracts this archived addon at runtime, so fix its
# interpreter-independent Nix RPATH before Bun embeds it.
autoPatchelf -- "packages/natives/native/${platform.addon}"
''}
${lib.optionalString stdenv.hostPlatform.isDarwin ''
# arm64 Darwin requires even locally-built Mach-O addons to carry an
# ad-hoc signature. Sign before Bun archives the file.
signIfRequired "packages/natives/native/${platform.addon}"
''}
echo "Compiling OMP"
BUN_COMPILE_EXECUTABLE_PATH="${bunRuntimeTemplate}/libexec/bun" \
bun --cwd="$PWD/packages/coding-agent" run build
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm755 packages/coding-agent/dist/omp "$out/bin/omp"
# The addon is gzip-compressed inside the compiled binary, so the store
# paths it links against are invisible to the output reference scanner.
# Record them in plain text to pin the libraries into the runtime closure.
mkdir -p "$out/nix-support"
${
if stdenv.hostPlatform.isLinux then
''
patchelf --print-rpath "packages/natives/native/${platform.addon}" \
> "$out/nix-support/embedded-addon-runpath"
''
else
''
echo "${lib.getLib libopus}/lib" > "$out/nix-support/embedded-addon-runpath"
''
}
// lib.optionalAttrs (platform ? rustFlags) { RUSTFLAGS = platform.rustFlags; }
// lib.optionalAttrs stdenv.hostPlatform.isDarwin { BUN_NO_CODESIGN_MACHO_BINARY = "1"; };
buildPhase = ''
runHook preBuild
runHook postInstall
'';
echo "Building pi-natives"
cargo build --release -p pi-natives ${lib.optionalString stdenv.hostPlatform.isLinux "--features wayland-pipewire"}
install -Dm755 "target/release/${platform.nativeLibrary}" \
"packages/natives/native/${platform.addon}"
${lib.optionalString stdenv.hostPlatform.isLinux ''
# The loader extracts this archived addon at runtime, so fix its
# interpreter-independent Nix RPATH before Bun embeds it.
autoPatchelf -- "packages/natives/native/${platform.addon}"
''}
${lib.optionalString stdenv.hostPlatform.isDarwin ''
# arm64 Darwin requires even locally-built Mach-O addons to carry an
# ad-hoc signature. Sign before Bun archives the file.
signIfRequired "packages/natives/native/${platform.addon}"
''}
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
HOME="$TMPDIR" "$out/bin/omp" --smoke-test | grep -q "smoke-test: ok"
BUN_BE_BUN=1 "$out/bin/omp" -e \
'if (Bun.version !== "${bun.version}" || typeof Bun.Image !== "function") process.exit(1)'
runHook postInstallCheck
'';
echo "Compiling OMP"
BUN_COMPILE_EXECUTABLE_PATH="${bunRuntimeTemplate}/libexec/bun" \
bun --cwd="$PWD/packages/coding-agent" run build
runHook postBuild
'';
installPhase = ''
runHook preInstall
install -Dm755 packages/coding-agent/dist/omp "$out/libexec/omp/omp"
${lib.optionalString stdenv.hostPlatform.isLinux ''
# The addon is gzip-compressed inside the compiled binary, so the Nix
# store RUNPATH autoPatchelf wrote into it is invisible to the output
# reference scanner. Record it in plain text to pin those libraries
# (pipewire, libopus, libgcc) into the runtime closure.
mkdir -p "$out/nix-support"
patchelf --print-rpath "packages/natives/native/${platform.addon}" \
> "$out/nix-support/embedded-addon-runpath"
''}
makeWrapper "$out/libexec/omp/omp" "$out/bin/omp" \
--set PI_SKIP_VERSION_CHECK 1
runHook postInstall
'';
doInstallCheck = true;
installCheckPhase = ''
runHook preInstallCheck
HOME="$TMPDIR" "$out/bin/omp" --smoke-test | grep -q "smoke-test: ok"
BUN_BE_BUN=1 "$out/libexec/omp/omp" -e \
'if (Bun.version !== "${bun.version}" || typeof Bun.Image !== "function") process.exit(1)'
runHook postInstallCheck
'';
meta = {
description = "Terminal-based coding agent with multi-model support";
homepage = "https://omp.sh";
changelog = "https://github.com/can1357/oh-my-pi/releases/tag/v${packageJson.version}";
license = lib.licenses.mit;
mainProgram = "omp";
platforms = [
"aarch64-darwin"
"aarch64-linux"
"x86_64-darwin"
"x86_64-linux"
];
sourceProvenance = with lib.sourceTypes; [
binaryNativeCode
fromSource
];
};
}
// lib.optionalAttrs stdenv.hostPlatform.isDarwin {
# The compile output is intentionally unsigned until all Darwin fixups are complete.
darwinDontCodeSign = false;
}
)
meta = {
description = "Terminal-based coding agent with multi-model support";
homepage = "https://omp.sh";
changelog = "https://github.com/can1357/oh-my-pi/releases/tag/v${packageJson.version}";
license = lib.licenses.mit;
mainProgram = "omp";
platforms = [
"aarch64-darwin"
"aarch64-linux"
"x86_64-darwin"
"x86_64-linux"
];
sourceProvenance = with lib.sourceTypes; [
binaryNativeCode
fromSource
];
};
}