commit ebdbba5dabfa3683199f1bf689b122d5387f2272 Author: Mikael Voss Date: Fri Nov 29 11:35:14 2024 +0100 Initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3d6222 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Hidden files +.* +!.git* + +# Nix +/result +/result-* diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..b8ffd30 --- /dev/null +++ b/flake.lock @@ -0,0 +1,114 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakey-profile": { + "locked": { + "lastModified": 1712898590, + "narHash": "sha256-FhGIEU93VHAChKEXx905TSiPZKga69bWl1VB37FK//I=", + "owner": "lf-", + "repo": "flakey-profile", + "rev": "243c903fd8eadc0f63d205665a92d4df91d42d9d", + "type": "github" + }, + "original": { + "owner": "lf-", + "repo": "flakey-profile", + "type": "github" + } + }, + "lix": { + "flake": false, + "locked": { + "lastModified": 1732899308, + "narHash": "sha256-1jsQqcbMbaWuFim3sqEUdB1/E2KqHa0+cHbTzd/GYFE=", + "rev": "2e5780ebc848f3b021f11dd94533b0b68362d989", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2e5780ebc848f3b021f11dd94533b0b68362d989.tar.gz?rev=2e5780ebc848f3b021f11dd94533b0b68362d989" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/lix/archive/main.tar.gz" + } + }, + "lix-module": { + "inputs": { + "flake-utils": "flake-utils", + "flakey-profile": "flakey-profile", + "lix": [ + "lix" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1732603698, + "narHash": "sha256-Jw2MhzgCCrKV2MJytehG0cCLIAosBX71p8qmQ6XQlR4=", + "rev": "15b999f9c958c475f71fb8c543b9fc2f36ae8730", + "type": "tarball", + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/15b999f9c958c475f71fb8c543b9fc2f36ae8730.tar.gz?rev=15b999f9c958c475f71fb8c543b9fc2f36ae8730" + }, + "original": { + "type": "tarball", + "url": "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1733249134, + "narHash": "sha256-aMaE93IAs3KR09jpsdz2/h/c7eQUCTS7Hf992On6l+g=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fdd294bc8fb594b6f9f5978671421f5647a47c65", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "staging", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "lix": "lix", + "lix-module": "lix-module", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..c104abc --- /dev/null +++ b/flake.nix @@ -0,0 +1,135 @@ +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/staging"; + + lix = { + url = "https://git.lix.systems/lix-project/lix/archive/main.tar.gz"; + flake = false; + }; + + lix-module = { + url = "https://git.lix.systems/lix-project/nixos-module/archive/main.tar.gz"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.lix.follows = "lix"; + }; + }; + + outputs = { self, nixpkgs, lix-module, ... }: let + inherit (builtins) mapAttrs match; + inherit (lib) filterAttrs genAttrs; + + lib = nixpkgs.lib.extend (import ./lib.nix); + systems = [ "riscv64-linux" "aarch64-linux" "x86_64-linux" ]; + packages = builtins.readDir ./packages + |> filterAttrs (name: type: (type == "regular" && match "[-.+_?=0-9a-zA-Z]+\.nix" name != null) + || (type == "directory" && match "[-.+_?=0-9a-zA-Z]+" name != null)) + |> lib.mapAttrs' (name: type: { + name = if type == "regular" then lib.removeSuffix ".nix" name else name; + value = + let path = if type == "directory" then "${name}/package.nix" else name; + in ./packages/${path}; + }); + in { + inherit lib; + + packages = self.legacyPackages + |> mapAttrs (system: pkgs: mapAttrs (name: path: pkgs.${name}) packages); + + overlays = let + lib' = final: prev: { inherit lib; }; + packages' = final: prev: packages |> mapAttrs (name: path: final.callPackage path { }); + in { + default = lib.composeManyExtensions (with self.overlays; [ + lib' + packages' + + lix + stdenv + alloc + non-x86-build + non-x86-host + security + modern + python + fixes + ]); + + lib = lib'; + packages = packages'; + lix = lix-module.overlays.default; + } // (builtins.readDir ./overlays + |> filterAttrs (name: type: type == "regular" && lib.hasSuffix ".nix" name) + |> lib.mapAttrs' (name: type: { + name = lib.removeSuffix ".nix" name; + value = import ./overlays/${name}; + })); + + legacyPackages = genAttrs systems (system: let + pkgs' = import nixpkgs { + localSystem = { + inherit system; + + gcc.arch = { + riscv64-linux = "rv64gc"; + aarch64-linux = "armv8.2-a+fp16+rcpc+dotprod"; + x86_64-linux = "x86-64-v3"; + }.${system}; + }; + + overlays = [ self.overlays.default ]; + config.allowUnfree = true; + }; + in import nixpkgs { + localSystem = pkgs'.hostPlatform; + overlays = [ self.overlays.default ]; + + config = { + allowUnfree = true; + replaceStdenv = { pkgs }: + import ./stdenv.nix pkgs' pkgs.stdenv; + replaceCrossStdenv = { buildPackages, baseStdenv }: + import ./stdenv.nix pkgs' baseStdenv; + }; + }); + + nixosModules = { + default = import ./module.nix; + }; + + hydraJobs = let + inherit (builtins) filter attrNames; + inherit (lib) any concat hydraJob; + inherit (lib.meta) platformMatch; + + extra = import ./hydra.nix; + in { + stdenv = self.legacyPackages |> mapAttrs (system: pkgs: hydraJob pkgs.stdenv); + } // { + nixos = self.legacyPackages |> mapAttrs (system: pkgs: let + nixos = lib.nixosSystem { + modules = [ + self.nixosModules.default { + system.stateVersion = "25.05"; + nixpkgs = { inherit (pkgs) hostPlatform overlays config; }; + + boot = { + kernel.enable = false; + initrd.enable = false; + loader.grub.enable = false; + }; + + users.allowNoPasswordLogin = true; + } + ]; + }; + in hydraJob nixos.config.system.build.toplevel); + } // lib.foldlAttrs (jobs: system: pkgs: let + inherit (pkgs.stdenv) hostPlatform; + names = extra ++ attrNames (self.overlays.default pkgs pkgs) |> filter (name: pkgs ? ${name}); + in lib.recursiveUpdate jobs (genAttrs names (name: pkgs.${name}) + |> filterAttrs (name: pkg: lib.isDerivation pkg + && (pkg.meta.hydraPlatforms or pkg.meta.platforms or [ ] |> any (platformMatch hostPlatform)) + && !(pkg.meta.badPlatforms or [ ] |> any (platformMatch hostPlatform))) + |> mapAttrs (name: pkg: { ${system} = hydraJob pkg; }))) { } self.legacyPackages; + }; +} diff --git a/hydra.nix b/hydra.nix new file mode 100644 index 0000000..55e0ed9 --- /dev/null +++ b/hydra.nix @@ -0,0 +1,34 @@ +[ + "stdenv" + "mimalloc" + "qemu-user" + + "clang" + "lld" + "rustc" + + "amd-libflame" + "blis" + "mesa" + + "pypy310" + "uutils-coreutils" + "systemd" + + "ceph" + "cockroachdb" + "openssh" + + "dbus-broker" + "pipewire" + "wireplumber" + + "fd" + "helix" + "jaq" + "kitty" + "niri" + "nushell" + "ripgrep" + "sd" +] diff --git a/lib.nix b/lib.nix new file mode 100644 index 0000000..9049c7a --- /dev/null +++ b/lib.nix @@ -0,0 +1,23 @@ +final: prev: +let + inherit (builtins) + typeOf isAttrs isList isString + mapAttrs; + inherit (final) filterAttrs toList; +in { + extendValue = set: name: ext: + assert (set ? ${name} -> (typeOf ext == typeOf set.${name})); + if isAttrs ext then mapAttrs (final.extendValue set.${name} or { }) ext + else if isList ext then set.${name} or [ ] ++ ext + else if isString ext then set.${name} or "" + "\n" + ext + else ext; + + extendAttrs = ext: prevAttrs: mapAttrs (final.extendValue prevAttrs) ext; + extendEnv = ext: prevAttrs: { + env = prevAttrs.env or { } + // (filterAttrs (n: v: !prevAttrs ? ${n}) ext |> mapAttrs (n: v: toList prevAttrs.env.${n} or [ ] ++ v |> toString)); + } // (filterAttrs (n: v: prevAttrs ? ${n}) ext |> mapAttrs (n: v: toList prevAttrs.${n} ++ v)); + + extendDrvAttrs = ext: drv: drv.overrideAttrs (final.extendAttrs ext); + extendDrvEnv = ext: drv: drv.overrideAttrs (final.extendEnv ext); +} diff --git a/module.nix b/module.nix new file mode 100644 index 0000000..7f62b4b --- /dev/null +++ b/module.nix @@ -0,0 +1,71 @@ +{ lib, config, pkgs, ... }: +let + inherit (lib) mkDefault mkForce; +in { + documentation.info.enable = mkForce false; + environment.memoryAllocator.provider = mkForce "mimalloc"; + + networking = { + nftables.enable = mkDefault true; + useNetworkd = mkDefault true; + }; + + nix = { + channel.enable = mkDefault false; + + daemonCPUSchedPolicy = mkDefault "batch"; + daemonIOSchedClass = mkDefault "best-effort"; + daemonIOSchedPriority = mkDefault 7; + + settings = { + experimental-features = [ + "cgroups" + "dynamic-derivations" + "flakes" + "nix-command" + "pipe-operator" + "repl-flake" + ]; + + allowed-users = config.users.users + |> lib.filterAttrs (_: user: user.isNormalUser) + |> lib.mapAttrsToList (_: user: user.name) + |> mkDefault; + trusted-users = mkDefault [ "@wheel" ]; + + builders-use-substitutes = mkDefault true; + http-connections = mkDefault 128; + max-substitution-jobs = mkDefault 32; + + preallocate-contents = mkDefault true; + use-cgroups = mkDefault true; + use-sqlite-wal = mkForce true; + use-xdg-base-directories = mkDefault true; + }; + + /* + registry = { + nixpkgs.to = mkDefault { + type = "path"; + path = pkgs.path; + narHash = lib.trim (builtins.readFile + (pkgs.runCommand "nixpkgs-hash" { + preferLocal = true; + } "${lib.getExe config.nix.package} hash path --sri --type sha256 ${pkgs.path} >$out")); + }; + }; + */ + }; + + security = { + sudo.enable = mkDefault false; + sudo-rs.enable = mkDefault true; + }; + + services = { + dbus.implementation = mkDefault "broker"; + xserver.enable = mkForce false; + }; + + users.mutableUsers = mkDefault false; +} diff --git a/overlays/alloc.nix b/overlays/alloc.nix new file mode 100644 index 0000000..1522bda --- /dev/null +++ b/overlays/alloc.nix @@ -0,0 +1,39 @@ +final: prev: +let + inherit (prev) lib; + inherit (lib) + mapAttrsToList + concatStringsSep + extendDrvAttrs + extendDrvEnv; +in { + mimalloc = let + mimalloc = prev.mimalloc |> extendDrvAttrs { + cmakeFlags = let + cppdefs = { + MI_DEFAULT_EAGER_COMMIT = 0; + MI_DEFAULT_ALLOW_LARGE_OS_PAGES = 1; + } |> mapAttrsToList (name: value: "${name}=${toString value}") + |> concatStringsSep ";"; + in [ ''-DMI_EXTRA_CPPDEFS="${cppdefs}"'' ]; + }; + in mimalloc.override { secureBuild = true; }; + + # incompatible allocators + gperftools = null; + jemalloc = null; + rust-jemalloc-sys = null; + + # individual packages + conduwuit = prev.conduwuit.override { enableJemalloc = false; }; + + sqlite = prev.sqlite |> extendDrvEnv { + NIX_CFLAGS_COMPILE = [ + "-DSQLITE_DEFAULT_PAGE_SIZE=2097152" + "-DSQLITE_DEFAULT_CACHE_SIZE=-64" + "-DSQLITE_DEFAULT_PCACHE_INITSZ=1" + "-DSQLITE_MALLOC_SOFT_LIMIT=0" + "-DSQLITE_USE_ALLOCA" + ]; + }; +} diff --git a/overlays/fixes.nix b/overlays/fixes.nix new file mode 100644 index 0000000..596f570 --- /dev/null +++ b/overlays/fixes.nix @@ -0,0 +1,111 @@ +final: prev: let + inherit (final) stdenv; + inherit (stdenv) hostPlatform; + inherit (prev) lib; + inherit (lib) + extendDrvAttrs extendDrvEnv + optionals; +in { + autoconf = prev.autoconf.overrideAttrs (prevAttrs: { + outputs = lib.remove "doc" prevAttrs.outputs; + + postBuild = null; + postInstall = null; + }); + + blis = prev.blis |> extendDrvAttrs { + buildInputs = [ final.llvmPackages.openmp ]; + } |> extendDrvEnv { + NIX_CFLAGS_COMPILE = optionals hostPlatform.isx86 [ "-fno-lto" ]; + }; + + busybox = let + busybox = prev.busybox |> extendDrvAttrs { + makeFlags = let + build = final.pkgsBuildBuild.targetPackages.llvmPackages.clangUseLLVM; + host = final.pkgsBuildHost.targetPackages.llvmPackages.clangUseLLVM; + exe = pkg: prg: lib.getExe' pkg (pkg.targetPrefix + prg); + in [ + "HOSTCC=${exe build "clang"}" + "HOSTCXX=${exe build "clang++"}" + "AS=${exe host "as"}" + "CC=${exe host "clang"}" + "LD=${exe host "clang"} -nostdlib" + "CPP=${exe host "cpp"}" + "AR=${exe host.bintools "ar"}" + "NM=${exe host.bintools "nm"}" + "STRIP=${exe host.bintools "strip"}" + "OBJCOPY=${exe host.bintools "objcopy"}" + "OBJDUMP=${exe host.bintools "objdump"}" + ]; + }; + in busybox.override { + stdenv = final.clangStdenv; + }; + + kexec-tools = prev.kexec-tools |> extendDrvAttrs { + configureFlags = [ "AS=${stdenv.cc.bintools.targetPrefix}as" ]; + } |> extendDrvEnv { + NIX_LDFLAGS = [ "--icf=none" ]; + }; + + keyutils = prev.keyutils |> extendDrvEnv { + LDFLAGS = [ "-Wl,--undefined-version" ]; + }; + + libbsd = prev.libbsd |> extendDrvAttrs { + configureFlags = [ "abi_nlist=no" ]; + } |> extendDrvEnv { + NIX_LDFLAGS = [ "--undefined-version" ]; + }; + + libjpeg_turbo = prev.libjpeg_turbo |> extendDrvAttrs { + postPatch = '' + cat >>CMakeLists.txt < extendDrvAttrs { + postPatch = '' + substituteInPlace tests/pngtest-all \ + --replace-warn --strict --relaxed + ''; + }; + + libredirect = prev.libredirect |> extendDrvEnv { + NIX_CFLAGS_COMPILE = [ "-fsemantic-interposition" ]; + }; + + libvpx = prev.libvpx |> extendDrvAttrs { + # Avoid build failure when attempting to strip bitcode library + makeFlags = [ "HAVE_GNU_STRIP=no" ]; + }; + + libxcrypt = prev.libxcrypt |> extendDrvEnv { + # https://github.com/besser82/libxcrypt/issues/24 + NIX_CFLAGS_COMPILE = [ "-fno-lto" ]; + }; + + patchelf = prev.patchelf |> extendDrvAttrs { + patches = [ ../patches/patchelf-hash-optional.patch ]; + }; + + tcl = prev.tcl |> extendDrvEnv { + NIX_CFLAGS_COMPILE = [ "-fno-lto" ]; + }; + + time = prev.time |> extendDrvAttrs { + patches = [ + (final.fetchpatch { + url = "https://gitweb.gentoo.org/repo/gentoo.git/plain/sys-process/time/files/time-1.9-implicit-func-decl-clang.patch"; + hash = "sha256-Asz8mWxVh4y3In5NU1dDV7nrJO+XlIhmKIvVFuPH8QE="; + }) + ]; + }; + + wayland = prev.wayland.override { withDocumentation = false; }; +} diff --git a/overlays/modern.nix b/overlays/modern.nix new file mode 100644 index 0000000..2f74598 --- /dev/null +++ b/overlays/modern.nix @@ -0,0 +1,209 @@ +final: prev: +let + inherit (builtins) match; + inherit (final) stdenv; + inherit (stdenv) hostPlatform; + inherit (prev) lib; + inherit (lib) + extendDrvAttrs extendDrvEnv + optionals; + + isZen = hostPlatform.isx86 && match "znver[12345]" hostPlatform.gcc.arch or "" != null; +in { + # booleans + enableAlsa = false; + enableGUI = false; + enableGui = false; + enableJack = false; + enableX11 = false; + enableXWayland = false; + alsaSupport = false; + gssSupport = false; + sndioSupport = false; + x11Support = false; + xineramaSupport = false; + withAlsa = false; + withBluray = false; + withCdio = false; + withDvdnav = false; + withDvdread = false; + withGui = false; + withJack = false; + withLibao = false; + withSdl2 = false; + withXcb = false; + withXlib = false; + withXorg = false; + + # disabled packages + SDL1 = null; + aalib = null; + gtk2 = null; + iptables-legacy = null; + jack1 = null; + jack2 = null; + libao = null; + libapparmor = null; + libcaca = null; + libjack = null; + libjack2 = null; + libselinux = null; + pulseaudioFull = null; + sndio = null; + texinfo = null; + xwayland = null; + + bind = prev.bind.override { enableGSSAPI = false; }; + + curl = prev.curl.override { + scpSupport = false; + zstdSupport = true; + }; + + blas = prev.blas.override { + blasProvider = if isZen then final.amd-blis else final.blis; + }; + + blis = prev.blis.override { + withArchitecture = + if hostPlatform.isRiscV then "rv64i" + else if hostPlatform.isAarch then "arm64" + else if hostPlatform.isx86 then "x86_64" + else "generic"; + }; + + cpio = final.runCommand "libarchive-cpio" { + preferLocalBuild = true; + meta.mainProgram = "cpio"; + } '' + mkdir -p "$out/bin" + ln -s "${lib.getExe' final.libarchive "bsdcpio"}" "$out/bin/cpio" + ''; + + electron = prev.electron.override { + electron-unwrapped = prev.electron.unwrapped |> extendDrvAttrs { + gnFlags = '' + # Disable X11 + ozone_platform_x11 = false + + # Disable internal memory allocator + use_partition_alloc_as_malloc = false + enable_backup_ref_ptr_support = false + enable_pointer_compression_support = false + ''; + }; + }; + + ffmpeg = prev.ffmpeg.override { + withSsh = false; + }; + + ffmpeg-headless = prev.ffmpeg-headless.override { + withSsh = false; + }; + + ffmpeg-browser = final.ffmpeg-headless.override { + withAmf = false; + withAom = false; + withCodec2 = true; + withDrm = false; + withGnutls = false; + withMp3lame = false; + withTwolame = false; + withV4l2 = false; + withXvid = false; + + withNetwork = false; + withBin = false; + withLib = true; + withDocumentation = false; + withStripping = true; + }; + + jdk = final.jdk_headless; + jre = final.jre_headless; + + lapack = prev.lapack.override { + lapackProvider = if isZen then final.amd-libflame else final.openblas; + }; + + lix = prev.lix.override { enableGC = true; }; + + mesa = let + mesa = prev.mesa.overrideAttrs (prevAttrs: { + outputs = prevAttrs.outputs |> lib.remove "spirv2dxil"; + }); + in mesa.override { + galliumDrivers = [ + "llvmpipe" + "nouveau" + "radeonsi" + "virgl" + "zink" + ]; + + vulkanDrivers = [ + "amd" + "intel" + "nouveau" + "swrast" + "virtio" + ]; + }; + + minizip = final.minizip-ng; + + qemu = prev.qemu.override { + hostCpuTargets = lib.mapCartesianProduct ({arch, mach}: "${arch}-${mach}") { + arch = [ "riscv64" "aarch64" "x86_64" ]; + mach = [ "softmmu" "linux-user" ]; + }; + }; + + mpv = final.mpv-unwrapped.wrapper { mpv = final.mpv-unwrapped; }; + mpv-unwrapped = prev.mpv-unwrapped.override { + cacaSupport = false; + openalSupport = false; + sdl2Support = false; + }; + + nix = final.lix; + + pulseaudio = prev.pulseaudio.override { + libOnly = true; + ossWrapper = false; + }; + + sqlite = prev.sqlite |> extendDrvEnv { + NIX_CFLAGS_COMPILE = [ + "-DSQLITE_THREADSAFE=2" + "-DSQLITE_OMIT_LOOKASIDE" + + "-DSQLITE_DEFAULT_MMAP_SIZE=281474976710656" + "-DSQLITE_MAX_MMAP_SIZE=281474976710656" + "-DSQLITE_DEFAULT_FILE_PERMISSIONS=0600" + "-DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1" + "-DSQLITE_DEFAULT_WORKER_THREADS=4" + "-USQLITE_SECURE_DELETE" + "-DSQLITE_ENABLE_NULL_TRIM" + ]; + }; + + svt-av1 = final.svt-av1-psy; + + systemd = prev.systemd.override { + withApparmor = false; + withIptables = false; + }; + + wrapFirefox = prev.wrapFirefox.override { + ffmpeg = final.ffmpeg-decode; + }; + + xorg = prev.xorg.overrideScope (final: prev: { + libXScrnSaver = null; + libXinerama = null; + libXv = null; + libXvMC = null; + }); +} diff --git a/overlays/non-x86-build.nix b/overlays/non-x86-build.nix new file mode 100644 index 0000000..4251795 --- /dev/null +++ b/overlays/non-x86-build.nix @@ -0,0 +1,22 @@ +final: prev: +let + inherit (final) stdenv; + inherit (prev) lib; +in lib.optionalAttrs (!prev.stdenv.buildPlatform.isx86) { + # no shellcheck on RISC-V and ARM + writeShellApplication = { ... }@args: prev.writeShellApplication (args // { + checkPhase = args.checkPhase or '' + runHook preCheck + ${stdenv.shellDryRun} "$target" + runHook postCheck + ''; + }); + + # no GHC support for RISC-V and ARM + pandoc = null; + + # no pandoc on RISC-V and ARM + sudo-rs = prev.sudo-rs.overrideAttrs { + postInstall = ""; + }; +} diff --git a/overlays/non-x86-host.nix b/overlays/non-x86-host.nix new file mode 100644 index 0000000..7c27bee --- /dev/null +++ b/overlays/non-x86-host.nix @@ -0,0 +1,19 @@ +final: prev: +let + inherit (prev) lib; + inherit (lib) extendDrvAttrs; +in lib.optionalAttrs (!prev.stdenv.hostPlatform.isx86) { + # BLIS works well on non‐x86 platforms + blis = prev.blis |> extendDrvAttrs { + meta.platforms = [ "riscv64-linux" "aarch64-linux" ]; + }; + + # JDK 17 is not available for RISC-V and ARM + jdk17_headless = final.jdk21_headless; + + # QEMU test failures + bison = prev.bison.overrideAttrs { doInstallCheck = false; }; + coreutils = prev.coreutils.overrideAttrs { doCheck = false; }; + gnugrep = prev.gnugrep.overrideAttrs { doCheck = false; }; + libuv = prev.libuv.overrideAttrs { doCheck = false; }; +} diff --git a/overlays/python.nix b/overlays/python.nix new file mode 100644 index 0000000..6e6082e --- /dev/null +++ b/overlays/python.nix @@ -0,0 +1,17 @@ +final: prev: +let + inherit (final) stdenv; + inherit (stdenv) hostPlatform; + inherit (prev) lib; + + packageOverrides = final: prev: { + psutil = prev.psutil.overrideAttrs { + doCheck = hostPlatform.isx86; + doInstallCheck = hostPlatform.isx86; + }; + }; +in { + python311 = prev.python311.override { inherit packageOverrides; }; + python312 = prev.python312.override { inherit packageOverrides; }; + python313 = prev.python313.override { inherit packageOverrides; }; +} diff --git a/overlays/security.nix b/overlays/security.nix new file mode 100644 index 0000000..0e2aae0 --- /dev/null +++ b/overlays/security.nix @@ -0,0 +1,123 @@ +final: prev: +let + inherit (prev) lib; + inherit (lib) extendDrvAttrs extendDrvEnv; + + concat = lib.concatStringsSep ","; +in { + sanitise = san: extendDrvEnv { + NIX_CFLAGS_COMPILE = [ + "-fsanitize-minimal-runtime" + "-fsanitize-undefined-strip-path-components=2" + "-fsanitize=${concat san}" + "-fno-sanitize-recover=${concat san}" + ]; + + NIX_CFLAGS_LINK = [ "-fsanitize-minimal-runtime" ]; + }; + + sanitise-trap = san: extendDrvEnv { + NIX_CFLAGS_COMPILE = [ "-fsanitize-trap=${concat san}" ]; + }; + + avahi = prev.avahi |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + bzip2 = prev.bzip2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + c-ares = prev.c-ares |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + cups = prev.cups |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + cups-filters = prev.cups-filters |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + curl = prev.curl |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + dbus = prev.dbus |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + dbus-broker = prev.dbus-broker |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + ffmpeg = prev.ffmpeg |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + ffmpeg-headless = prev.ffmpeg-headless |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + file = prev.file |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + firefox-unwrapped = prev.firefox-unwrapped |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + firefox-beta-unwrapped = prev.firefox-beta-unwrapped |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + firefox-esr-unwrapped = prev.firefox-esr-unwrapped |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + fontconfig = prev.fontconfig |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + freetype = prev.freetype |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + fribidi = prev.fribidi |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + ghostscript = prev.ghostscript |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + giflib = prev.giflib |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + git = prev.git |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + gnupg = prev.gnupg |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + gnutar = prev.gnutar |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + gnutls = prev.gnutls |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + gumbo = prev.gumbo |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + gzip = prev.gzip |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + harfbuzz = prev.harfbuzz |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + icu72 = prev.icu72 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + icu73 = prev.icu73 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + icu74 = prev.icu74 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + icu75 = prev.icu75 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + icu76 = prev.icu76 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + imagemagick = prev.imagemagick |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + imlib2 = prev.imlib2 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + iputils = prev.iputils |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + jansson = prev.jansson |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + jbig2dec = prev.jbig2dec |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + jq = prev.jq |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + json_c = prev.json_c |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + ldns = prev.ldns |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libarchive = prev.libarchive |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libev = prev.libev |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libcbor= prev.libcbor |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libevent = prev.libevent |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libexif = prev.libexif |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libheif = prev.libheif |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libid3tag = prev.libid3tag |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libidn2 = prev.libidn2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libjpeg_turbo = prev.libjpeg_turbo |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libjxl = prev.libjxl |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libmicrohttpd = prev.libmicrohttpd |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libpcap = prev.libpcap |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libpng = prev.libpng |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libvpx = prev.libvpx |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libwebp = prev.libwebp |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libressl = prev.libressl |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + librsvg = prev.librsvg |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libspectre = prev.libspectre |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libssh2 = prev.libssh2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libtiff = prev.libtiff |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + libunistring = prev.libunistring |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libxml2 = prev.libxml2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + libxslt = prev.libxslt |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + linux-pam = prev.linux-pam |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + lix = prev.lix |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + lz4 = prev.lz4 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + lzip = prev.lzip |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + lzo = prev.lzo |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + mercurial = prev.mercurial |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + mujs = prev.mujs |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + mupdf = prev.mupdf |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nghttp2 = prev.nghttp2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + ngtcp2 = prev.ngtcp2 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nlohmann_json = prev.nlohmann_json |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nodejs_22 = prev.nodejs_22 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nodejs_23 = prev.nodejs_23 |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nss_esr = prev.nss_esr |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + nss_latest = prev.nss_latest |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + openjpeg = prev.openjpeg |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + openssh = prev.openssh |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + openssl = prev.openssl |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + pcre = prev.pcre |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + pcre2 = prev.pcre2 |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + poppler = prev.poppler |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + rsync = prev.rsync |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + sane-backends = prev.sane-backends |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + sane-frontends = prev.sane-frontends |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + shadow = prev.shadow |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + sharutils = prev.sharutils |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + sioyek = prev.sioyek |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + snappy = prev.snappy |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + systemd = prev.systemd |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + tcb = prev.tcb |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + unbound = prev.unbound |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + unzip = prev.unzip |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + util-linux = prev.util-linux |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + wget = prev.wget |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + xz = prev.xz |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + yara = prev.yara |> final.sanitise [ "bounds" "object-size" "vla-bound" ]; + zlib-ng = prev.zlib-ng |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; + zstd = prev.zstd |> final.sanitise-trap [ "bounds" "object-size" "vla-bound" ]; +} diff --git a/overlays/stdenv.nix b/overlays/stdenv.nix new file mode 100644 index 0000000..b9d0569 --- /dev/null +++ b/overlays/stdenv.nix @@ -0,0 +1,116 @@ +final: prev: +let + inherit (builtins) isAttrs; + inherit (final) + lib + stdenv + pkgsBuildBuild + pkgsBuildHost + pkgsBuildTarget; + inherit (lib) extendDrvAttrs; +in { + # break dependency cycle + libarchive = prev.libarchive.override { + e2fsprogs = final.e2fsprogs.override { withFuse = false; }; + }; + + llvmPackages = prev.llvmPackages // { + clang = final.llvmPackages.clangUseLLVM; + + clangUseLLVM = let + clangUseLLVM' = prev.llvmPackages.clangUseLLVM |> extendDrvAttrs { + postFixup = '' + pushd "$out/nix-support" + + sed -E -i 's/(-ftrivial-auto-var-init=)pattern/\1zero/' \ + add-hardening.sh + + cat >>cc-cflags <>cc-cflags-before < extendDrvAttrs { + postFixup = '' + cat >>"$out/nix-support/libc-ldflags-before" < recurse [ ] |> lib.flatten; + in prevAttrs.configureFlags or [ ] ++ [ + "--enable-llvm-link-shared" + "--llvm-libunwind=system" + "--enable-use-libcxx" + ] ++ config; + }); + }); + }; + }; +} diff --git a/packages/xvfb-run.nix b/packages/xvfb-run.nix new file mode 100644 index 0000000..4bba2f1 --- /dev/null +++ b/packages/xvfb-run.nix @@ -0,0 +1,20 @@ +{ lib, writeShellApplication, cage }: + +writeShellApplication { + name = "xvfb-run"; + text = '' + # Discard all options + while [[ "$1" =~ ^- ]]; do + case "$1" in + (-e|-f|-n|-p|-s|-w) shift ;& + (*) shift ;; + esac + done + + WLR_BACKENDS=headless \ + WLR_LIBINPUT_NO_DEVICES=1 \ + WLR_RENDERER=pixman \ + XDG_RUNTIME_DIR="$(mktemp -d)" \ + exec '${lib.getExe cage}' -- "$@" + ''; +} diff --git a/packages/zlib.nix b/packages/zlib.nix new file mode 100644 index 0000000..529c329 --- /dev/null +++ b/packages/zlib.nix @@ -0,0 +1,31 @@ +{ lib, stdenv, fetchurl, zlib-ng, ... }: + +assert zlib-ng.version == "2.2.2"; + +stdenv.mkDerivation (finalAttrs: { + inherit (zlib-ng) pname version meta; + + src = fetchurl { + url = "https://github.com/zlib-ng/zlib-ng/archive/refs/tags/${finalAttrs.version}.tar.gz"; + hash = "sha256-/LQd1Zo/FwAq6xuyHwRpbJtyFASJC7lFxas50stpZUw="; + }; + + outputs = [ "out" "dev" "man" ]; + + setOutputFlags = false; + dontAddDisableDepTrack = true; + configurePlatforms = [ ]; + + env = { + CHOST = stdenv.hostPlatform.config; + }; + + configureFlags = [ + "--libdir=${placeholder "dev"}/lib" + "--sharedlibdir=${placeholder "out"}/lib" + "--includedir=${placeholder "dev"}/include" + "--zlib-compat" + ]; + + makeFlags = [ "mandir=$(man)/share/man" ]; +}) diff --git a/patches/patchelf-hash-optional.patch b/patches/patchelf-hash-optional.patch new file mode 100644 index 0000000..3154283 --- /dev/null +++ b/patches/patchelf-hash-optional.patch @@ -0,0 +1,18 @@ +diff --git a/src/patchelf.cc b/src/patchelf.cc +index 35a5dc1..a133d2e 100644 +--- a/src/patchelf.cc ++++ b/src/patchelf.cc +@@ -1201,9 +1201,10 @@ void ElfFile::rewriteHeaders(Elf_Addr phdrAddress) + dyn->d_un.d_val = findSectionHeader(".dynstr").sh_size; + else if (d_tag == DT_SYMTAB) + dyn->d_un.d_ptr = findSectionHeader(".dynsym").sh_addr; +- else if (d_tag == DT_HASH) +- dyn->d_un.d_ptr = findSectionHeader(".hash").sh_addr; +- else if (d_tag == DT_GNU_HASH) { ++ else if (d_tag == DT_HASH) { ++ auto shdr = tryFindSectionHeader(".hash"); ++ if (shdr) dyn->d_un.d_ptr = (*shdr).get().sh_addr; ++ } else if (d_tag == DT_GNU_HASH) { + auto shdr = tryFindSectionHeader(".gnu.hash"); + // some binaries might this section stripped + // in which case we just ignore the value. diff --git a/stdenv.nix b/stdenv.nix new file mode 100644 index 0000000..cc2cf3c --- /dev/null +++ b/stdenv.nix @@ -0,0 +1,31 @@ +pkgs: baseStdenv: let + inherit (pkgs) lib; + inherit (lib) + concatStrings + optionals + optionalAttrs + mapAttrsToList + extendEnv; + inherit (stdenv) targetPlatform; + + stdenv = pkgs.overrideCC baseStdenv pkgs.llvmPackages.clangUseLLVM; +in pkgs.addAttrsToDerivation (extendEnv { + NIX_RUSTFLAGS = let + target-cpu = targetPlatform.rust.rustcTargetCPU + or (if targetPlatform.isx86 then "x86-64-v3" else null); + + target-features = targetPlatform.rust.rustcTargetFeatures + or (optionalAttrs targetPlatform.isAarch { + "v8.2a" = true; + fp16 = true; + rcpc = true; + dotprod = true; + }) |> mapAttrsToList (n: v: (if v then "+" else "-") + n) |> concatStrings; + in [ + "-C" "codegen-units=1" + "-C" "opt-level=2" + "-C" "linker-plugin-lto" + "-C" "prefer-dynamic" + "-C" "target-features=${target-features}" + ] ++ optionals (target-cpu != null) [ "-C target-cpu=${target-cpu}" ]; +}) stdenv