nandi/jolt-nativepublic Fork 0
12754c296522cfbc554e0742cc14896b4fb3905b
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

flake.nix · 498 lines · 22.1 KBNix Blame HistoryRaw
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago1# The whole toolchain, as one closure.
2#
3# This replaces buck2 and DotSlash together, and for the same reason each of
4# them was here: a checkout should build on a machine with nothing installed.
5# DotSlash pinned five tools by digest and fetched them on first use; buck2 knew
6# how to run them. Nix pins the compiler, the C toolchain, the system libraries
7# *and* the crate graph in one lockfile, so the pinning and the running stop
8# being two problems.
9#
10# nix develop # the edit loop: cargo, just, everything below
11# nix build # all three desktop objects into result/lib
12# nix build .#android # the two device objects, cross-compiled
13# nix flake check # fmt, clippy, tests
14#
Publish the shared objects instead of dropping them b6001e6 nandi 11d ago15# Every push to main publishes the same two outputs to the GitLab package
16# registry as tarballs rooted at lib/ and include/, so another flake can link
17# against them without building this one:
18#
19# inputs.jolt-native-libs = {
20# url = "https://gitlab.example/api/v4/projects/<id>/packages/generic/jolt-native/<sha>/android-arm64-v8a.tar.gz";
21# flake = false; # a plain tarball, not a flake — nix unpacks it as-is
22# };
23# # then: ${jolt-native-libs}/lib/arm64-v8a/libjoltmoq.so
24#
25# The URL carries a commit sha and flake.lock pins the unpacked tree's narHash,
26# so the input is immutable from both ends; moving it is an edit plus a lock
27# update. There is deliberately no `latest` URL — a moving target under a
The window nobody could unpack 121e5f1 nandi 20h ago28# pinned hash is a lockfile that lies. The desktop tarballs are published the
29# same way, and there are two of them because there are two kinds of consumer:
30#
31# x86_64-linux.tar.gz the store objects, RUNPATH into the
32# *builder's* /nix/store. They resolve only on
33# a machine holding those paths, so a nix
34# consumer should take this repo as a flake
35# input and build .#libs rather than unpack it.
36# x86_64-linux-portable.tar.gz .#libsPortable — the same objects with their
37# NEEDED closure beside them and RUNPATH
38# $ORIGIN. Unpack it anywhere, point
39# LD_LIBRARY_PATH at its lib/, and dlopen
40# works with no nix on the machine. The GL
41# driver is deliberately NOT in it: that one
42# has to be the host's.
Publish the shared objects instead of dropping them b6001e6 nandi 11d ago43#
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago44# What went away with buck2: third-party/rust's reindeer-generated BUCK graph
45# (Cargo.lock is the one dependency graph now), the RBE container and its GitLab
46# job, and scripts/ entire — zcc, zxx, zig-include, the .dotslash manifests and
47# the generator that restated them for buck. The zig sysroot in particular was
48# only ever standing in for a system C toolchain; nix supplies a real one, which
49# is also why cpal's `pipewire` feature no longer has to be off.
50{
51 description = "jolt's native backends glimmer/egui, a terminal painter, and a MoQ media plane, each behind a C ABI";
52
53 inputs = {
54 nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
55 rust-overlay = {
56 url = "github:oxalica/rust-overlay";
57 inputs.nixpkgs.follows = "nixpkgs";
58 };
59 crane.url = "github:ipetkov/crane";
60 flake-utils.url = "github:numtide/flake-utils";
61 };
62
63 outputs = { self, nixpkgs, rust-overlay, crane, flake-utils }:
64 flake-utils.lib.eachDefaultSystem (system:
65 let
66 pkgs = import nixpkgs {
67 inherit system;
68 overlays = [ (import rust-overlay) ];
69 # The NDK is unfree, and only the android outputs pull it in.
70 config.allowUnfree = true;
71 config.android_sdk.accept_license = true;
72 };
73
74 inherit (pkgs) lib;
75
76 # One toolchain for both directions. The Android std comes from the same
77 # rustc rather than a second pinned tarball, which is what
78 # scripts/rust-std-android.dotslash and the sysroot symlink farm in
79 # scripts/rustc existed to stitch together by hand.
80 rustToolchain = pkgs.rust-bin.stable.latest.default.override {
81 extensions = [ "rust-src" "clippy" "rustfmt" ];
82 targets = [ "aarch64-linux-android" ];
83 };
84
85 craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
86
87 # crane's own cleanCargoSource keeps .rs and the manifests and drops
88 # everything else — which here would drop the C headers each crate
89 # publishes and vidya-core's font and emoji assets, all of which are
90 # `include_bytes!`d or shipped beside the object. Keep them.
91 src = lib.cleanSourceWith {
92 src = ./.;
93 name = "jolt-native-source";
94 filter = path: type:
95 let rel = lib.removePrefix (toString ./. + "/") (toString path);
96 in
97 (craneLib.filterCargoSources path type)
98 || lib.hasInfix "/include/" rel
Move iroh-live forward and let the vendored cpal go 789bb13 nandi 12d ago99 || lib.hasInfix "/assets/" rel;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago100 };
101
102 # Built by a build script, linked into the objects, or opened by them at
103 # run time. Split out because the Android graph wants almost none of it.
104 desktopBuildInputs = with pkgs; [
105 alsa-lib # cpal's ALSA host
106 pipewire # cpal's `pipewire` feature, via libspa-sys
107 libGL # glow/glutin
108 libxkbcommon # winit
109 wayland
110 libx11
111 libxcursor
112 libxi
113 libxrandr
114 ];
115
116 nativeBuildInputs = with pkgs; [
117 pkg-config
118 # aws-lc-sys (under rustls and moq-native) configures with cmake and
119 # generates its assembly with perl and go.
120 cmake
121 ninja
122 perl
123 go
124 # Sets LIBCLANG_PATH and the clang resource-dir include for every
125 # bindgen build script in the graph — v4l2r, libspa-sys, aws-lc-sys.
126 rustPlatform.bindgenHook
127 ];
128
129 # v4l2r's build script wants linux/videodev2.h. On a machine with kernel
130 # headers installed that is /usr/include; on one without it is nowhere,
131 # which is the whole reason the justfile used to reach into zig's
132 # bundled copies. nixpkgs has them as a package.
133 v4l2Env = {
134 V4L2R_VIDEODEV2_H_PATH = "${pkgs.linuxHeaders}/include";
135 BINDGEN_EXTRA_CLANG_ARGS = "-I${pkgs.linuxHeaders}/include";
136 };
137
138 commonArgs = {
139 inherit src;
140 strictDeps = true;
141 inherit nativeBuildInputs;
142 buildInputs = desktopBuildInputs;
143 } // v4l2Env;
144
Build each object's dependencies, not every object's 2975a43 nandi 9d ago145 # Every external crate, compiled once and shared by the objects that
146 # actually want it.
147 #
148 # This used to be ONE derivation for the whole workspace, and the
149 # sharing was the point: three objects, one dependency build. What it
150 # cost was invisible until a consumer wanted only some of them.
151 # jolt-moq brings moq-net, iroh, quinn, rustls and aws-lc-sys behind
152 # it -- 440 crates that nothing else here touches -- so a build of
153 # libvidya alone still paid for the media plane. A client that has
154 # stopped loading libjoltmoq paid for it too, which is the case that
155 # made this worth splitting.
156 #
157 # Split by CONSUMER rather than per package: vidya and tui share
158 # nearly everything, and giving them an artifact each would trade one
159 # kind of waste for another.
160 depsFor = { pname, packages }:
161 craneLib.buildDepsOnly (commonArgs // {
162 inherit pname;
163 version = "0.1.0";
164 cargoExtraArgs =
165 "--locked " + lib.concatMapStringsSep " " (p: "-p " + p) packages;
166 });
167
168 uiArtifacts = depsFor {
169 pname = "jolt-native-ui-deps";
170 packages = [ "vidya-ffi" "jolt-tui" ];
171 };
172 moqArtifacts = depsFor {
173 pname = "jolt-native-moq-deps";
174 packages = [ "jolt-moq" ];
175 };
Build libjoltcosmic out of the flake, so frq can link it 4706c92 nandi 7d ago176 # Its own artifact rather than a share of the UI one, for the reason
177 # crates/jolt-cosmic/Cargo.toml gives: libcosmic drags iced, wgpu,
178 # cosmic-text and zbus in behind it, and none of that belongs in the
179 # dependency build a terminal backend waits on.
180 cosmicArtifacts = depsFor {
181 pname = "jolt-native-cosmic-deps";
182 packages = [ "jolt-cosmic" ];
183 };
Build each object's dependencies, not every object's 2975a43 nandi 9d ago184
185 # The whole workspace, for the clippy and test runs — those do build
186 # everything, and want the sharing this split gives up.
Move iroh-live forward and let the vendored cpal go 789bb13 nandi 12d ago187 cargoArtifacts = craneLib.buildDepsOnly (commonArgs // {
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago188 pname = "jolt-native-deps";
189 version = "0.1.0";
190 });
191
192 # cargo does not install a cdylib, so crane's default install phase —
193 # `cargo install`, which only knows about binaries — has nothing to do.
194 # Take the objects out of the target directory instead.
Run the formatter over the tree 3e8c6f0 nandi 13d ago195 # `dir` is named separately because a crate's directory and its cargo
196 # package name are not the same thing here: vidya-ffi lives in
197 # crates/jolt-vidya. Nothing is silenced — a header that stops being
198 # there should fail the build rather than ship an object with no ABI
199 # beside it.
Build libjoltcosmic out of the flake, so frq can link it 4706c92 nandi 7d ago200 # `headers` is false for a backend that exports no C API of its own.
201 # jolt-cosmic is one: the jolt side reaches it through jolt.ffi by
202 # symbol name, so there is no header for an embedder to include and no
203 # crates/jolt-cosmic/include to copy. The others keep the check that
204 # a vanished header fails the build.
205 soPackage = { pname, package, dir, soname, artifacts, headers ? true }:
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago206 craneLib.buildPackage (commonArgs // {
Build each object's dependencies, not every object's 2975a43 nandi 9d ago207 inherit pname;
208 cargoArtifacts = artifacts;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago209 version = "0.1.0";
210 cargoExtraArgs = "--locked -p ${package}";
211 doCheck = false;
212 installPhaseCommand = ''
Build libjoltcosmic out of the flake, so frq can link it 4706c92 nandi 7d ago213 mkdir -p $out/lib
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago214 cp target/release/${soname} $out/lib/
Build libjoltcosmic out of the flake, so frq can link it 4706c92 nandi 7d ago215 '' + lib.optionalString headers ''
216 mkdir -p $out/include
Run the formatter over the tree 3e8c6f0 nandi 13d ago217 cp -r crates/${dir}/include/. $out/include/
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago218 '';
219 });
220
221 libvidya = soPackage {
Build each object's dependencies, not every object's 2975a43 nandi 9d ago222 artifacts = uiArtifacts;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago223 pname = "libvidya";
224 package = "vidya-ffi";
Run the formatter over the tree 3e8c6f0 nandi 13d ago225 dir = "jolt-vidya";
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago226 soname = "libvidya.so";
227 };
228 libjolttui = soPackage {
Build each object's dependencies, not every object's 2975a43 nandi 9d ago229 artifacts = uiArtifacts;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago230 pname = "libjolttui";
231 package = "jolt-tui";
Run the formatter over the tree 3e8c6f0 nandi 13d ago232 dir = "jolt-tui";
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago233 soname = "libjolttui.so";
234 };
235 libjoltmoq = soPackage {
Build each object's dependencies, not every object's 2975a43 nandi 9d ago236 artifacts = moqArtifacts;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago237 pname = "libjoltmoq";
238 package = "jolt-moq";
Run the formatter over the tree 3e8c6f0 nandi 13d ago239 dir = "jolt-moq";
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago240 soname = "libjoltmoq.so";
241 };
Build libjoltcosmic out of the flake, so frq can link it 4706c92 nandi 7d ago242 libjoltcosmic = soPackage {
243 artifacts = cosmicArtifacts;
244 pname = "libjoltcosmic";
245 package = "jolt-cosmic";
246 dir = "jolt-cosmic";
247 soname = "libjoltcosmic.so";
248 headers = false;
249 };
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago250
251 # The phone. Same sources, same Cargo.lock, only the target
252 # configuration moves — which is what //:libs-android and its pair of
253 # configured_alias targets used to say. Build scripts and proc macros
254 # still compile for the host; cargo arranges that on its own.
255 androidApi = 28;
256 androidTarget = "aarch64-linux-android";
257
258 androidComposition = pkgs.androidenv.composeAndroidPackages {
259 includeNDK = true;
260 ndkVersions = [ "27.2.12479018" ];
261 platformVersions = [ "${toString androidApi}" ];
262 abiVersions = [ "arm64-v8a" ];
263 };
264 ndkRoot = "${androidComposition.androidsdk}/libexec/android-sdk/ndk-bundle";
265 ndkBin = "${ndkRoot}/toolchains/llvm/prebuilt/linux-x86_64/bin";
266
267 # The NDK's clang is the linker rustc runs and the compiler cc-rs runs.
268 # scripts/android-cc existed only because -Clinker takes a plain string
269 # and so needed something with a stable name; a nix store path is one.
270 androidCC = "${ndkBin}/clang";
271
272 androidEnv = {
273 CARGO_BUILD_TARGET = androidTarget;
274 "CC_${builtins.replaceStrings ["-"] ["_"] androidTarget}" = androidCC;
275 "CXX_${builtins.replaceStrings ["-"] ["_"] androidTarget}" = "${ndkBin}/clang++";
276 "AR_${builtins.replaceStrings ["-"] ["_"] androidTarget}" = "${ndkBin}/llvm-ar";
277 CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER = androidCC;
278 # cc-rs and clang both need the API level; rustc's target triple does
279 # not carry one, so it is passed as a flag on every C compile and on
280 # the link.
281 "CFLAGS_${builtins.replaceStrings ["-"] ["_"] androidTarget}" =
282 "--target=${androidTarget}${toString androidApi}";
283 "CXXFLAGS_${builtins.replaceStrings ["-"] ["_"] androidTarget}" =
284 "--target=${androidTarget}${toString androidApi}";
285 CARGO_TARGET_AARCH64_LINUX_ANDROID_RUSTFLAGS =
286 "-Clink-arg=--target=${androidTarget}${toString androidApi}";
287 ANDROID_NDK_HOME = ndkRoot;
288 ANDROID_NDK_ROOT = ndkRoot;
289 };
290
291 # None of the desktop libraries cross: the camera is Camera2 over JNI
292 # rather than V4L2, and the audio is cpal's AAudio host rather than
293 # PipeWire or ALSA. The bindgen hook still comes along for aws-lc-sys.
294 androidArgs = {
295 inherit src;
296 strictDeps = true;
297 nativeBuildInputs = nativeBuildInputs ++ [ androidComposition.androidsdk ];
298 buildInputs = [ ];
299 doCheck = false;
300 cargoExtraArgs = "--locked -p vidya-ffi -p jolt-moq";
301 } // androidEnv;
302
Move iroh-live forward and let the vendored cpal go 789bb13 nandi 12d ago303 androidArtifacts = craneLib.buildDepsOnly (androidArgs // {
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago304 pname = "jolt-native-android-deps";
305 version = "0.1.0";
306 });
307
308 libsAndroid = craneLib.buildPackage (androidArgs // {
309 pname = "jolt-native-android";
310 version = "0.1.0";
311 cargoArtifacts = androidArtifacts;
312 installPhaseCommand = ''
313 mkdir -p $out/lib/arm64-v8a
314 cp target/${androidTarget}/release/libvidya.so $out/lib/arm64-v8a/
315 cp target/${androidTarget}/release/libjoltmoq.so $out/lib/arm64-v8a/
Publish the shared objects instead of dropping them b6001e6 nandi 11d ago316 # Both objects NEEDED it aws-lc-sys and libspa-sys pull in the
317 # C++ runtime and the NDK ships it as a shared library that
318 # nothing else provides on the device. It has to ride along in the
319 # same directory the APK packages, or dlopen fails at run time.
320 cp ${ndkBin}/../sysroot/usr/lib/${androidTarget}/libc++_shared.so \
321 $out/lib/arm64-v8a/
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago322 '';
323 });
324
325 # The directory a consumer points LD_LIBRARY_PATH at — the same shape
326 # `just build` leaves in target/release, and the same one //:libs used
327 # to stage into build/lib.
The window nobody could unpack 121e5f1 nandi 20h ago328 #
329 # libjoltcosmic is in here now. It was left out while it was the new
330 # backend and nothing took this attribute for it, and what that cost
331 # was not local: `.#libs` is what CI stages and tars, so the window
332 # every desktop consumer actually paints with was the one object never
333 # published. frq takes libjolttui and libjoltcosmic by name out of
334 # this flake's packages; the tarball is what a consumer WITHOUT nix
335 # gets, and it had a retired backend in it instead.
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago336 libs = pkgs.symlinkJoin {
337 name = "jolt-native-libs";
The window nobody could unpack 121e5f1 nandi 20h ago338 paths = [ libvidya libjolttui libjoltmoq libjoltcosmic ];
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago339 };
The window nobody could unpack 121e5f1 nandi 20h ago340
341 # The same objects, for a machine with no /nix/store.
342 #
343 # `libs` is only usable under nix, and not by accident: crane links
344 # against the closure, so every object here NEEDs sonames that resolve
345 # through a RUNPATH naming store paths the consumer does not have.
346 # That is the right answer for a nix consumer and the whole problem
347 # for anyone else — a tarball of `libs` unpacked on Debian is a set of
348 # objects dlopen fails on, which is what the x86_64-linux tarball has
349 # quietly been.
350 #
351 # So: copy each object, walk its NEEDED closure, bring along every
352 # library that closure names, and set RUNPATH to $ORIGIN so the copies
353 # find each other wherever the tarball lands.
354 #
355 # Two kinds of library are deliberately NOT brought along, and the
356 # distinction is what keeps this honest rather than a second AppImage:
357 #
358 # the driver stack — libGL, libEGL, libvulkan, libdrm, libgbm — which
359 # must be the HOST's or the window does not open. This is the thing
360 # nixGL exists to paper over, and the reason it exists is that a nix
361 # closure carries its own Mesa. Not carrying one means not needing a
362 # nixGL. Nothing here NEEDs them anyway: wgpu and glutin open the
363 # driver with dlopen at run time, which is exactly the seam that lets
364 # the host's win.
365 #
366 # glibc and the loader, which are the host's for the usual reason:
367 # a newer ld.so can load an older program's libraries and not the
368 # reverse, so bundling ours would set the floor at nixpkgs' glibc
369 # rather than at the oldest thing we actually build against.
370 #
371 # libstdc++ IS bundled: it is the other way round — the C++ runtime
372 # nixpkgs links against is routinely newer than a stable distro's, and
373 # a missing GLIBCXX_3.4.3x is the failure this avoids.
374 portableDenyList = [
375 "libGL" "libEGL" "libGLX" "libGLdispatch" "libOpenGL"
376 "libvulkan" "libdrm" "libgbm"
377 "libc" "libm" "libdl" "libpthread" "librt" "libresolv" "libutil"
378 "ld-linux-x86-64" "ld-linux-aarch64"
379 ];
380
381 libsPortable = pkgs.runCommand "jolt-native-libs-portable"
382 {
383 nativeBuildInputs = [ pkgs.patchelf ];
384 # The fallback search path. The real one is each file's OWN
385 # RUNPATH, read below: crane records the closure the linker used,
386 # which is complete, where a path built from the flake's inputs is
387 # only the direct ones — it has libxcb because libxcb is a
388 # buildInput, and not libXau, which is libxcb's.
389 searchPath = lib.makeLibraryPath
390 ([ libvidya libjolttui libjoltmoq libjoltcosmic ]
391 ++ desktopBuildInputs
392 ++ [ pkgs.stdenv.cc.cc.lib ]);
393 deny = lib.concatStringsSep " " portableDenyList;
394 }
395 ''
396 set -eu
397 mkdir -p "$out/lib" "$out/include"
398 cp -r ${libs}/include/. "$out/include/"
399 for so in ${libs}/lib/*.so; do
400 install -m 0755 "$so" "$out/lib/"
401 done
402
403 denied() {
404 # Match on the soname up to the first ".so", so libGL.so.1 and
405 # libGL.so are the same answer.
406 stem=''${1%%.so*}
407 for d in $deny; do [ "$stem" = "$d" ] && return 0; done
408 return 1
409 }
410
411 # Breadth-first over NEEDED, because a bundled library has NEEDED
412 # entries of its own libspa pulls the C++ runtime in, and a pass
413 # that only looked at our four objects would leave it out.
414 pending=$(ls "$out/lib")
415 while [ -n "$pending" ]; do
416 next=""
417 for f in $pending; do
418 for need in $(patchelf --print-needed "$out/lib/$f"); do
419 [ -e "$out/lib/$need" ] && continue
420 denied "$need" && continue
421 found=""
422 # The file's own RUNPATH first: it is the closure this
423 # object was linked against, so the answer is in it unless
424 # the library is dlopened rather than NEEDED.
425 IFS=: read -ra dirs <<< "$(patchelf --print-rpath "$out/lib/$f"):$searchPath"
426 for d in "''${dirs[@]}"; do
427 if [ -e "$d/$need" ]; then found="$d/$need"; break; fi
428 done
429 if [ -z "$found" ]; then
430 echo "no $need on the search path" >&2
431 exit 1
432 fi
433 install -m 0755 -T "$found" "$out/lib/$need"
434 next="$next $need"
435 done
436 done
437 pending=$next
438 done
439
440 # One RUNPATH for the lot, and $ORIGIN rather than a directory:
441 # the consumer decides where this unpacks, and only the loader
442 # knows where that turned out to be.
443 for f in "$out/lib"/*; do
444 patchelf --set-rpath '$ORIGIN' "$f"
445 done
446
447 echo "bundled:"
448 ls -la "$out/lib"
449 '';
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago450 in
451 {
452 packages = {
453 default = libs;
454 android = libsAndroid;
The window nobody could unpack 121e5f1 nandi 20h ago455 inherit libs libsPortable libvidya libjolttui libjoltmoq libjoltcosmic;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago456 };
457
Run the glimmer-gfx counter from the repo root 5416ab2 nandi 11d ago458 # Just the X11 client library on LD_LIBRARY_PATH, for `jolt gfx-demo`.
459 # The default shell would do too, but it evaluates the rust toolchain
460 # and the crane graph to hand a Clojure program one dlopen target.
461 devShells.gfx = pkgs.mkShell {
462 LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.libx11 ];
463 };
464
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago465 devShells.default = pkgs.mkShell ({
466 packages = [ rustToolchain pkgs.just pkgs.sccache pkgs.cargo-nextest ]
467 ++ nativeBuildInputs
468 ++ desktopBuildInputs;
469
470 # egui opens libGL and the Wayland/X11 client libraries with dlopen,
471 # so they have to be findable at run time and not only at link time.
472 LD_LIBRARY_PATH = lib.makeLibraryPath desktopBuildInputs;
473 } // v4l2Env);
474
475 checks = {
The window nobody could unpack 121e5f1 nandi 20h ago476 inherit libvidya libjolttui libjoltmoq libjoltcosmic;
Pin the toolchain with a flake, and let buck2 and DotSlash go 5ae197f nandi 13d ago477
478 clippy = craneLib.cargoClippy (commonArgs // {
479 inherit cargoArtifacts;
480 pname = "jolt-native-clippy";
481 cargoClippyExtraArgs = "--workspace --all-targets -- -D warnings";
482 });
483
484 fmt = craneLib.cargoFmt {
485 inherit src;
486 pname = "jolt-native-fmt";
487 };
488
489 test = craneLib.cargoTest (commonArgs // {
490 inherit cargoArtifacts;
491 pname = "jolt-native-test";
492 cargoTestExtraArgs = "--workspace";
493 });
494 };
495
496 formatter = pkgs.nixpkgs-fmt;
497 });
498}