xo-umbrella2/default.nix
2026-04-03 15:23:07 -04:00

1064 lines
38 KiB
Nix

#{ pkgs ? import <nixpkgs> { overlays = [ (final: prev: { llvmPackages = prev.llvmPackages_17; }) ]; } }:
#pkgs.mkShell {
# buildInputs = [ pkgs.coreutils ];
#}
{
# official 24.05 release # nearly works on macos, clang17, llvm18 except for sphinx-contrib.ditaa
# on roly-chicago-24: using nixos-25.05, local nixpkgs
# nixpkgs-path ? fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-24.11.tar.gz",
nixpkgs-path ? ../nixpkgs,
# pkgs ? import (fetchTarball {
# # 24.05-darwin works on macos, clang17, llvm 18 (copying from xo-nix2)
# url = "https://github.com/NixOS/nixpkgs/archive/dd868b7bd4d1407d607da0d1d9c5eca89132e2f7.tar.gz";
# }),
} :
let
# this approach (overlays) is effective, but has super wide cross-section,
# since absolutely everything has to be rebuilt from source
#
amf-headers-overlay = self: super: {
amf-headers = super.amf-headers.overrideAttrs (old: {
src = self.fetchFromGitHub {
# nixpkgs sha256 stale for version 1.4.36 asof 4sep2025
owner = "GPUOpen-LibrariesAndSDKs";
repo = "AMF";
rev = "v${old.version}";
sha256 = "sha256-0PgWEq+329/EhI0/CgPsCkJ4CiTsFe56w2O+AcjVUdc=";
#sha256 = "sha256-u6gvdc1acemd01TO5EbuF3H7HkEJX4GUx73xCo71yPY=";
};});
};
# complains about 'no more ptys'
dejagnu-overlay = self: super: {
dejagnu = super.dejagnu.overrideAttrs (old: {
doCheck = false;
});
};
swtpm-overlay = self: super: {
swtpm = super.swtpm.overrideAttrs (old: {
doCheck = false;
});
};
# libffi tests run, but only if sandbox disabled
libffi-overlay = self: super: {
libffi = super.libffi.overrideAttrs (old: {
doCheck = false;
});
};
# libqmi test seems to stall on ubuntu
libqmi-overlay = self: super: {
libqmi = super.libqmi.overrideAttrs (old: {
doCheck = false;
});
};
# ghostty tests require ptys
ghostty-overlay = self: super: {
ghostty = super.ghostty.overrideAttrs (old: {
doCheck = false;
});
};
# fish tests require ptys
fish-overlay = self: super: {
fish = super.fish.overrideAttrs (old: {
doCheck = false;
});
};
# # nixGL not present in my nixpkgs snapshot
# nixgl-overlay = self: super: {
# nixGL = import (self.fetchFromGitHub {
# owner = "nix-community";
# repo = "nixGL";
# rev = "main";
# sha256 = "sha256-Ob/HuUhANoDs+nvYqyTKrkcPXf4ZgXoqMTQoCK0RFgQ=";
# }) {pkgs = self; };
# };
# Problem: builds *everything* with llvm18 toolchain, exposes too many compiler nits
llvm-overlay = self: super:
# use 'super' when you want to override the terms of a package.
# use 'self' when pointing to an existing package
#
let
llvmPackages = super.llvmPackages_18;
in let
clangStdenv = super.overrideCC super.stdenv super.llvmPackages_18.clang;
in let
jitStdenv = if super.stdenv.isDarwin then clangStdenv else super.stdenv;
in
{ inherit llvmPackages clangStdenv jitStdenv; };
# tests excruciatingly slow
mailutils-overlay = self: super: {
mailutils = super.mailutils.overrideAttrs (old: {
doCheck = false;
});
};
# 2 tests fail with 25.05
notmuch-overlay = self: super: {
notmuch = super.notmuch.overrideAttrs (old: {
doCheck = false;
});
};
xo-overlay = self: super:
# use 'super' when you want to override the terms of a package.
# use 'self' when pointing to an existing package
let
# note:
# - problems with nix llvm build-from-source w/ gcc 13.3.
# - building outside nix following linuxfromscratch instructions, using gcc 12.3, works fine.
#
llvmXo = self.callPackage pkgs/llvm.nix {};
# Choose the LLVM version you want
llvmPackages1 = super.llvmPackages_18;
in
let
# on darwin, rebuild stdenv to use clang tied to that LLVM version.
# otherwise we get conflicts since darwin stdenv is using clang+llvm for gcc.
#
clangStdenv = super.overrideCC super.stdenv llvmPackages1.clang;
# stdenv to use for xo-jit
jitStdenv = if super.stdenv.isDarwin then clangStdenv else super.stdenv;
in
{
xo-cmake = self.callPackage pkgs/xo-cmake.nix { stdenv = jitStdenv; };
xo-indentlog = self.callPackage pkgs/xo-indentlog.nix { stdenv = jitStdenv; buildDocs = true; buildExamples = true; };
xo-reflectutil = self.callPackage pkgs/xo-reflectutil.nix { stdenv = jitStdenv; };
xo-randomgen = self.callPackage pkgs/xo-randomgen.nix { stdenv = jitStdenv; buildExamples = true; };
xo-arena = self.callPackage pkgs/xo-arena.nix { stdenv = jitStdenv; buildDocs = true; };
xo-facet = self.callPackage pkgs/xo-facet.nix { stdenv = jitStdenv; };
xo-allocutil = self.callPackage pkgs/xo-allocutil.nix { stdenv = jitStdenv; };
xo-refcnt = self.callPackage pkgs/xo-refcnt.nix { stdenv = jitStdenv; };
xo-subsys = self.callPackage pkgs/xo-subsys.nix { stdenv = jitStdenv; };
xo-flatstring = self.callPackage pkgs/xo-flatstring.nix { stdenv = jitStdenv; buildDocs = true; buildExamples = true; };
xo-pyutil = self.callPackage pkgs/xo-pyutil.nix { stdenv = jitStdenv; };
xo-reflect = self.callPackage pkgs/xo-reflect.nix { stdenv = jitStdenv; };
xo-pyreflect = self.callPackage pkgs/xo-pyreflect.nix { stdenv = jitStdenv; };
xo-ratio = self.callPackage pkgs/xo-ratio.nix { stdenv = jitStdenv; buildDocs = true; buildExamples = true; };
xo-unit = self.callPackage pkgs/xo-unit.nix { stdenv = jitStdenv; buildDocs = true; buildExamples = true; };
xo-pyunit = self.callPackage pkgs/xo-pyunit.nix { stdenv = jitStdenv; };
xo-callback = self.callPackage pkgs/xo-callback.nix { stdenv = jitStdenv; };
xo-printable2 = self.callPackage pkgs/xo-printable2.nix { stdenv = jitStdenv; };
xo-alloc = self.callPackage pkgs/xo-alloc.nix { stdenv = jitStdenv; buildDocs = true; };
xo-alloc2 = self.callPackage pkgs/xo-alloc2.nix { stdenv = jitStdenv; buildDocs = true; };
xo-stringtable2 = self.callPackage pkgs/xo-stringtable2.nix { stdenv = jitStdenv; };
xo-gc = self.callPackage pkgs/xo-gc.nix { stdenv = jitStdenv; buildDocs = true; };
xo-object = self.callPackage pkgs/xo-object.nix { stdenv = jitStdenv; };
xo-type = self.callPackage pkgs/xo-type.nix { stdenv = jitStdenv; };
xo-object2 = self.callPackage pkgs/xo-object2.nix { stdenv = jitStdenv; };
xo-procedure2 = self.callPackage pkgs/xo-procedure2.nix { stdenv = jitStdenv; };
xo-numeric = self.callPackage pkgs/xo-numeric.nix { stdenv = jitStdenv; };
xo-ordinaltree = self.callPackage pkgs/xo-ordinaltree.nix { stdenv = jitStdenv; };
xo-tokenizer2 = self.callPackage pkgs/xo-tokenizer2.nix { stdenv = jitStdenv; buildExamples = true; };
#
# xo-expression2
# xo-reader2
# xo-interpreter2
#
xo-webutil = self.callPackage pkgs/xo-webutil.nix { stdenv = jitStdenv; };
xo-pywebutil = self.callPackage pkgs/xo-pywebutil.nix {};
xo-printjson = self.callPackage pkgs/xo-printjson.nix {};
xo-pyprintjson = self.callPackage pkgs/xo-pyprintjson.nix {};
xo-reactor = self.callPackage pkgs/xo-reactor.nix {};
xo-pyreactor = self.callPackage pkgs/xo-pyreactor.nix {};
xo-websock = self.callPackage pkgs/xo-websock.nix {};
xo-pywebsock = self.callPackage pkgs/xo-pywebsock.nix {};
#
xo-statistics = self.callPackage pkgs/xo-statistics.nix {};
xo-distribution = self.callPackage pkgs/xo-distribution.nix {};
xo-pydistribution = self.callPackage pkgs/xo-pydistribution.nix {};
xo-simulator = self.callPackage pkgs/xo-simulator.nix {};
xo-pysimulator = self.callPackage pkgs/xo-pysimulator.nix {};
xo-process = self.callPackage pkgs/xo-process.nix {};
xo-pyprocess = self.callPackage pkgs/xo-pyprocess.nix {};
xo-kalmanfilter = self.callPackage pkgs/xo-kalmanfilter.nix {};
xo-pykalmanfilter = self.callPackage pkgs/xo-pykalmanfilter.nix {};
#
xo-expression = self.callPackage pkgs/xo-expression.nix { buildExamples = true; };
xo-pyexpression = self.callPackage pkgs/xo-pyexpression.nix {};
xo-tokenizer = self.callPackage pkgs/xo-tokenizer.nix { buildDocs = true; buildExamples = true; };
xo-reader = self.callPackage pkgs/xo-reader.nix { buildDocs = true; buildExamples = true; };
xo-jit = self.callPackage pkgs/xo-jit.nix { buildDocs = true; buildExamples = true;
#stdenv = jitStdenv;
#clang = llvmPackages2.clang;
llvm = llvmPackages1.llvm; };
xo-pyjit = self.callPackage pkgs/xo-pyjit.nix {};
#
xo-userenv = self.callPackage pkgs/xo-userenv.nix {};
xo-userenv-slow = self.callPackage pkgs/xo-userenv-slow.nix { stdenv = jitStdenv;
#clang = llvmPackages.clang;
llvm = llvmPackages1.llvm;
};
# xo-packaged version of llvm; fewer packaging features than nixpkgs
# but easier to debug/modify
llvmXo = llvmXo;
};
in
let
pkgs = import nixpkgs-path {
overlays = [
#qrencode-overlay # not needed 4sep2025 nixpkgs (? might have src in nix store)
#libconfig-overlay # not needed 4sep2025 nixpkgs (? might have src in nix store)
#pipewire-overlay # not needed 4sep2025 nixpkgs ?
#ccache-overlay # not needed 4sep2025 nixpkgs
amf-headers-overlay
dejagnu-overlay
libffi-overlay
libqmi-overlay
swtpm-overlay
mailutils-overlay
notmuch-overlay
ghostty-overlay
fish-overlay
# nixgl-overlay
# llvm-overlay
xo-overlay
];
};
in
let
xo_topdir = toString ./.;
fonts = pkgs.makeFontsConf {
fontDirectories = [
pkgs.inconsolata-lgc
pkgs.noto-fonts
pkgs.noto-fonts-emoji
pkgs.dejavu_fonts
];
};
# xo deps
xodeps = [
pkgs.python3Packages.python
# note: pybind11 won't build on roly-chicago-24a in nix sandbox, runs out of pty devices
#
pkgs.python3Packages.pybind11
pkgs.python3Packages.json5
pkgs.python3Packages.jinja2
pkgs.llvmPackages_18.llvm.dev
pkgs.replxx
pkgs.libwebsockets
pkgs.jsoncpp
pkgs.eigen
pkgs.zlib
pkgs.libbsd
];
# emacs
emacs4xo = (pkgs.emacsPackagesFor pkgs.emacs30).emacsWithPackages (epkgs: with epkgs; [
lsp-mode
lsp-ui
lsp-ivy
flycheck
ivy
rg
transient # magit dep
nix-mode
yaml-mode
htmlize
magit
exec-path-from-shell
highlight
surround
projectile
treemacs
treemacs-projectile
company
cmake-mode
which-key
xterm-color
yasnippet
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
notmuch
]);
# xo ide utils
ideutils = [
pkgs.gsettings-desktop-schemas
emacs4xo
# pkgs.emacs-pgtk # wayland with treesitter; alternatively pkgs.emacs30 for emacs+tree-sitter
pkgs.tree-sitter # CLI tool, but not grammars
pkgs.llvmPackages_18.clang-tools # clangd for lsp-mode
pkgs.notmuch
pkgs.emacsPackages.notmuch
pkgs.inconsolata-lgc
pkgs.fontconfig
]
++ (if pkgs.stdenv.isLinux then [
pkgs.ghostty
] else [])
++ [
pkgs.timg
pkgs.fish
pkgs.nushell
];
# xo general-purpose devutils
devutils = [
pkgs.nix-tree # note: needs GHC
pkgs.git
pkgs.gh # github cli
pkgs.cloc
pkgs.bloaty
pkgs.lcov
pkgs.catch2
pkgs.btop
]
++ (if pkgs.stdenv.isLinux then [
pkgs.gdb
pkgs.strace
] else [
pkgs.llvmPackages_18.lldb
])
++ [
pkgs.which
pkgs.man
pkgs.man-pages
pkgs.less
pkgs.ripgrep
pkgs.openssh
pkgs.ccache
]
++ (if pkgs.stdenv.isLinux then [
pkgs.distcc
] else [])
++ [
pkgs.cmake
pkgs.pkg-config
pkgs.unzip
];
# xo docutils
docutils =
pkgs.lib.optionals pkgs.stdenv.isLinux [
pkgs.python3Packages.sphinxcontrib-ditaa
] ++
[
pkgs.python3Packages.python
pkgs.python3Packages.pillow
pkgs.python3Packages.breathe
#pkgs.python3Packages.sphinx-autobuild # needs patch for typeguard; defer for now
pkgs.python3Packages.sphinx-rtd-theme
pkgs.python3Packages.sphinxcontrib-plantuml
pkgs.doxygen
pkgs.graphviz
pkgs.ditaa
pkgs.sphinx
];
# xo x11utils
x11utils =
[
pkgs.xorg.xcbutil
pkgs.xorg.xcbutilwm # xcb window manager utilities
pkgs.xorg.xcbutilimage
pkgs.xorg.xclock
pkgs.xorg.xdpyinfo
];
# xo opengl utils
gldeps =
[
# glew: used for opengl apps; not needed for vulkan apps (even when those apps use opengl)
pkgs.glew
] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
pkgs.mesa-demos
] ++ [
pkgs.libGL
];
vkdeps =
pkgs.lib.optionals pkgs.stdenv.isDarwin [
pkgs.darwin.moltenvk
] ++
[ pkgs.vulkan-tools
pkgs.vulkan-loader
pkgs.vulkan-headers
pkgs.vulkan-validation-layers
];
imguideps =
[
# pkgs.imgui # incorporated directly into xo dev tree, see xo-imgui/include/imgui
pkgs.SDL2.dev
pkgs.xorg.libX11.dev # e.g. for X11/Xlib.h; needed by SDL2
pkgs.dejavu_fonts # also must set DEJAVU_FONTS_PATH for imgui_ex2
];
shell4-assembly =
{ ld-library-path-before,
vk-icd-filenames,
shell-hook-text-after,
} :
pkgs.mkShell {
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils ++ x11utils ++ gldeps ++ vkdeps ++ imguideps;
shellHook =
let
# dependencies of host system libraries
# (e.g. from /usr/lib/x86_64-linux-gnu) that we want to satisfy from nix;
# sufficient for glxgears
#
# be careful here: easy to insert something that breaks xo cmake build
#
# with minimal list
# (libXau, libXdmcp, libX11, libXext, libXfixes, libXxf86vm, libxml2, libffi,
# elfutils, ncurses, expat, zstd, zlib, libbsd, gcc.cc.lib)
# glxgears runs at ~170fps
#
glpath = pkgs.lib.makeLibraryPath ([
pkgs.wayland # for libwayland-client.so
pkgs.xorg.libXau
pkgs.xorg.libXdmcp
pkgs.xorg.libX11 # e.g. for libX11-xcb.so
pkgs.xorg.libXext
pkgs.xorg.libXfixes
pkgs.xorg.libXxf86vm
pkgs.xorg.libxcb
pkgs.libxml2
pkgs.libffi
] ++ (if pkgs.stdenv.isLinux then [ pkgs.elfutils ] else [])
++ [
pkgs.ncurses # for libtinfo.so
pkgs.expat
pkgs.zstd
pkgs.zlib # for libz.so
pkgs.libbsd
pkgs.gcc.cc.lib # for libstdc++.so (won't blow up cmake, only touching LD_LIBRARY_PATH)
]);
in
''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo4
# override SOURCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
# fonts
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
export DEJAVU_FONTS_PATH=${pkgs.dejavu_fonts}/share/fonts
${pkgs.fontconfig}/bin/fc-cache -f
# nix-provided GPU libraries only work out-of-the-box on nixos.
# For non-nixos build, need to use host-provided versions of these libraries.
# Complications:
# 1. host location is likely something like /usr/lib/x86_64-linux-gnu,
# in which case interposing that directly will change link behavior for unrelated shared libraries
# (e.g. risk getting stale non-nix libc.so etc). Use a curated symlink directory to finesse.
# 2. host-installed libraries may not set RUNPATH (they don't need to if installed in system-wide default location).
# We need to also add nix-store LD_LIBRARY_PATH entries for indirect dependencies of system-provided libraries.
#
export LD_LIBRARY_PATH=${ld-library-path-before}:${glpath}:$LD_LIBRARY_PATH
export VK_ICD_FILENAMES="${vk-icd-filenames}"
# need this on OSX, + claude wants it for both wsl2, ubuntu
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
# hardware acceleration
export LIBGL_ALWAYS_SOFTWARE=0
export MESA_LOADER_DRIVER_OVERRIDE=""
echo "tree_sitter=${pkgs.tree-sitter}"
tree_sitter=${pkgs.tree-sitter}
echo "nix_mesa=${pkgs.mesa}"
nix_mesa=${pkgs.mesa}
${shell-hook-text-after}
'';
};
in
{
pkgs = pkgs;
xo = {
cmake = pkgs.xo-cmake;
indentlog = pkgs.xo-indentlog;
reflectutil = pkgs.xo-reflectutil;
randomgen = pkgs.xo-randomgen;
arena = pkgs.xo-arena;
facet = pkgs.xo-facet;
allocutil = pkgs.xo-allocutil;
refcnt = pkgs.xo-refcnt;
subsys = pkgs.xo-subsys;
flatstring = pkgs.xo-flatstring;
pyutil = pkgs.xo-pyutil;
reflect = pkgs.xo-reflect;
pyreflect = pkgs.xo-pyreflect;
ratio = pkgs.xo-ratio;
unit = pkgs.xo-unit;
pyunit = pkgs.xo-pyunit;
callback = pkgs.xo-callback;
printable2 = pkgs.xo-printable2;
alloc = pkgs.xo-alloc;
alloc2 = pkgs.xo-alloc2;
stringtable2 = pkgs.xo-stringtable2;
gc = pkgs.xo-gc;
object = pkgs.xo-object;
type = pkgs.xo-type;
object2 = pkgs.xo-object2;
procedure2 = pkgs.xo-procedure2;
numeric = pkgs.xo-numeric;
ordinaltree = pkgs.xo-ordinaltree;
tokenizer2 = pkgs.xo-tokenizer2;
webutil = pkgs.xo-webutil;
pywebutil = pkgs.xo-pywebutil;
printjson = pkgs.xo-printjson;
pyprintjson = pkgs.xo-pyprintjson;
reactor = pkgs.xo-reactor;
pyreactor = pkgs.xo-pyreactor;
websock = pkgs.xo-websock;
pywebsock = pkgs.xo-pywebsock;
statistics = pkgs.xo-statistics;
distribution = pkgs.xo-distribution;
pydistribution = pkgs.xo-pydistribution;
simulator = pkgs.xo-simulator;
pysimulator = pkgs.xo-pysimulator;
process = pkgs.xo-process;
pyprocess = pkgs.xo-pyprocess;
kalmanfilter = pkgs.xo-kalmanfilter;
pykalmanfilter = pkgs.xo-pykalmanfilter;
expression = pkgs.xo-expression;
pyexpression = pkgs.xo-pyexpression;
tokenizer = pkgs.xo-tokenizer;
reader = pkgs.xo-reader;
jit = pkgs.xo-jit;
pyjit = pkgs.xo-pyjit;
};
# works, but only if build with --option sandbox=false
# to workaround pcre broken. overlay above does work,
# but is not applied to stdenv devs
#
shellpre = pkgs.mkShell {
buildInputs = [
# NOTE: pkgs.pcre2, pkgs.dejagnu, pkgs.libffi
# also won't build in genuine sandbox
pkgs.nix-tree # needs GHC btw
pkgs.git
pkgs.openssh
pkgs.cloc
pkgs.lcov
pkgs.gdb
pkgs.strace
pkgs.ripgrep
pkgs.clang # 19.1.7
pkgs.ninja # will this work? tbd
pkgs.cmake
pkgs.distcc
pkgs.pkg-config
pkgs.unzip
];
# includes stdenv, so will have gcc,gawk,tar,gzip etc.
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xopre
# override SOURCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
'';
};
# minimal shell - just enough to verify gcc works.
# not sufficient to build xo
#
# $ nix-shell -A shell0 # requires nixpkgs.runCommand
#
shell0 = pkgs.mkShell {
buildInputs = devutils;
# includes stdenv, so will have gcc,gawk,tar,gzip etc
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo0
# override SOURCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
'';
};
# stable shell. can build xo without docs
#
shell1a = pkgs.mkShell {
buildInputs = xodeps ++ devutils;
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo1a
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
'';
};
# minimal shell, intended to be stable
shell1 = pkgs.mkShell {
buildInputs = docutils ++ xodeps ++ devutils;
# includes stdenv, so will have gcc,gawk,tar,gzip etc
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo1
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
'';
};
# minimal shell + ide stuff, intended to be stable
shell2 = pkgs.mkShell {
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils;
# includes stdenv, so will have gcc,gawk,tar,gzip etc
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo2
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
${pkgs.fontconfig}/bin/fc-cache -f
'';
};
# xo shell with opengl support
shell3 = pkgs.mkShell {
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils ++ x11utils ++ gldeps ++ vkdeps ++ imguideps;
shellHook =
let
# dependencies of host system libraries
# (e.g. from /usr/lib/x86_64-linux-gnu) that we want to satisfy from nix;
# sufficient for glxgears
#
# be careful here: easy to insert something that breaks xo cmake build
#
# with minimal list
# (libXau, libXdmcp, libX11, libXext, libXfixes, libXxf86vm, libxml2, libffi,
# elfutils, ncurses, expat, zstd, zlib, libbsd, gcc.cc.lib)
# glxgears runs at ~170fps
#
glpath = pkgs.lib.makeLibraryPath ([
pkgs.wayland # for libwayland-client.so
pkgs.xorg.libXau
pkgs.xorg.libXdmcp
pkgs.xorg.libX11 # e.g. for libX11-xcb.so
pkgs.xorg.libXext
pkgs.xorg.libXfixes
pkgs.xorg.libXxf86vm
pkgs.libxml2
pkgs.libffi
] ++ (if pkgs.stdenv.isLinux then [ pkgs.elfutils ] else [])
++ [
pkgs.ncurses # for libtinfo.so
pkgs.expat
pkgs.zstd
pkgs.zlib # for libz.so
pkgs.libbsd
pkgs.gcc.cc.lib # for libstdc++.so (won't blow up cmake, only touching LD_LIBRARY_PATH)
]);
in
''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo3
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
# fonts
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
${pkgs.fontconfig}/bin/fc-cache -f
# nix-provided GPU libraries only work out-of-the-box on nixos.
# For non-nixos build, need to use host-provided versions of these libraries.
# Complications:
# 1. host location is likely something like /usr/lib/x86_64-linux-gnu,
# in which case interposing that directly will change link behavior for unrelated shared libraries
# (e.g. risk getting stale non-nix libc.so etc). Use a curated symlink directory to finesse.
# 2. host-installed libraries may not set RUNPATH (they don't need to if installed in system-wide default location).
# We need to also add nix-store LD_LIBRARY_PATH entries for indirect dependencies of system-provided libraries.
#
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:${xo_topdir}/etc/hostwsl:${glpath}:$LD_LIBRARY_PATH
# for vulkan on wsl, need to use llvm pipe rendering.
# (asof sep 2025 hardware rendering is supported, but with compute-only in mind i.e. for cuda)
# export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json
export VK_ICD_FILENAMES="${pkgs.mesa}/share/vulkan/icd.d/dzn_icd.x86_64.json"
# need this on OSX, + claude wants it for wsl2. but looks sketchy to me
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
# hardware acceleration
export LIBGL_ALWAYS_SOFTWARE=0
export MESA_LOADER_DRIVER_OVERRIDE=""
# wsl2-specific gpu setup
export MESA_D3D12_DEFAULT_ADAPTER_NAME=DX
echo "using d3d12 vulkan driver: $VK_ICD_FILENAMES"
'';
# TODO: consider a nix project to generate this directory. nixwsl
};
# vkcube works here
shell4-wsl = shell4-assembly {
ld-library-path-before = "${pkgs.mesa}/lib:/usr/lib/wsl/lib:${xo_topdir}/etc/hostwsl2";
vk-icd-filenames = "${pkgs.mesa}/share/vulkan/icd.d/dzn_icd.x86_64.json";
shell-hook-text-after = ''
export MESA_D3D12_DEFAULT_ADAPTER_NAME=DX
echo "using d3d12 vulkan driver: $VK_ICD_FILENAMES"
'';
};
# nov 2025 - try to get xo-imgui working on native ubuntu
shell4-nvidia = shell4-assembly {
ld-library-path-before = "${xo_topdir}/etc/hostubuntu:${pkgs.mesa}/lib";
vk-icd-filenames = "/usr/share/vulkan/icd.d/nvidia_icd.json";
shell-hook-text-after = ''
export __GLX_VENDOR_LIBRARY_NAME=nvidia
#export __EGL_VENDOR_LIBRARY_DIRS=/usr/share/glvnd/egl_vendor.d # maybe
echo "using nvidia for libglvnd"
'';
};
# nov 2025 - try to get xo-imgui working on osx again
# WIP ! plan:
# 1 - get this to work as standalone copy of shell4-assembly
# 2 - merge to look like shell4-wsl / shell4-nvidia
#
#shell4-osx = pkgs.mkShell.override { stdenv = pkgs.jitStdenv; } { .. } # very high attack surface area
shell4-osx =
let
clangStdenv = pkgs.overrideCC pkgs.stdenv pkgs.llvmPackages_18.clang;
in
let jitStdenv = if pkgs.stdenv.isDarwin then clangStdenv else pkgs.stdenv;
in
(pkgs.mkShell.override { stdenv = jitStdenv; })
{
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils ++ x11utils ++ gldeps ++ vkdeps ++ imguideps;
shellHook =
''
export CXENV=$CXENV:xo4-WIP
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
# fonts
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
export DEJAVU_FONTS_PATH=${pkgs.dejavu_fonts}/share/fonts
${pkgs.fontconfig}/bin/fc-cache -f
# would set vk-icd-filename to this + call shell4-assembly
export VK_ICD_FILENAMES=${pkgs.darwin.moltenvk}/share/vulkan/icd.d/MoltenVK_icd.json
# already baked in to shell4-assembly
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
# dependencies on host system libraries
# glpath = pkgs.lib.makeLibraryPath [ ];
# debugserver interacts with a local process to debug it.
# requires code signing, so nix can't replicate it.
export LLDB_DEBUGSERVER_PATH=/Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/debugserver
# choose a temp directory that can outlive nix-shell
export TMPDIR=$(getconf DARWIN_USER_TEMP_DIR)
export TMP=$TMPDIR
'';
};
# like shell4 but drop etc/hostwsl2 symlink dir.
# looks like nixpkgs mesa not built for wsl2 dxg
# works with opengl (llvmpipe) and vulkan
#
shell5 = pkgs.mkShell {
buildInputs = docutils ++ xodeps ++ devutils ++ ideutils ++ x11utils ++ gldeps ++ vkdeps ++ imguideps ++ imguideps;
shellHook =
let
# dependencies of host system libraries
# (e.g. from /usr/lib/x86_64-linux-gnu) that we want to satisfy from nix;
# sufficient for glxgears
#
# be careful here: easy to insert something that breaks xo cmake build
#
# with minimal list
# (libXau, libXdmcp, libX11, libXext, libXfixes, libXxf86vm, libxml2, libffi,
# elfutils, ncurses, expat, zstd, zlib, libbsd, gcc.cc.lib)
# glxgears runs at ~170fps
#
glpath = pkgs.lib.makeLibraryPath [
pkgs.wayland # for libwayland-client.so
pkgs.mesa
pkgs.xorg.libXau
pkgs.xorg.libXdmcp
pkgs.xorg.libX11 # e.g. for libX11-xcb.so
pkgs.xorg.libXext
pkgs.xorg.libXfixes
pkgs.xorg.libXxf86vm
pkgs.xorg.libxcb
pkgs.libxml2
pkgs.libffi
pkgs.elfutils # for libelf.so
pkgs.ncurses # for libtinfo.so
pkgs.expat
pkgs.zstd
pkgs.zlib # for libz.so
pkgs.libbsd
pkgs.gcc.cc.lib # for libstdc++.so (won't blow up cmake, only touching LD_LIBRARY_PATH)
];
in
''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo5
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
# fonts
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
export DEJAVU_FONTS_PATH=${pkgs.dejavu_fonts}/share/fonts
${pkgs.fontconfig}/bin/fc-cache -f
# works but only get glx using llvmpipe.
# vkcube uses dzn (see VK_ICD_FILENAMES) however!
export LD_LIBRARY_PATH=/usr/lib/wsl/lib:${glpath}:$LD_LIBRARY_PATH
# need this on OSX, + claude wants it for wsl2. but looks sketchy to me
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
export VK_ICD_FILENAMES="${pkgs.mesa}/share/vulkan/icd.d/dzn_icd.x86_64.json"
# hardware acceleration (so far ineffective w/ nixpkgs mesa)
export LIBGL_ALWAYS_SOFTWARE=0
export MESA_LOADER_DRIVER_OVERRIDE="d3d12"
# wsl2-specific gpu setup (so far ineffective w/ nixpkgs mesa)
export MESA_D3D12_DEFAULT_ADAPTER_NAME=DX
echo "using d3d12 vulkan driver: $VK_ICD_FILENAMES"
echo "nix_mesa=${pkgs.mesa}"
nix_mesa=${pkgs.mesa}
echo "nix_libgl=${pkgs.libGL}"
nix_libgl=${pkgs.libGL}
echo "nix_vk_validation: VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d"
nix_vk_validation=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
'';
# don't seem to need this -- doesn't invoke mesa hardware accel
#echo "nix_nixgl=${pkgs.nixgl.nixGLMesa}"
#nix_nixgl=${pkgs.nixgl.nixGLMesa}
};
# Old shell from failed vulkan-on-wsl attempts.
# Descends from working OSX though, so keep until we coordinate with that
#
shell = pkgs.mkShell {
# maybe should create a python environment:
# let
# pythonenv = pkgs.python3.withPackages (pset: [ pset.sphinx pset.breathe ..etc.. ])
# in
# buildInputs = [ pythonenv ..etc.. ];
#
buildInputs = [
#pkgs.nix
pkgs.nushell
]
++ docutils
++ devutils
++ xodeps
++ ideutils
++ (if pkgs.stdenv.isLinux then [ pkgs.emscripten ] else [])
++ x11utils
++ gldeps
++ imguideps
++
[
# pkgs.nixgl.auto.nixGLDefault # this + libGL + mesa-demos -> 'nixGL glxgears' works out-of-the-box
# pkgs.nixgl.auto.nixGLNvidia
# pkgs.nixgl.nixVulkanIntel # mesa+vulkan
# pkgs.nixgl.nixGLMesa
# pkgs.nixgl.nixGLNvidia # try this explicitly for wsl2
# *might* also need xorg.libXext.dev, xorg.libXrender.dev, xorg.xorgproto
]
++ (if pkgs.stdenv.isLinux then [ pkgs.stdenv.cc.cc.lib pkgs.glibc ] else [])
++ vkdeps
++ (if pkgs.stdenv.isDarwin then [ pkgs.darwin.moltenvk ] else [])
++ [
pkgs.xorg.xcbutil
pkgs.xorg.xcbutilwm # xcb window manager utilities
pkgs.xorg.xcbutilimage
# fonts for imgui
# pkgs.gucharmap
pkgs.noto-fonts
#pkgs.noto-fonts-lgc # lgc for latin,greek,cyrillic (but doesn't exist in pinned nixpkgs)
#pkgs.noto-fonts-cjk # cjk for chinese,japanese,korean
pkgs.noto-fonts-emoji
pkgs.dejavu_fonts
];
shellHook = ''
# CXENV: cosmetic: coordinates with ~/proj/env/dotfiles/bashrc to drive PS1
export CXENV=$CXENV:xo
# override SOUCE_DATE_EPOCH to current time (otherwise will get 1980)
export SOURCE_DATE_EPOCH=$(date +%s)
# software-only pipeline
#export SDL_VIDEODRIVER=x11
#export LIBGL_ALWAYS_SOFTWARE=1
#export SDL_VIDEO_X11_FORCE_EGL=0
#export SDL_VIDEO_X11_VISUALID=0x023
#export LIBGL_ALWAYS_INDIRECT=1
#export WSLG_FORCE_EGL=1
#export GLFW_USE_EGL=1
export VULKAN_SDK=${pkgs.vulkan-headers}
# for Vulkan on OSX only..
${pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
export VK_ICD_FILENAMES=${pkgs.darwin.moltenvk}/share/vulkan/icd.d/MoltenVK_icd.json
export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
''}
# do need VK_LAYER_PATH on OSX. Not sure if we need it on wsl2
#export VK_LAYER_PATH=${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d
# nixGL experiment (on wsl2). Doesn't work out of the box, but maybe with some help..
# TODO: put this in its own generated wrapper.
# TODO: if/when this works, refactor to use something like
# let vklibpath = pkgs.lib.makeLibraryPath [ pkgs.foo pkgs.libffi pkgs.glibc ... ];
# with
# export LD_LIBRARY_PATH="$vklibpath:$LD_LIBRARY_PATH"
# NOTE: nixGL doesn't really know how to handle a wsl2 host, in particular doesn't know
# about /usr/lib/wsl/lib
#
${pkgs.lib.optionalString pkgs.stdenv.isLinux ''
# export LD_LIBRARY_PATH=${pkgs.glibc}:$LD_LIBRARY_PATH
# export LD_LIBRARY_PATH=${xo_topdir}/etc/hostwsl:$LD_LIBRARY_PATH
# export LD_LIBRARY_PATH=${pkgs.vulkan-loader}/lib:$LD_LIBRARY_PATH
# export LD_LIBRARY_PATH=/usr/lib/wsl/lib:$LD_LIBRARY_PATH
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.mesa}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.libffi}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.wayland}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libXext}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libXau}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libXdmcp}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libXfixes}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libXxf86vm}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xorg.libX11}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.gcc.cc.lib}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.ncurses}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.expat}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.elfutils.out}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.libxml2.out}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.icu}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.libmd}
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.xz.out}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.zstd.out}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.zlib}/lib
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.libbsd}/lib
# #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.libedit}/lib # gets libedit.so.0, but system wants libedit.so.2
# #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${pkgs.lm_sensors} # wanted libsensors.so.5, this package doesn't provide it
export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
# lvp_icd.x86_64.json: llvm pipe rendering (software)
export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.x86_64.json
export VK_LD_PRELOAD=${pkgs.vulkan-loader}/lib/libvulkan.so.1
## mesa software rendering settings
# export GALLIUM_DRIVER=llvmpipe
# export MESA_GL_VERSION_OVERRIDE=3.3
# export LIBGL_ALWAYS_SOFTWARE=1
# export VK_LOADER_DEBUG=all # or info
# export MESA_DEBUG=1
# export EGL_LOG_LEVEL=debug
# export LIBGL_DEBUG=verbose
# vkcube --wsi xcb
''}
# just for info
export mesa_drivers=${pkgs.mesa.drivers}
export FONTCONFIG_FILE=${fonts}
export FONTCONFIG_PATH=${pkgs.fontconfig.out}/etc/fonts
export NOTO_FONTS_PATH=${pkgs.noto-fonts}/share/fonts
export DEJAVU_FONTS_PATH=${pkgs.dejavu_fonts}/share/fonts
# refresh font cache
${pkgs.fontconfig}/bin/fc-cache -fv
echo "FONTCONFIG_PATH=$FONTCONFIG_PATH"
echo "NOTO_FONTS_PATH=$NOTO_FONTS_PATH"
echo "xo development environment loaded!"
'';
};
}