diff options
75 files changed, 2103 insertions, 1065 deletions
diff --git a/.gitignore b/.gitignore index 5409b2f09..d25f6310f 100644 --- a/.gitignore +++ b/.gitignore @@ -21,15 +21,13 @@ perl/Makefile.config /doc/manual/conf-file.json /doc/manual/language.json /doc/manual/xp-features.json -/doc/manual/src/SUMMARY.md -/doc/manual/src/SUMMARY-rl-next.md /doc/manual/src/command-ref/new-cli /doc/manual/src/command-ref/conf-file.md /doc/manual/src/command-ref/experimental-features-shortlist.md /doc/manual/src/contributing/experimental-feature-descriptions.md /doc/manual/src/language/builtins.md /doc/manual/src/language/builtin-constants.md -/doc/manual/src/release-notes/rl-next.md +/doc/manual/src/release-notes/rl-next-generated.md # /scripts/ /scripts/nix-profile.sh diff --git a/bench/.gitignore b/bench/.gitignore new file mode 100644 index 000000000..8115aa6f2 --- /dev/null +++ b/bench/.gitignore @@ -0,0 +1,3 @@ +bench-*.json +bench-*.md +nixpkgs diff --git a/bench/README.md b/bench/README.md new file mode 100644 index 000000000..4aefcd7a8 --- /dev/null +++ b/bench/README.md @@ -0,0 +1,91 @@ +# Benchmarking scripts for Lix + +These are very much WIP, and have a few clumsy assumptions that we would +somewhat rather be fixed, but we have committed them to let others be able to +do benchmarking in the mean time. + +## Benchmarking procedure + +Build some Lixes you want to compare, by whichever means you wish. + +Get a computer that is not busy and *strongly preferably* is bare-metal or at +least not a cloud VM (e.g. go make coffee when running benchmarks). + +From the root of a Lix checkout, run `./bench/bench.sh resultlink-one +resultlink-two`, where `resultlink-one` and `resultlink-two` are the result +links from the builds you want to test (they can be any directory with bin/nix +in it, however). + +To get the summary again, run `./bench/summarize.jq bench/bench-*.json`. + +## Example results + +(vim tip: `:r !bench/summarize.jq bench/bench-*.json` to dump it directly into +your editor) + +``` +result-asserts/bin/nix --extra-experimental-features 'nix-command flakes' search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6 +c6fe19ccb59cac54b5b3f25e160870 hello + mean: 15.993s ± 0.081s + user: 13.321s | system: 1.865s + median: 15.994s + range: 15.829s ... 16.096s + relative: 1 +result/bin/nix --extra-experimental-features 'nix-command flakes' search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6c6fe19cc +b59cac54b5b3f25e160870 hello + mean: 15.897s ± 0.075s + user: 13.248s | system: 1.843s + median: 15.88s + range: 15.807s ... 16.047s + relative: 0.994 + +--- + +result/bin/nix --extra-experimental-features 'nix-command flakes' eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix + mean: 0.4s ± 0.024s + user: 0.335s | system: 0.046s + median: 0.386s + range: 0.379s ... 0.43s + relative: 1 + +result-asserts/bin/nix --extra-experimental-features 'nix-command flakes' eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix + mean: 0.404s ± 0.024s + user: 0.338s | system: 0.046s + median: 0.386s + range: 0.384s ... 0.436s + relative: 1.008 + +--- + +result-asserts/bin/nix --extra-experimental-features 'nix-command flakes' eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' + mean: 5.838s ± 0.023s + user: 5.083s | system: 0.464s + median: 5.845s + range: 5.799s ... 5.867s + relative: 1 + +result/bin/nix --extra-experimental-features 'nix-command flakes' eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' + mean: 5.788s ± 0.044s + user: 5.056s | system: 0.439s + median: 5.79s + range: 5.715s ... 5.876s + relative: 0.991 + +--- + +GC_INITIAL_HEAP_SIZE=10g result-asserts/bin/nix eval --extra-experimental-features 'nix-command flakes' --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' + mean: 4.147s ± 0.021s + user: 3.457s | system: 0.487s + median: 4.147s + range: 4.123s ... 4.195s + relative: 1 + +GC_INITIAL_HEAP_SIZE=10g result/bin/nix eval --extra-experimental-features 'nix-command flakes' --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' + mean: 4.149s ± 0.027s + user: 3.483s | system: 0.456s + median: 4.142s + range: 4.126s ... 4.215s + relative: 1 + +--- +``` diff --git a/bench/bench.sh b/bench/bench.sh new file mode 100755 index 000000000..70acd4640 --- /dev/null +++ b/bench/bench.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -euo pipefail +shopt -s inherit_errexit + +scriptdir=$(cd "$(dirname -- "$0")" ; pwd -P) +cd "$scriptdir/.." + +if [[ $# -lt 2 ]]; then + # FIXME(jade): it is a reasonable use case to want to run a benchmark run + # on just one build. However, since we are using hyperfine in comparison + # mode, we would have to combine the JSON ourselves to support that, which + # would probably be better done by writing a benchmarking script in + # not-bash. + echo "Fewer than two result dirs given, nothing to compare!" >&2 + echo "Pass some directories (with names indicating which alternative they are) with bin/nix in them" >&2 + echo "Usage: ./bench/bench.sh result-1 result-2 [result-3...]" >&2 + exit 1 +fi + +_exit="" +trap "$_exit" EXIT + +# XXX: yes this is very silly. flakes~!! +nix build --impure --expr '(builtins.getFlake "git+file:.").inputs.nixpkgs.outPath' -o bench/nixpkgs + +export NIX_REMOTE="$(mktemp -d)" +_exit='rm -rfv "$NIX_REMOTE"; $_exit' +export NIX_PATH="nixpkgs=bench/nixpkgs:nixos-config=bench/configuration.nix" + +builds=("$@") + +flake_args="--extra-experimental-features 'nix-command flakes'" + +hyperfineArgs=( + --parameter-list BUILD "$(IFS=,; echo "${builds[*]}")" + --warmup 2 --runs 10 +) + +declare -A cases +cases=( + [search]="{BUILD}/bin/nix $flake_args search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6c6fe19ccb59cac54b5b3f25e160870 hello" + [rebuild]="{BUILD}/bin/nix $flake_args eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system'" + [rebuild-lh]="GC_INITIAL_HEAP_SIZE=10g {BUILD}/bin/nix eval $flake_args --raw --impure --expr 'with import <nixpkgs/nixos> {}; system'" + [parse]="{BUILD}/bin/nix $flake_args eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix" +) + +benches=( + rebuild + rebuild-lh + search + parse +) + +for k in "${benches[@]}"; do + taskset -c 2,3 \ + chrt -f 50 \ + hyperfine "${hyperfineArgs[@]}" --export-json="bench/bench-${k}.json" --export-markdown="bench/bench-${k}.md" "${cases[$k]}" +done + +echo "Benchmarks summary (from ./bench/summarize.jq bench/bench-*.json)" +bench/summarize.jq bench/*.json diff --git a/bench/configuration.nix b/bench/configuration.nix new file mode 100644 index 000000000..54782a1d3 --- /dev/null +++ b/bench/configuration.nix @@ -0,0 +1,325 @@ +{ + config, + pkgs, + lib, + ... +}: + +{ + boot = { + initrd = { + availableKernelModules = [ + "xhci_pci" + "ahci" + ]; + kernelModules = [ "dm-snapshot" ]; + luks.devices = { + croot = { + device = "/dev/sdb"; + allowDiscards = true; + }; + }; + }; + kernelModules = [ "kvm-intel" ]; + kernelPackages = pkgs.linuxPackages_latest; + + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + }; + + hardware = { + enableRedistributableFirmware = true; + cpu.intel.updateMicrocode = true; + opengl.driSupport32Bit = true; + opengl.extraPackages = with pkgs; [ + vaapiIntel + intel-media-driver + intel-compute-runtime + ]; + }; + + fileSystems = { + "/" = { + device = "/dev/sda2"; + fsType = "xfs"; + options = [ "noatime" ]; + }; + + "/boot" = { + device = "/dev/sda1"; + fsType = "vfat"; + }; + + "/nas" = { + device = "nas:/"; + fsType = "nfs4"; + options = [ + "ro" + "x-systemd.automount" + ]; + }; + }; + swapDevices = [ { device = "/dev/swap"; } ]; + + networking = { + useDHCP = false; + hostName = "host"; + wireless = { + enable = true; + interfaces = [ "eth1" ]; + }; + interfaces = { + eth0.useDHCP = true; + eth1.useDHCP = true; + }; + wg-quick.interfaces = { + wg0 = { + address = [ "2001:db8::1" ]; + privateKeyFile = "/etc/secrets/wg0.key"; + peers = [ + { + publicKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; + endpoint = "[2001:db8::2]:61021"; + allowedIPs = [ "2001::db8:1::/64" ]; + } + ]; + }; + }; + + firewall.allowedUDPPorts = [ 4567 ]; + }; + + i18n = { + defaultLocale = "en_US.UTF-8"; + inputMethod.enabled = "ibus"; + }; + + services = { + xserver = { + enable = true; + layout = "us"; + xkbVariant = "altgr-intl"; + xkbOptions = "ctrl:nocaps"; + libinput.enable = true; + wacom.enable = true; + videoDrivers = [ "modesetting" ]; + modules = [ pkgs.xf86_input_wacom ]; + + displayManager.sx.enable = true; + windowManager.i3.enable = true; + }; + + udev.extraHwdb = '' + # not like this mattered at all + # we're not running udev from here + ''; + + udev.extraRules = '' + # ACTION=="add", SUBSYSTEM=="input", ... + ''; + }; + + sound.enable = true; + hardware.pulseaudio = { + enable = true; + package = pkgs.pulseaudioFull; + daemon.config = { + lock-memory = "yes"; + realtime-scheduling = "yes"; + rlimit-rtprio = "-1"; + }; + }; + + programs = { + light.enable = true; + wireshark = { + enable = true; + package = pkgs.wireshark-qt; + }; + gnupg.agent = { + enable = true; + }; + }; + + fonts.packages = with pkgs; [ + font-awesome + noto-fonts + noto-fonts-cjk + noto-fonts-emoji + noto-fonts-extra + dejavu_fonts + powerline-fonts + source-code-pro + cantarell-fonts + ]; + + users = { + mutableUsers = false; + + users = { + user = { + isNormalUser = true; + group = "user"; + extraGroups = [ + "wheel" + "video" + "audio" + "dialout" + "users" + "kvm" + "wireshark" + ]; + password = "unimportant"; + }; + }; + + groups = { + user = { }; + }; + }; + + security = { + pam.loginLimits = [ + { + domain = "@audio"; + item = "memlock"; + type = "-"; + value = "unlimited"; + } + { + domain = "@audio"; + item = "rtprio"; + type = "-"; + value = "99"; + } + { + domain = "@audio"; + item = "nofile"; + type = "soft"; + value = "99999"; + } + { + domain = "@audio"; + item = "nofile"; + type = "hard"; + value = "99999"; + } + ]; + + sudo.extraRules = [ + { + users = [ "user" ]; + commands = [ + { + command = "${pkgs.linuxPackages.cpupower}/bin/cpupower"; + options = [ "NOPASSWD" ]; + } + ]; + } + ]; + }; + + environment.systemPackages = with pkgs; [ + a2jmidid + age + ardour + bemenu + blender + breeze-icons + breeze-qt5 + bubblewrap + calf + claws-mail + darktable + duperemove + emacs + feh + file + firefox + fluidsynth + gnome3.adwaita-icon-theme + gnuplot + graphviz + helm + i3status-rust + inkscape + jack2 + jq + krita + ldns + libqalculate + libreoffice + man-pages + nheko + nix-diff + nix-index + nix-output-monitor + open-music-kontrollers.patchmatrix + pamixer + pavucontrol + pciutils + picom + pwgen + redshift + ripgrep + rlwrap + silver-searcher + soundfont-fluid + whois + wol + xclip + xdot + xdotool + xorg.xkbcomp + yt-dlp + zathura + borgbackup + linuxPackages.cpupower + mtr + kitty + xf86_input_wacom + ]; + + environment.pathsToLink = [ "/share/soundfonts" ]; + + systemd.user.services.run-python = { + after = [ "network-online.target" ]; + script = '' + exec ${pkgs.python3}/bin/python + ''; + serviceConfig = { + CapabilityBoundingSet = [ "" ]; + KeyringMode = "private"; + LockPersonality = true; + MemoryDenyWriteExecute = true; + NoNewPrivileges = true; + PrivateDevices = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; + ProtectControlGroups = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectProc = "invisible"; + ProtectSystem = "strict"; + RestrictAddressFamilies = "AF_INET AF_INET6"; + RestrictNamespaces = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + SystemCallArchitectures = "native"; + SystemCallFilter = [ + "@system-service" + "~ @resources @privileged" + ]; + UMask = "077"; + }; + }; + + system.stateVersion = "23.11"; +} diff --git a/bench/summarize.jq b/bench/summarize.jq new file mode 100755 index 000000000..5d1449108 --- /dev/null +++ b/bench/summarize.jq @@ -0,0 +1,22 @@ +#!/usr/bin/env -S jq -Mrf + +def round3: + . * 1000 | round | . / 1000 + ; + +def stats($first): + [ + " mean: \(.mean | round3)s ± \(.stddev | round3)s", + " user: \(.user | round3)s | system: \(.system | round3)s", + " median: \(.median | round3)s", + " range: \(.min | round3)s ... \(.max | round3)s", + " relative: \(.mean / $first.mean | round3)" + ] + | join("\n") + ; + +def fmt($first): + "\(.command)\n" + (. | stats($first)) + ; + +[.results | .[0] as $first | .[] | fmt($first)] | join("\n\n") | (. + "\n\n---\n") diff --git a/default.nix b/default.nix index 2cccff28d..6466507b7 100644 --- a/default.nix +++ b/default.nix @@ -1,10 +1,9 @@ -(import - ( - let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in - fetchTarball { - url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; - sha256 = lock.nodes.flake-compat.locked.narHash; - } - ) - { src = ./.; } -).defaultNix +(import ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } +) { src = ./.; }).defaultNix diff --git a/doc/manual/book.toml b/doc/manual/book.toml index 1d14347a4..e03bed737 100644 --- a/doc/manual/book.toml +++ b/doc/manual/book.toml @@ -15,6 +15,7 @@ command = "python3 doc/manual/docroot.py" # the link preprocessor gets its hands on this book, but nope it's actually # the opposite. after = ["links"] +before = ["anchors"] [preprocessor.anchors] renderers = ["html"] diff --git a/doc/manual/generate-builtin-constants.nix b/doc/manual/generate-builtin-constants.nix index 8af80a02c..23ec2cb55 100644 --- a/doc/manual/generate-builtin-constants.nix +++ b/doc/manual/generate-builtin-constants.nix @@ -5,7 +5,13 @@ in builtinsInfo: let - showBuiltin = name: { doc, type, impure-only }: + showBuiltin = + name: + { + doc, + type, + impure-only, + }: let type' = optionalString (type != null) " (${type})"; diff --git a/doc/manual/generate-builtins.nix b/doc/manual/generate-builtins.nix index 813a287f5..60cba266b 100644 --- a/doc/manual/generate-builtins.nix +++ b/doc/manual/generate-builtins.nix @@ -5,7 +5,14 @@ in builtinsInfo: let - showBuiltin = name: { doc, args, arity, experimental-feature }: + showBuiltin = + name: + { + doc, + args, + arity, + experimental-feature, + }: let experimentalNotice = optionalString (experimental-feature != null) '' This function is only available if the [${experimental-feature}](@docroot@/contributing/experimental-features.md#xp-feature-${experimental-feature}) experimental feature is enabled. diff --git a/doc/manual/generate-manpage.nix b/doc/manual/generate-manpage.nix index 972def69a..5c6a2a48a 100644 --- a/doc/manual/generate-manpage.nix +++ b/doc/manual/generate-manpage.nix @@ -1,8 +1,26 @@ let inherit (builtins) - attrNames attrValues fromJSON listToAttrs mapAttrs - concatStringsSep concatMap length lessThan replaceStrings sort; - inherit (import ./utils.nix) concatStrings optionalString filterAttrs trim squash unique showSettings; + attrNames + attrValues + fromJSON + listToAttrs + mapAttrs + concatStringsSep + concatMap + length + lessThan + replaceStrings + sort + ; + inherit (import ./utils.nix) + concatStrings + optionalString + filterAttrs + trim + squash + unique + showSettings + ; in inlineHTML: commandDump: @@ -11,7 +29,13 @@ let commandInfo = fromJSON commandDump; - showCommand = { command, details, filename, toplevel }: + showCommand = + { + command, + details, + filename, + toplevel, + }: let result = '' @@ -35,26 +59,27 @@ let ${maybeOptions} ''; - showSynopsis = command: args: + showSynopsis = + command: args: let - showArgument = arg: "*${arg.label}*" + optionalString (! arg ? arity) "..."; + showArgument = arg: "*${arg.label}*" + optionalString (!arg ? arity) "..."; arguments = concatStringsSep " " (map showArgument args); - in '' - `${command}` [*option*...] ${arguments} + in + '' + `${command}` [*option*...] ${arguments} ''; - maybeSubcommands = optionalString (details ? commands && details.commands != {}) - '' - where *subcommand* is one of the following: + maybeSubcommands = optionalString (details ? commands && details.commands != { }) '' + where *subcommand* is one of the following: - ${subcommands} - ''; + ${subcommands} + ''; - subcommands = if length categories > 1 - then listCategories - else listSubcommands details.commands; + subcommands = if length categories > 1 then listCategories else listSubcommands details.commands; - categories = sort (x: y: x.id < y.id) (unique (map (cmd: cmd.category) (attrValues details.commands))); + categories = sort (x: y: x.id < y.id) ( + unique (map (cmd: cmd.category) (attrValues details.commands)) + ); listCategories = concatStrings (map showCategory categories); @@ -71,11 +96,11 @@ let ''; # TODO: move this confusing special case out of here when implementing #8496 - maybeStoreDocs = optionalString - (details ? doc) - (replaceStrings ["@stores@"] [storeDocs] details.doc); + maybeStoreDocs = optionalString (details ? doc) ( + replaceStrings [ "@stores@" ] [ storeDocs ] details.doc + ); - maybeOptions = optionalString (details.flags != {}) '' + maybeOptions = optionalString (details.flags != { }) '' # Options ${showOptions details.flags toplevel.flags} @@ -85,51 +110,70 @@ let > See [`man nix.conf`](@docroot@/command-ref/conf-file.md#command-line-flags) for overriding configuration settings with command line flags. ''; - showOptions = options: commonOptions: + showOptions = + options: commonOptions: let allOptions = options // commonOptions; showCategory = cat: '' ${optionalString (cat != "") "**${cat}:**"} ${listOptions (filterAttrs (n: v: v.category == cat) allOptions)} - ''; + ''; listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts)); - showOption = name: option: + showOption = + name: option: let result = trim '' - ${item} ${option.description} ''; - item = if inlineHTML - then ''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}'' - else "`--${name}` ${shortName} ${labels}"; - shortName = optionalString - (option ? shortName) - ("/ `-${option.shortName}`"); - labels = optionalString - (option ? labels) - (concatStringsSep " " (map (s: "*${s}*") option.labels)); - in result; + item = + if inlineHTML then + ''<span id="opt-${name}">[`--${name}`](#opt-${name})</span> ${shortName} ${labels}'' + else + "`--${name}` ${shortName} ${labels}"; + shortName = optionalString (option ? shortName) ("/ `-${option.shortName}`"); + labels = optionalString (option ? labels) (concatStringsSep " " (map (s: "*${s}*") option.labels)); + in + result; categories = sort lessThan (unique (map (cmd: cmd.category) (attrValues allOptions))); - in concatStrings (map showCategory categories); - in squash result; + in + concatStrings (map showCategory categories); + in + squash result; appendName = filename: name: (if filename == "nix" then "nix3" else filename) + "-" + name; - processCommand = { command, details, filename, toplevel }: + processCommand = + { + command, + details, + filename, + toplevel, + }: let cmd = { inherit command; name = filename + ".md"; - value = showCommand { inherit command details filename toplevel; }; - }; - subcommand = subCmd: processCommand { - command = command + " " + subCmd; - details = details.commands.${subCmd}; - filename = appendName filename subCmd; - inherit toplevel; + value = showCommand { + inherit + command + details + filename + toplevel + ; + }; }; - in [ cmd ] ++ concatMap subcommand (attrNames details.commands or {}); + subcommand = + subCmd: + processCommand { + command = command + " " + subCmd; + details = details.commands.${subCmd}; + filename = appendName filename subCmd; + inherit toplevel; + }; + in + [ cmd ] ++ concatMap subcommand (attrNames details.commands or { }); manpages = processCommand { command = "nix"; @@ -138,14 +182,15 @@ let toplevel = commandInfo.args; }; - tableOfContents = let - showEntry = page: - " - [${page.command}](command-ref/new-cli/${page.name})"; - in concatStringsSep "\n" (map showEntry manpages) + "\n"; - storeDocs = let - showStore = name: { settings, doc, experimentalFeature }: + showStore = + name: + { + settings, + doc, + experimentalFeature, + }: let experimentalFeatureNote = optionalString (experimentalFeature != null) '' > **Warning** @@ -161,7 +206,8 @@ let extra-experimental-features = ${experimentalFeature} ``` ''; - in '' + in + '' ## ${name} ${doc} @@ -172,6 +218,7 @@ let ${showSettings { inherit inlineHTML; } settings} ''; - in concatStrings (attrValues (mapAttrs showStore commandInfo.stores)); - -in (listToAttrs manpages) // { "SUMMARY.md" = tableOfContents; } + in + concatStrings (attrValues (mapAttrs showStore commandInfo.stores)); +in +listToAttrs manpages diff --git a/doc/manual/generate-xp-features-shortlist.nix b/doc/manual/generate-xp-features-shortlist.nix index 30e211c96..ea8bf8d49 100644 --- a/doc/manual/generate-xp-features-shortlist.nix +++ b/doc/manual/generate-xp-features-shortlist.nix @@ -2,8 +2,8 @@ with builtins; with import ./utils.nix; let - showExperimentalFeature = name: doc: - '' - - [`${name}`](@docroot@/contributing/experimental-features.md#xp-feature-${name}) - ''; -in xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) + showExperimentalFeature = name: doc: '' + - [`${name}`](@docroot@/contributing/experimental-features.md#xp-feature-${name}) + ''; +in +xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/generate-xp-features.nix b/doc/manual/generate-xp-features.nix index adb94355c..c56ddeea1 100644 --- a/doc/manual/generate-xp-features.nix +++ b/doc/manual/generate-xp-features.nix @@ -2,10 +2,12 @@ with builtins; with import ./utils.nix; let - showExperimentalFeature = name: doc: + showExperimentalFeature = + name: doc: squash '' ## [`${name}`]{#xp-feature-${name}} ${doc} ''; -in xps: (concatStringsSep "\n" (attrValues (mapAttrs showExperimentalFeature xps))) +in +xps: (concatStringsSep "\n" (attrValues (mapAttrs showExperimentalFeature xps))) diff --git a/doc/manual/local.mk b/doc/manual/local.mk index e7c029727..13ab6da2f 100644 --- a/doc/manual/local.mk +++ b/doc/manual/local.mk @@ -60,10 +60,6 @@ $(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md $(d)/nix-profiles.5: $(d)/src/command-ref/files/profiles.md $(trace-gen) doc/manual/render-manpage.sh "$$(basename $@ .5)" 5 $^ $^.tmp $@ -$(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/SUMMARY-rl-next.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md - @cp $< $@ - @doc/manual/process-includes.sh $@ $@ - $(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(doc_nix) @rm -rf $@ $@.tmp $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' @@ -113,7 +109,7 @@ $(d)/language.json: $(doc_nix) @mv $@.tmp $@ # Generate "Upcoming release" notes (or clear it and remove from menu) -$(d)/src/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* +$(d)/src/release-notes/rl-next-generated.md: $(d)/rl-next $(d)/rl-next/* @if type -p build-release-notes > /dev/null; then \ echo " GEN " $@; \ build-release-notes doc/manual/rl-next > $@; \ @@ -122,14 +118,6 @@ $(d)/src/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* true > $@; \ fi -$(d)/src/SUMMARY-rl-next.md: $(d)/src/release-notes/rl-next.md - $(trace-gen) true - @if [ -s $< ]; then \ - echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ - else \ - true > $@; \ - fi - # Generate the HTML manual. .PHONY: manual-html manual-html: $(docdir)/manual/index.html @@ -159,19 +147,15 @@ doc/manual/generated/man1/nix3-manpages: $(d)/src/command-ref/new-cli done @touch $@ -$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/language/builtin-constants.md $(d)/src/release-notes/rl-next.md $(d)/docroot.py +doc/manual/generated/out: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/src/SUMMARY.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md $(d)/src/command-ref/conf-file.md $(d)/src/language/builtins.md $(d)/src/language/builtin-constants.md $(d)/src/release-notes/rl-next-generated.md $(d)/docroot.py + @rm -rf $@ $(trace-gen) \ - tmp="$$(mktemp -d)"; \ - cp -r doc/manual "$$tmp"; \ - find "$$tmp" -name '*.md' | while read -r file; do \ - doc/manual/process-includes.sh $$file $$file; \ - done; \ - set -euo pipefail; \ - RUST_LOG=warn mdbook build "$$tmp/manual" -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ - | { grep -Fv "because fragment resolution isn't implemented" || :; }; \ - rm -rf "$$tmp/manual" + RUST_LOG=warn mdbook build doc/manual -d generated/out 2>&1 \ + | { grep -Fv "because fragment resolution isn't implemented" || :; } + +$(docdir)/manual/index.html: doc/manual/generated/out + @mkdir -p $(DESTDIR)$(docdir) @rm -rf $(DESTDIR)$(docdir)/manual - @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual - @rm -rf $(DESTDIR)$(docdir)/manual.tmp + @cp -r $</html $(DESTDIR)$(docdir)/manual endif diff --git a/doc/manual/rl-next/new-assertions.md b/doc/manual/rl-next/new-assertions.md new file mode 100644 index 000000000..efaaeb306 --- /dev/null +++ b/doc/manual/rl-next/new-assertions.md @@ -0,0 +1,23 @@ +--- +synopsis: Lix turns more internal bugs into crashes +cls: [797, 626] +--- + +Lix now enables build options such as trapping on signed overflow and enabling +libstdc++ assertions by default. These may find new bugs in Lix, which will +present themselves as Lix processes aborting, potentially without an error +message. + +If Lix processes abort on your machine, this is a bug. Please file a bug, +ideally with the core dump (or information from it). + +On Linux, run `coredumpctl list`, find the crashed process's PID at +the bottom of the list, then run `coredumpctl info THE-PID`. You can then paste +the output into a bug report. + +On macOS, open the Console app from Applications/Utilities, select Crash +Reports, select the crash report in question. Right click on it, select Open In +Finder, then include that file in your bug report. [See the Apple +documentation][apple-crashreport] for more details. + +[apple-crashreport]: https://developer.apple.com/documentation/xcode/acquiring-crash-reports-and-diagnostic-logs#Locate-crash-reports-and-memory-logs-on-the-device diff --git a/doc/manual/src/SUMMARY.md.in b/doc/manual/src/SUMMARY.md index acb87cc01..7747b9061 100644 --- a/doc/manual/src/SUMMARY.md.in +++ b/doc/manual/src/SUMMARY.md @@ -88,7 +88,92 @@ - [nix-instantiate](command-ref/nix-instantiate.md) - [nix-prefetch-url](command-ref/nix-prefetch-url.md) - [Experimental Commands](command-ref/experimental-commands.md) -{{#include ./command-ref/new-cli/SUMMARY.md}} + - [nix](command-ref/new-cli/nix.md) + - [nix build](command-ref/new-cli/nix3-build.md) + - [nix bundle](command-ref/new-cli/nix3-bundle.md) + - [nix copy](command-ref/new-cli/nix3-copy.md) + - [nix daemon](command-ref/new-cli/nix3-daemon.md) + - [nix derivation](command-ref/new-cli/nix3-derivation.md) + - [nix derivation add](command-ref/new-cli/nix3-derivation-add.md) + - [nix derivation show](command-ref/new-cli/nix3-derivation-show.md) + - [nix develop](command-ref/new-cli/nix3-develop.md) + - [nix doctor](command-ref/new-cli/nix3-doctor.md) + - [nix edit](command-ref/new-cli/nix3-edit.md) + - [nix eval](command-ref/new-cli/nix3-eval.md) + - [nix flake](command-ref/new-cli/nix3-flake.md) + - [nix flake archive](command-ref/new-cli/nix3-flake-archive.md) + - [nix flake check](command-ref/new-cli/nix3-flake-check.md) + - [nix flake clone](command-ref/new-cli/nix3-flake-clone.md) + - [nix flake info](command-ref/new-cli/nix3-flake-info.md) + - [nix flake init](command-ref/new-cli/nix3-flake-init.md) + - [nix flake lock](command-ref/new-cli/nix3-flake-lock.md) + - [nix flake metadata](command-ref/new-cli/nix3-flake-metadata.md) + - [nix flake new](command-ref/new-cli/nix3-flake-new.md) + - [nix flake prefetch](command-ref/new-cli/nix3-flake-prefetch.md) + - [nix flake show](command-ref/new-cli/nix3-flake-show.md) + - [nix flake update](command-ref/new-cli/nix3-flake-update.md) + - [nix fmt](command-ref/new-cli/nix3-fmt.md) + - [nix hash](command-ref/new-cli/nix3-hash.md) + - [nix hash file](command-ref/new-cli/nix3-hash-file.md) + - [nix hash path](command-ref/new-cli/nix3-hash-path.md) + - [nix hash to-base16](command-ref/new-cli/nix3-hash-to-base16.md) + - [nix hash to-base32](command-ref/new-cli/nix3-hash-to-base32.md) + - [nix hash to-base64](command-ref/new-cli/nix3-hash-to-base64.md) + - [nix hash to-sri](command-ref/new-cli/nix3-hash-to-sri.md) + - [nix help](command-ref/new-cli/nix3-help.md) + - [nix help-stores](command-ref/new-cli/nix3-help-stores.md) + - [nix key](command-ref/new-cli/nix3-key.md) + - [nix key convert-secret-to-public](command-ref/new-cli/nix3-key-convert-secret-to-public.md) + - [nix key generate-secret](command-ref/new-cli/nix3-key-generate-secret.md) + - [nix log](command-ref/new-cli/nix3-log.md) + - [nix nar](command-ref/new-cli/nix3-nar.md) + - [nix nar cat](command-ref/new-cli/nix3-nar-cat.md) + - [nix nar dump-path](command-ref/new-cli/nix3-nar-dump-path.md) + - [nix nar ls](command-ref/new-cli/nix3-nar-ls.md) + - [nix path-info](command-ref/new-cli/nix3-path-info.md) + - [nix print-dev-env](command-ref/new-cli/nix3-print-dev-env.md) + - [nix profile](command-ref/new-cli/nix3-profile.md) + - [nix profile diff-closures](command-ref/new-cli/nix3-profile-diff-closures.md) + - [nix profile history](command-ref/new-cli/nix3-profile-history.md) + - [nix profile install](command-ref/new-cli/nix3-profile-install.md) + - [nix profile list](command-ref/new-cli/nix3-profile-list.md) + - [nix profile remove](command-ref/new-cli/nix3-profile-remove.md) + - [nix profile rollback](command-ref/new-cli/nix3-profile-rollback.md) + - [nix profile upgrade](command-ref/new-cli/nix3-profile-upgrade.md) + - [nix profile wipe-history](command-ref/new-cli/nix3-profile-wipe-history.md) + - [nix realisation](command-ref/new-cli/nix3-realisation.md) + - [nix realisation info](command-ref/new-cli/nix3-realisation-info.md) + - [nix registry](command-ref/new-cli/nix3-registry.md) + - [nix registry add](command-ref/new-cli/nix3-registry-add.md) + - [nix registry list](command-ref/new-cli/nix3-registry-list.md) + - [nix registry pin](command-ref/new-cli/nix3-registry-pin.md) + - [nix registry remove](command-ref/new-cli/nix3-registry-remove.md) + - [nix repl](command-ref/new-cli/nix3-repl.md) + - [nix run](command-ref/new-cli/nix3-run.md) + - [nix search](command-ref/new-cli/nix3-search.md) + - [nix shell](command-ref/new-cli/nix3-shell.md) + - [nix show-config](command-ref/new-cli/nix3-show-config.md) + - [nix store](command-ref/new-cli/nix3-store.md) + - [nix store add-file](command-ref/new-cli/nix3-store-add-file.md) + - [nix store add-path](command-ref/new-cli/nix3-store-add-path.md) + - [nix store cat](command-ref/new-cli/nix3-store-cat.md) + - [nix store copy-log](command-ref/new-cli/nix3-store-copy-log.md) + - [nix store copy-sigs](command-ref/new-cli/nix3-store-copy-sigs.md) + - [nix store delete](command-ref/new-cli/nix3-store-delete.md) + - [nix store diff-closures](command-ref/new-cli/nix3-store-diff-closures.md) + - [nix store dump-path](command-ref/new-cli/nix3-store-dump-path.md) + - [nix store gc](command-ref/new-cli/nix3-store-gc.md) + - [nix store ls](command-ref/new-cli/nix3-store-ls.md) + - [nix store make-content-addressed](command-ref/new-cli/nix3-store-make-content-addressed.md) + - [nix store optimise](command-ref/new-cli/nix3-store-optimise.md) + - [nix store path-from-hash-part](command-ref/new-cli/nix3-store-path-from-hash-part.md) + - [nix store ping](command-ref/new-cli/nix3-store-ping.md) + - [nix store prefetch-file](command-ref/new-cli/nix3-store-prefetch-file.md) + - [nix store repair](command-ref/new-cli/nix3-store-repair.md) + - [nix store sign](command-ref/new-cli/nix3-store-sign.md) + - [nix store verify](command-ref/new-cli/nix3-store-verify.md) + - [nix upgrade-nix](command-ref/new-cli/nix3-upgrade-nix.md) + - [nix why-depends](command-ref/new-cli/nix3-why-depends.md) - [Files](command-ref/files.md) - [nix.conf](command-ref/conf-file.md) - [Profiles](command-ref/files/profiles.md) @@ -109,7 +194,7 @@ - [CLI guideline](contributing/cli-guideline.md) - [C++ style guide](contributing/cxx.md) - [Release Notes](release-notes/release-notes.md) -{{#include ./SUMMARY-rl-next.md}} + - [Upcoming release](release-notes/rl-next.md) - [Release 2.18 (2023-09-20)](release-notes/rl-2.18.md) - [Release 2.17 (2023-07-24)](release-notes/rl-2.17.md) - [Release 2.16 (2023-05-31)](release-notes/rl-2.16.md) diff --git a/doc/manual/src/command-ref/conf-file-prefix.md b/doc/manual/src/command-ref/conf-file-prefix.md index 181fa5040..822777eff 100644 --- a/doc/manual/src/command-ref/conf-file-prefix.md +++ b/doc/manual/src/command-ref/conf-file-prefix.md @@ -17,7 +17,7 @@ By default Nix reads settings from the following places, in that order: 1. If [`NIX_USER_CONF_FILES`](./env-common.md#env-NIX_USER_CONF_FILES) is set, then each path separated by `:` will be loaded in reverse order. - Otherwise it will look for `nix/nix.conf` files in `XDG_CONFIG_DIRS` and [`XDG_CONFIG_HOME`](./env-common.md#env-XDG_CONFIG_HOME). + Otherwise it will look for `nix/nix.conf` files in `XDG_CONFIG_DIRS` and `XDG_CONFIG_HOME`. If unset, `XDG_CONFIG_DIRS` defaults to `/etc/xdg`, and `XDG_CONFIG_HOME` defaults to `$HOME/.config` as per [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html). 1. If [`NIX_CONFIG`](./env-common.md#env-NIX_CONFIG) is set, its contents are treated as the contents of a configuration file. diff --git a/doc/manual/src/command-ref/env-common.md b/doc/manual/src/command-ref/env-common.md index b4a9bb2a9..3de8ba9eb 100644 --- a/doc/manual/src/command-ref/env-common.md +++ b/doc/manual/src/command-ref/env-common.md @@ -115,9 +115,9 @@ For backwards compatibility, Nix commands will follow the standard only when [`u The following environment variables are used to determine locations of various state and configuration files: -- [`XDG_CONFIG_HOME`]{#env-XDG_CONFIG_HOME} (default `~/.config`) -- [`XDG_STATE_HOME`]{#env-XDG_STATE_HOME} (default `~/.local/state`) -- [`XDG_CACHE_HOME`]{#env-XDG_CACHE_HOME} (default `~/.cache`) +- `XDG_CONFIG_HOME` (default `~/.config`) +- `XDG_STATE_HOME` (default `~/.local/state`) +- `XDG_CACHE_HOME` (default `~/.cache`) [XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html diff --git a/doc/manual/src/release-notes/rl-next.md b/doc/manual/src/release-notes/rl-next.md new file mode 100644 index 000000000..35033f7b6 --- /dev/null +++ b/doc/manual/src/release-notes/rl-next.md @@ -0,0 +1,3 @@ +# Upcoming release + +{{#include rl-next-generated.md}} diff --git a/doc/manual/utils.nix b/doc/manual/utils.nix index 193c1efc0..17e6378eb 100644 --- a/doc/manual/utils.nix +++ b/doc/manual/utils.nix @@ -5,10 +5,15 @@ rec { concatStrings = concatStringsSep ""; - attrsToList = a: - map (name: { inherit name; value = a.${name}; }) (builtins.attrNames a); - - replaceStringsRec = from: to: string: + attrsToList = + a: + map (name: { + inherit name; + value = a.${name}; + }) (builtins.attrNames a); + + replaceStringsRec = + from: to: string: # recursively replace occurrences of `from` with `to` within `string` # example: # replaceStringRec "--" "-" "hello-----world" @@ -16,14 +21,16 @@ rec { let replaced = replaceStrings [ from ] [ to ] string; in - if replaced == string then string else replaceStringsRec from to replaced; + if replaced == string then string else replaceStringsRec from to replaced; squash = replaceStringsRec "\n\n\n" "\n\n"; - trim = string: + trim = + string: # trim trailing spaces and squash non-leading spaces let - trimLine = line: + trimLine = + line: let # separate leading spaces from the rest parts = split "(^ *)" line; @@ -31,76 +38,102 @@ rec { rest = elemAt parts 2; # drop trailing spaces body = head (split " *$" rest); - in spaces + replaceStringsRec " " " " body; - in concatStringsSep "\n" (map trimLine (splitLines string)); + in + spaces + replaceStringsRec " " " " body; + in + concatStringsSep "\n" (map trimLine (splitLines string)); # FIXME: O(n^2) - unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) []; + unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [ ]; nameValuePair = name: value: { inherit name value; }; - filterAttrs = pred: set: - listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set)); + filterAttrs = + pred: set: + listToAttrs ( + concatMap ( + name: + let + v = set.${name}; + in + if pred name v then [ (nameValuePair name v) ] else [ ] + ) (attrNames set) + ); optionalString = cond: string: if cond then string else ""; - showSetting = { inlineHTML }: name: { description, documentDefault, defaultValue, aliases, value, experimentalFeature }: + showSetting = + { inlineHTML }: + name: + { + description, + documentDefault, + defaultValue, + aliases, + value, + experimentalFeature, + }: let result = squash '' - - ${if inlineHTML - then ''<span id="conf-${name}">[`${name}`](#conf-${name})</span>'' - else ''`${name}`''} + - ${ + if inlineHTML then ''<span id="conf-${name}">[`${name}`](#conf-${name})</span>'' else ''`${name}`'' + } - ${indent " " body} - ''; + ${indent " " body} + ''; experimentalFeatureNote = optionalString (experimentalFeature != null) '' - > **Warning** - > This setting is part of an - > [experimental feature](@docroot@/contributing/experimental-features.md). + > **Warning** + > This setting is part of an + > [experimental feature](@docroot@/contributing/experimental-features.md). - To change this setting, you need to make sure the corresponding experimental feature, - [`${experimentalFeature}`](@docroot@/contributing/experimental-features.md#xp-feature-${experimentalFeature}), - is enabled. - For example, include the following in [`nix.conf`](#): + To change this setting, you need to make sure the corresponding experimental feature, + [`${experimentalFeature}`](@docroot@/contributing/experimental-features.md#xp-feature-${experimentalFeature}), + is enabled. + For example, include the following in [`nix.conf`](#): - ``` - extra-experimental-features = ${experimentalFeature} - ${name} = ... - ``` - ''; + ``` + extra-experimental-features = ${experimentalFeature} + ${name} = ... + ``` + ''; # separate body to cleanly handle indentation body = '' - ${description} + ${description} - ${experimentalFeatureNote} + ${experimentalFeatureNote} - **Default:** ${showDefault documentDefault defaultValue} + **Default:** ${showDefault documentDefault defaultValue} - ${showAliases aliases} - ''; + ${showAliases aliases} + ''; - showDefault = documentDefault: defaultValue: + showDefault = + documentDefault: defaultValue: if documentDefault then # a StringMap value type is specified as a string, but # this shows the value type. The empty stringmap is `null` in # JSON, but that converts to `{ }` here. - if defaultValue == "" || defaultValue == [] || isAttrs defaultValue - then "*empty*" - else if isBool defaultValue then - if defaultValue then "`true`" else "`false`" - else "`${toString defaultValue}`" - else "*machine-specific*"; - - showAliases = aliases: - optionalString (aliases != []) - "**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}"; - - in result; + if defaultValue == "" || defaultValue == [ ] || isAttrs defaultValue then + "*empty*" + else if isBool defaultValue then + if defaultValue then "`true`" else "`false`" + else + "`${toString defaultValue}`" + else + "*machine-specific*"; + + showAliases = + aliases: + optionalString (aliases != [ ]) + "**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}"; + in + result; - indent = prefix: s: - concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); + indent = + prefix: s: concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s)); - showSettings = args: settingsInfo: concatStrings (attrValues (mapAttrs (showSetting args) settingsInfo)); + showSettings = + args: settingsInfo: concatStrings (attrValues (mapAttrs (showSetting args) settingsInfo)); } diff --git a/docker.nix b/docker.nix index bd16b71cd..2d57cd548 100644 --- a/docker.nix +++ b/docker.nix @@ -1,70 +1,71 @@ -{ pkgs ? import <nixpkgs> { } -, lib ? pkgs.lib -, name ? "nix" -, tag ? "latest" -, bundleNixpkgs ? true -, channelName ? "nixpkgs" -, channelURL ? "https://nixos.org/channels/nixpkgs-unstable" -, extraPkgs ? [] -, maxLayers ? 100 -, nixConf ? {} -, flake-registry ? null +{ + pkgs ? import <nixpkgs> { }, + lib ? pkgs.lib, + name ? "nix", + tag ? "latest", + bundleNixpkgs ? true, + channelName ? "nixpkgs", + channelURL ? "https://nixos.org/channels/nixpkgs-unstable", + extraPkgs ? [ ], + maxLayers ? 100, + nixConf ? { }, + flake-registry ? null, }: let - defaultPkgs = with pkgs; [ - nix - bashInteractive - coreutils-full - gnutar - gzip - gnugrep - which - curl - less - wget - man - cacert.out - findutils - iana-etc - git - openssh - ] ++ extraPkgs; - - users = { - - root = { - uid = 0; - shell = "${pkgs.bashInteractive}/bin/bash"; - home = "/root"; - gid = 0; - groups = [ "root" ]; - description = "System administrator"; - }; - - nobody = { - uid = 65534; - shell = "${pkgs.shadow}/bin/nologin"; - home = "/var/empty"; - gid = 65534; - groups = [ "nobody" ]; - description = "Unprivileged account (don't use!)"; - }; + defaultPkgs = + with pkgs; + [ + nix + bashInteractive + coreutils-full + gnutar + gzip + gnugrep + which + curl + less + wget + man + cacert.out + findutils + iana-etc + git + openssh + ] + ++ extraPkgs; + + users = + { + + root = { + uid = 0; + shell = "${pkgs.bashInteractive}/bin/bash"; + home = "/root"; + gid = 0; + groups = [ "root" ]; + description = "System administrator"; + }; - } // lib.listToAttrs ( - map - ( - n: { - name = "nixbld${toString n}"; - value = { - uid = 30000 + n; - gid = 30000; - groups = [ "nixbld" ]; - description = "Nix build user ${toString n}"; - }; - } - ) - (lib.lists.range 1 32) - ); + nobody = { + uid = 65534; + shell = "${pkgs.shadow}/bin/nologin"; + home = "/var/empty"; + gid = 65534; + groups = [ "nobody" ]; + description = "Unprivileged account (don't use!)"; + }; + } + // lib.listToAttrs ( + map (n: { + name = "nixbld${toString n}"; + value = { + uid = 30000 + n; + gid = 30000; + groups = [ "nixbld" ]; + description = "Nix build user ${toString n}"; + }; + }) (lib.lists.range 1 32) + ); groups = { root.gid = 0; @@ -74,24 +75,20 @@ let userToPasswd = ( k: - { uid - , gid ? 65534 - , home ? "/var/empty" - , description ? "" - , shell ? "/bin/false" - , groups ? [ ] - }: "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}" - ); - passwdContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs userToPasswd users)) + { + uid, + gid ? 65534, + home ? "/var/empty", + description ? "", + shell ? "/bin/false", + groups ? [ ], + }: + "${k}:x:${toString uid}:${toString gid}:${description}:${home}:${shell}" ); + passwdContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToPasswd users))); userToShadow = k: { ... }: "${k}:!:1::::::"; - shadowContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs userToShadow users)) - ); + shadowContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs userToShadow users))); # Map groups to members # { @@ -101,42 +98,28 @@ let let # Create a flat list of user/group mappings mappings = ( - builtins.foldl' - ( - acc: user: - let - groups = users.${user}.groups or [ ]; - in - acc ++ map - (group: { - inherit user group; - }) - groups - ) - [ ] - (lib.attrNames users) + builtins.foldl' ( + acc: user: + let + groups = users.${user}.groups or [ ]; + in + acc ++ map (group: { inherit user group; }) groups + ) [ ] (lib.attrNames users) ); in - ( - builtins.foldl' - ( - acc: v: acc // { - ${v.group} = acc.${v.group} or [ ] ++ [ v.user ]; - } - ) - { } - mappings) + (builtins.foldl' ( + acc: v: acc // { ${v.group} = acc.${v.group} or [ ] ++ [ v.user ]; } + ) { } mappings) ); - groupToGroup = k: { gid }: + groupToGroup = + k: + { gid }: let members = groupMemberMap.${k} or [ ]; in "${k}:x:${toString gid}:${lib.concatStringsSep "," members}"; - groupContents = ( - lib.concatStringsSep "\n" - (lib.attrValues (lib.mapAttrs groupToGroup groups)) - ); + groupContents = (lib.concatStringsSep "\n" (lib.attrValues (lib.mapAttrs groupToGroup groups))); defaultNixConf = { sandbox = "false"; @@ -144,11 +127,17 @@ let trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; }; - nixConfContents = (lib.concatStringsSep "\n" (lib.mapAttrsFlatten (n: v: - let - vStr = if builtins.isList v then lib.concatStringsSep " " v else v; - in - "${n} = ${vStr}") (defaultNixConf // nixConf))) + "\n"; + nixConfContents = + (lib.concatStringsSep "\n" ( + lib.mapAttrsFlatten ( + n: v: + let + vStr = if builtins.isList v then lib.concatStringsSep " " v else v; + in + "${n} = ${vStr}" + ) (defaultNixConf // nixConf) + )) + + "\n"; baseSystem = let @@ -167,21 +156,31 @@ let manifest = pkgs.buildPackages.runCommand "manifest.nix" { } '' cat > $out <<EOF [ - ${lib.concatStringsSep "\n" (builtins.map (drv: let - outputs = drv.outputsToInstall or [ "out" ]; - in '' - { - ${lib.concatStringsSep "\n" (builtins.map (output: '' - ${output} = { outPath = "${lib.getOutput output drv}"; }; - '') outputs)} - outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ]; - name = "${drv.name}"; - outPath = "${drv}"; - system = "${drv.system}"; - type = "derivation"; - meta = { }; - } - '') defaultPkgs)} + ${lib.concatStringsSep "\n" ( + builtins.map ( + drv: + let + outputs = drv.outputsToInstall or [ "out" ]; + in + '' + { + ${ + lib.concatStringsSep "\n" ( + builtins.map (output: '' + ${output} = { outPath = "${lib.getOutput output drv}"; }; + '') outputs + ) + } + outputs = [ ${lib.concatStringsSep " " (builtins.map (x: "\"${x}\"") outputs)} ]; + name = "${drv.name}"; + outPath = "${drv}"; + system = "${drv.system}"; + type = "derivation"; + meta = { }; + } + '' + ) defaultPkgs + )} ] EOF ''; @@ -190,16 +189,22 @@ let cp -a ${rootEnv}/* $out/ ln -s ${manifest} $out/manifest.nix ''; - flake-registry-path = if (flake-registry == null) then - null - else if (builtins.readFileType (toString flake-registry)) == "directory" then - "${flake-registry}/flake-registry.json" - else - flake-registry; + flake-registry-path = + if (flake-registry == null) then + null + else if (builtins.readFileType (toString flake-registry)) == "directory" then + "${flake-registry}/flake-registry.json" + else + flake-registry; in pkgs.runCommand "base-system" { - inherit passwdContents groupContents shadowContents nixConfContents; + inherit + passwdContents + groupContents + shadowContents + nixConfContents + ; passAsFile = [ "passwdContents" "groupContents" @@ -208,63 +213,66 @@ let ]; allowSubstitutes = false; preferLocalBuild = true; - } ('' - env - set -x - mkdir -p $out/etc - - mkdir -p $out/etc/ssl/certs - ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs + } + ( + '' + env + set -x + mkdir -p $out/etc - cat $passwdContentsPath > $out/etc/passwd - echo "" >> $out/etc/passwd + mkdir -p $out/etc/ssl/certs + ln -s /nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/certs - cat $groupContentsPath > $out/etc/group - echo "" >> $out/etc/group + cat $passwdContentsPath > $out/etc/passwd + echo "" >> $out/etc/passwd - cat $shadowContentsPath > $out/etc/shadow - echo "" >> $out/etc/shadow + cat $groupContentsPath > $out/etc/group + echo "" >> $out/etc/group - mkdir -p $out/usr - ln -s /nix/var/nix/profiles/share $out/usr/ + cat $shadowContentsPath > $out/etc/shadow + echo "" >> $out/etc/shadow - mkdir -p $out/nix/var/nix/gcroots + mkdir -p $out/usr + ln -s /nix/var/nix/profiles/share $out/usr/ - mkdir $out/tmp + mkdir -p $out/nix/var/nix/gcroots - mkdir -p $out/var/tmp + mkdir $out/tmp - mkdir -p $out/etc/nix - cat $nixConfContentsPath > $out/etc/nix/nix.conf + mkdir -p $out/var/tmp - mkdir -p $out/root - mkdir -p $out/nix/var/nix/profiles/per-user/root + mkdir -p $out/etc/nix + cat $nixConfContentsPath > $out/etc/nix/nix.conf - ln -s ${profile} $out/nix/var/nix/profiles/default-1-link - ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default - ln -s /nix/var/nix/profiles/default $out/root/.nix-profile + mkdir -p $out/root + mkdir -p $out/nix/var/nix/profiles/per-user/root - ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link - ln -s $out/nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels + ln -s ${profile} $out/nix/var/nix/profiles/default-1-link + ln -s $out/nix/var/nix/profiles/default-1-link $out/nix/var/nix/profiles/default + ln -s /nix/var/nix/profiles/default $out/root/.nix-profile - mkdir -p $out/root/.nix-defexpr - ln -s $out/nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels - echo "${channelURL} ${channelName}" > $out/root/.nix-channels + ln -s ${channel} $out/nix/var/nix/profiles/per-user/root/channels-1-link + ln -s $out/nix/var/nix/profiles/per-user/root/channels-1-link $out/nix/var/nix/profiles/per-user/root/channels - mkdir -p $out/bin $out/usr/bin - ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env - ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh + mkdir -p $out/root/.nix-defexpr + ln -s $out/nix/var/nix/profiles/per-user/root/channels $out/root/.nix-defexpr/channels + echo "${channelURL} ${channelName}" > $out/root/.nix-channels - '' + (lib.optionalString (flake-registry-path != null) '' - nixCacheDir="/root/.cache/nix" - mkdir -p $out$nixCacheDir - globalFlakeRegistryPath="$nixCacheDir/flake-registry.json" - ln -s ${flake-registry-path} $out$globalFlakeRegistryPath - mkdir -p $out/nix/var/nix/gcroots/auto - rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath)) - ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName - '')); + mkdir -p $out/bin $out/usr/bin + ln -s ${pkgs.coreutils}/bin/env $out/usr/bin/env + ln -s ${pkgs.bashInteractive}/bin/bash $out/bin/sh + '' + + (lib.optionalString (flake-registry-path != null) '' + nixCacheDir="/root/.cache/nix" + mkdir -p $out$nixCacheDir + globalFlakeRegistryPath="$nixCacheDir/flake-registry.json" + ln -s ${flake-registry-path} $out$globalFlakeRegistryPath + mkdir -p $out/nix/var/nix/gcroots/auto + rootName=$(${pkgs.nix}/bin/nix --extra-experimental-features nix-command hash file --type sha1 --base32 <(echo -n $globalFlakeRegistryPath)) + ln -s $globalFlakeRegistryPath $out/nix/var/nix/gcroots/auto/$rootName + '') + ); in pkgs.dockerTools.buildLayeredImageWithNixDb { @@ -285,20 +293,23 @@ pkgs.dockerTools.buildLayeredImageWithNixDb { Cmd = [ "/root/.nix-profile/bin/bash" ]; Env = [ "USER=root" - "PATH=${lib.concatStringsSep ":" [ - "/root/.nix-profile/bin" - "/nix/var/nix/profiles/default/bin" - "/nix/var/nix/profiles/default/sbin" - ]}" - "MANPATH=${lib.concatStringsSep ":" [ - "/root/.nix-profile/share/man" - "/nix/var/nix/profiles/default/share/man" - ]}" + "PATH=${ + lib.concatStringsSep ":" [ + "/root/.nix-profile/bin" + "/nix/var/nix/profiles/default/bin" + "/nix/var/nix/profiles/default/sbin" + ] + }" + "MANPATH=${ + lib.concatStringsSep ":" [ + "/root/.nix-profile/share/man" + "/nix/var/nix/profiles/default/share/man" + ] + }" "SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "GIT_SSL_CAINFO=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "NIX_SSL_CERT_FILE=/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt" "NIX_PATH=/nix/var/nix/profiles/per-user/root/channels:/root/.nix-defexpr/channels" ]; }; - } diff --git a/flake.lock b/flake.lock index f1f7828c0..269efc21a 100644 --- a/flake.lock +++ b/flake.lock @@ -16,45 +16,6 @@ "type": "github" } }, - "flake-utils": { - "inputs": { - "systems": "systems" - }, - "locked": { - "lastModified": 1710146030, - "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1711481231, @@ -88,25 +49,13 @@ } }, "pre-commit-hooks": { - "inputs": { - "flake-compat": [ - "flake-compat" - ], - "flake-utils": "flake-utils", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ], - "nixpkgs-stable": [ - "nixpkgs" - ] - }, + "flake": false, "locked": { - "lastModified": 1711981679, - "narHash": "sha256-pnbHEXJOdGkPrHBdkZLv/a2V09On+V3J4aPE/BfAJC8=", + "lastModified": 1712055707, + "narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "f3bb95498eaaa49a93bacaf196cdb6cf8e872cdf", + "rev": "e35aed5fda3cc79f88ed7f1795021e559582093a", "type": "github" }, "original": { @@ -122,21 +71,6 @@ "nixpkgs-regression": "nixpkgs-regression", "pre-commit-hooks": "pre-commit-hooks" } - }, - "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", @@ -6,16 +6,22 @@ nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2"; pre-commit-hooks = { url = "github:cachix/git-hooks.nix"; - inputs = { - flake-compat.follows = "flake-compat"; - nixpkgs.follows = "nixpkgs"; - nixpkgs-stable.follows = "nixpkgs"; - }; + flake = false; + }; + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; }; - flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; }; - outputs = { self, nixpkgs, nixpkgs-regression, pre-commit-hooks, flake-compat }: + outputs = + { + self, + nixpkgs, + nixpkgs-regression, + pre-commit-hooks, + flake-compat, + }: let inherit (nixpkgs) lib; @@ -27,70 +33,98 @@ version = lib.fileContents ./.version + versionSuffix; versionSuffix = - if officialRelease - then "" - else "pre${builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101")}_${self.shortRev or "dirty"}"; + if officialRelease then + "" + else + "pre${ + builtins.substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101") + }_${self.shortRev or "dirty"}"; linux32BitSystems = [ "i686-linux" ]; - linux64BitSystems = [ "x86_64-linux" "aarch64-linux" ]; + linux64BitSystems = [ + "x86_64-linux" + "aarch64-linux" + ]; linuxSystems = linux32BitSystems ++ linux64BitSystems; - darwinSystems = [ "x86_64-darwin" "aarch64-darwin" ]; + darwinSystems = [ + "x86_64-darwin" + "aarch64-darwin" + ]; systems = linuxSystems ++ darwinSystems; crossSystems = [ - "armv6l-linux" "armv7l-linux" - "x86_64-freebsd13" "x86_64-netbsd" + "armv6l-linux" + "armv7l-linux" + "x86_64-freebsd13" + "x86_64-netbsd" ]; - stdenvs = [ "gccStdenv" "clangStdenv" "stdenv" "libcxxStdenv" "ccacheStdenv" ]; + stdenvs = [ + "gccStdenv" + "clangStdenv" + "stdenv" + "libcxxStdenv" + "ccacheStdenv" + ]; forAllSystems = lib.genAttrs systems; forAllCrossSystems = lib.genAttrs crossSystems; - forAllStdenvs = f: - lib.listToAttrs - (map - (stdenvName: { - name = "${stdenvName}Packages"; - value = f stdenvName; - }) - stdenvs); + forAllStdenvs = + f: + lib.listToAttrs ( + map (stdenvName: { + name = "${stdenvName}Packages"; + value = f stdenvName; + }) stdenvs + ); # Memoize nixpkgs for different platforms for efficiency. - nixpkgsFor = forAllSystems - (system: let - make-pkgs = crossSystem: stdenv: import nixpkgs { - localSystem = { - inherit system; - }; - crossSystem = if crossSystem == null then null else { - system = crossSystem; - } // lib.optionalAttrs (crossSystem == "x86_64-freebsd13") { - useLLVM = true; - }; - overlays = [ - (overlayFor (p: p.${stdenv})) - ]; + nixpkgsFor = forAllSystems ( + system: + let + make-pkgs = + crossSystem: stdenv: + import nixpkgs { + localSystem = { + inherit system; + }; + crossSystem = + if crossSystem == null then + null + else + { + system = crossSystem; + } + // lib.optionalAttrs (crossSystem == "x86_64-freebsd13") { useLLVM = true; }; + overlays = [ + (overlayFor (p: p.${stdenv})) + (final: prev: { nixfmt = final.callPackage ./nix-support/nixfmt.nix { }; }) + ]; - config.permittedInsecurePackages = [ "nix-2.13.6" ]; - }; + config.permittedInsecurePackages = [ "nix-2.13.6" ]; + }; stdenvs = forAllStdenvs (make-pkgs null); native = stdenvs.stdenvPackages; - in { + in + { inherit stdenvs native; static = native.pkgsStatic; cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv"); - }); + } + ); - binaryTarball = nix: pkgs: + binaryTarball = + nix: pkgs: let inherit (pkgs) buildPackages; installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix ]; }; in buildPackages.runCommand "nix-binary-tarball-${version}" - { #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck; + { + #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck; meta.description = "Distribution-independent Nix bootstrap binaries for ${pkgs.system}"; } '' @@ -111,17 +145,19 @@ $(cat ${installerClosureInfo}/store-paths) ''; - overlayFor = getStdenv: final: prev: + overlayFor = + getStdenv: final: prev: let currentStdenv = getStdenv final; - in { + in + { nixStable = prev.nix; # Forward from the previous stage as we don’t want it to pick the lowdown override nixUnstable = prev.nixUnstable; - build-release-notes = - final.buildPackages.callPackage ./maintainers/build-release-notes.nix { }; + build-release-notes = final.buildPackages.callPackage ./maintainers/build-release-notes.nix { }; + check-headers = final.buildPackages.callPackage ./maintainers/check-headers.nix { }; clangbuildanalyzer = final.buildPackages.callPackage ./misc/clangbuildanalyzer.nix { }; default-busybox-sandbox-shell = final.busybox.override { @@ -158,8 +194,8 @@ # for consumers of this flake. boehmgc-nix = final.nix.boehmgc-nix; }; - - in { + in + { # A Nixpkgs overlay that overrides the 'nix' and # 'nix.perl-bindings' packages. overlays.default = overlayFor (p: p.stdenv); @@ -169,58 +205,67 @@ # Binary package for various platforms. build = forAllSystems (system: self.packages.${system}.nix); - rl-next = forAllSystems (system: + rl-next = forAllSystems ( + system: let - rl-next-check = name: dir: - let pkgs = nixpkgsFor.${system}.native; - in pkgs.buildPackages.runCommand "test-${name}-release-notes" { } '' - LANG=C.UTF-8 ${lib.getExe pkgs.build-release-notes} ${dir} >$out - ''; + rl-next-check = + name: dir: + let + pkgs = nixpkgsFor.${system}.native; + in + pkgs.buildPackages.runCommand "test-${name}-release-notes" { } '' + LANG=C.UTF-8 ${lib.getExe pkgs.build-release-notes} ${dir} >$out + ''; in - { - user = rl-next-check "rl-next" ./doc/manual/rl-next; - dev = rl-next-check "rl-next-dev" ./doc/manual/rl-next-dev; - }); + { + user = rl-next-check "rl-next" ./doc/manual/rl-next; + dev = rl-next-check "rl-next-dev" ./doc/manual/rl-next-dev; + } + ); # FIXME(Qyriad): remove this when the migration to Meson has been completed. # NOTE: mesonBuildClang depends on mesonBuild depends on build to avoid OOMs # on aarch64 builders caused by too many parallel compiler/linker processes. - mesonBuild = forAllSystems (system: - (self.packages.${system}.nix.override { - buildWithMeson = true; - }).overrideAttrs (prev: { + mesonBuild = forAllSystems ( + system: + (self.packages.${system}.nix.override { buildWithMeson = true; }).overrideAttrs (prev: { buildInputs = prev.buildInputs ++ [ self.packages.${system}.nix ]; - })); - mesonBuildClang = forAllSystems (system: - (nixpkgsFor.${system}.stdenvs.clangStdenvPackages.nix.override { - buildWithMeson = true; - }).overrideAttrs (prev: { - buildInputs = prev.buildInputs ++ [ self.hydraJobs.mesonBuild.${system} ]; }) ); + mesonBuildClang = forAllSystems ( + system: + (nixpkgsFor.${system}.stdenvs.clangStdenvPackages.nix.override { buildWithMeson = true; }) + .overrideAttrs + (prev: { + buildInputs = prev.buildInputs ++ [ self.hydraJobs.mesonBuild.${system} ]; + }) + ); # Perl bindings for various platforms. perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nix.perl-bindings); # Binary tarball for various platforms, containing a Nix store # with the closure of 'nix' package. - binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native); + binaryTarball = forAllSystems ( + system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native + ); # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); # API docs for Nix's unstable internal C++ interfaces. - internal-api-docs = let - nixpkgs = nixpkgsFor.x86_64-linux.native; - inherit (nixpkgs) pkgs; - - nix = pkgs.callPackage ./package.nix { - inherit versionSuffix officialRelease buildUnreleasedNotes; - inherit (pkgs) build-release-notes; - internalApiDocs = true; - busybox-sandbox-shell = pkgs.busybox-sandbox-shell; - }; - in + internal-api-docs = + let + nixpkgs = nixpkgsFor.x86_64-linux.native; + inherit (nixpkgs) pkgs; + + nix = pkgs.callPackage ./package.nix { + inherit versionSuffix officialRelease buildUnreleasedNotes; + inherit (pkgs) build-release-notes; + internalApiDocs = true; + busybox-sandbox-shell = pkgs.busybox-sandbox-shell; + }; + in nix.overrideAttrs (prev: { # This Hydra job is just for the internal API docs. # We don't need the build artifacts here. @@ -236,191 +281,272 @@ # on a particular version of Nixpkgs. evalNixpkgs = with nixpkgsFor.x86_64-linux.native; - runCommand "eval-nixos" { buildInputs = [ nix ]; } - '' - type -p nix-env - # Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593. - time nix-env --store dummy:// -f ${nixpkgs-regression} -qaP --drv-path | sort | grep -v nixos-install-tools > packages - [[ $(sha1sum < packages | cut -c1-40) = 402242fca90874112b34718b8199d844e8b03d12 ]] - mkdir $out - ''; + runCommand "eval-nixos" { buildInputs = [ nix ]; } '' + type -p nix-env + # Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593. + time nix-env --store dummy:// -f ${nixpkgs-regression} -qaP --drv-path | sort | grep -v nixos-install-tools > packages + [[ $(sha1sum < packages | cut -c1-40) = 402242fca90874112b34718b8199d844e8b03d12 ]] + mkdir $out + ''; - nixpkgsLibTests = - forAllSystems (system: - import (nixpkgs + "/lib/tests/release.nix") - { pkgs = nixpkgsFor.${system}.native; - nixVersions = [ self.packages.${system}.nix ]; - } - ); + nixpkgsLibTests = forAllSystems ( + system: + import (nixpkgs + "/lib/tests/release.nix") { + pkgs = nixpkgsFor.${system}.native; + nixVersions = [ self.packages.${system}.nix ]; + } + ); }; - pre-commit = builtins.mapAttrs (system: pre-commit-lib: pre-commit-lib.run { - src = self; - hooks = { - no-commit-to-branch = { - enable = true; - settings.branch = ["main"]; - }; - check-case-conflicts.enable = true; - check-executables-have-shebangs = { - enable = true; - stages = [ "commit" ]; - }; - check-shebang-scripts-are-executable = { - enable = true; - stages = [ "commit" ]; - }; - check-symlinks = { - enable = true; - excludes = [ "^tests/functional/lang/symlink-resolution/broken$" ]; - }; - check-merge-conflicts.enable = true; - end-of-file-fixer = { - enable = true; - excludes = [ - "\\.drv$" - "^tests/functional/lang/" - ]; - }; - mixed-line-endings = { - enable = true; - excludes = [ "^tests/functional/lang/" ]; - }; - # TODO: Once the test suite is nicer, clean up and start - # enforcing trailing whitespace on tests that don't explicitly - # check for it. - trim-trailing-whitespace = { - enable = true; - stages = [ "commit" ]; - excludes = [ "^tests/functional/lang/" ]; + pre-commit = forAllSystems ( + system: + let + pkgs = nixpkgsFor.${system}.native; + # Import pre-commit bypassing the flake because flakes don't let + # you have overlays. Also their implementation forces an + # unnecessary reimport of nixpkgs for our use cases. + tools = import (pre-commit-hooks + "/nix/call-tools.nix") pkgs; + pre-commit-run = pkgs.callPackage (pre-commit-hooks + "/nix/run.nix") { + inherit tools; + isFlakes = true; + # unused! + gitignore-nix-src = builtins.throw "gitignore-nix-src is unused"; }; - treefmt = { - enable = true; - settings.formatters = [ ]; + in + pre-commit-run { + src = self; + hooks = { + no-commit-to-branch = { + enable = true; + settings.branch = [ "main" ]; + }; + check-case-conflicts.enable = true; + check-executables-have-shebangs = { + enable = true; + stages = [ "commit" ]; + }; + check-shebang-scripts-are-executable = { + enable = true; + stages = [ "commit" ]; + }; + check-symlinks = { + enable = true; + excludes = [ "^tests/functional/lang/symlink-resolution/broken$" ]; + }; + check-merge-conflicts.enable = true; + end-of-file-fixer = { + enable = true; + excludes = [ + "\\.drv$" + "^tests/functional/lang/" + ]; + }; + mixed-line-endings = { + enable = true; + excludes = [ "^tests/functional/lang/" ]; + }; + release-notes = { + enable = true; + package = pkgs.build-release-notes; + files = "^doc/manual/rl-next(-dev)?"; + pass_filenames = false; + entry = '' + ${lib.getExe pkgs.build-release-notes} doc/manual/rl-next doc/manual/rl-next-dev + ''; + }; + check-headers = { + enable = true; + package = pkgs.check-headers; + files = "^src/"; + types = [ + "c++" + "file" + "header" + ]; + # generated files; these will never actually be seen by this + # check, and are left here as documentation + excludes = [ + "(parser|lexer)-tab\\.hh$" + "\\.gen\\.hh$" + ]; + entry = lib.getExe pkgs.check-headers; + }; + # TODO: Once the test suite is nicer, clean up and start + # enforcing trailing whitespace on tests that don't explicitly + # check for it. + trim-trailing-whitespace = { + enable = true; + stages = [ "commit" ]; + excludes = [ "^tests/functional/lang/" ]; + }; + treefmt = { + enable = true; + settings.formatters = [ pkgs.nixfmt ]; + }; }; - }; - }) pre-commit-hooks.lib; + } + ); }; # NOTE *do not* add fresh derivations to checks, always add them to # hydraJobs first (so CI will pick them up) and only link them here - checks = forAllSystems (system: { - # FIXME(Qyriad): remove this when the migration to Meson has been completed. - mesonBuild = self.hydraJobs.mesonBuild.${system}; - mesonBuildClang = self.hydraJobs.mesonBuildClang.${system}; - binaryTarball = self.hydraJobs.binaryTarball.${system}; - perlBindings = self.hydraJobs.perlBindings.${system}; - nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system}; - rl-next = self.hydraJobs.rl-next.${system}.user; - rl-next-dev = self.hydraJobs.rl-next.${system}.dev; - pre-commit = self.hydraJobs.pre-commit.${system}; - } // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) { - dockerImage = self.hydraJobs.dockerImage.${system}; - }); - - packages = forAllSystems (system: rec { - inherit (nixpkgsFor.${system}.native) nix; - default = nix; - } // (lib.optionalAttrs (builtins.elem system linux64BitSystems) { - nix-static = nixpkgsFor.${system}.static.nix; - dockerImage = - let - pkgs = nixpkgsFor.${system}.native; - image = import ./docker.nix { inherit pkgs; tag = version; }; - in - pkgs.runCommand - "docker-image-tarball-${version}" - { meta.description = "Docker image with Nix for ${system}"; } - '' - mkdir -p $out/nix-support - image=$out/image.tar.gz - ln -s ${image} $image - echo "file binary-dist $image" >> $out/nix-support/hydra-build-products - ''; - } // builtins.listToAttrs (map - (crossSystem: { - name = "nix-${crossSystem}"; - value = nixpkgsFor.${system}.cross.${crossSystem}.nix; - }) - crossSystems) - // builtins.listToAttrs (map - (stdenvName: { - name = "nix-${stdenvName}"; - value = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nix; - }) - stdenvs))); - - devShells = let - makeShell = pkgs: stdenv: - let - nix = pkgs.callPackage ./package.nix { - inherit stdenv versionSuffix; - busybox-sandbox-shell = pkgs.busybox-sandbox-shell or pkgs.default-busybox-sandbox; - forDevShell = true; - }; - pre-commit = self.hydraJobs.pre-commit.${pkgs.system} or {}; - in + checks = forAllSystems ( + system: + { + # FIXME(Qyriad): remove this when the migration to Meson has been completed. + mesonBuild = self.hydraJobs.mesonBuild.${system}; + mesonBuildClang = self.hydraJobs.mesonBuildClang.${system}; + binaryTarball = self.hydraJobs.binaryTarball.${system}; + perlBindings = self.hydraJobs.perlBindings.${system}; + nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system}; + rl-next = self.hydraJobs.rl-next.${system}.user; + rl-next-dev = self.hydraJobs.rl-next.${system}.dev; + pre-commit = self.hydraJobs.pre-commit.${system}; + } + // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) { + dockerImage = self.hydraJobs.dockerImage.${system}; + } + ); + + packages = forAllSystems ( + system: + rec { + inherit (nixpkgsFor.${system}.native) nix; + default = nix; + } + // ( + lib.optionalAttrs (builtins.elem system linux64BitSystems) { + nix-static = nixpkgsFor.${system}.static.nix; + dockerImage = + let + pkgs = nixpkgsFor.${system}.native; + image = import ./docker.nix { + inherit pkgs; + tag = version; + }; + in + pkgs.runCommand "docker-image-tarball-${version}" + { meta.description = "Docker image with Nix for ${system}"; } + '' + mkdir -p $out/nix-support + image=$out/image.tar.gz + ln -s ${image} $image + echo "file binary-dist $image" >> $out/nix-support/hydra-build-products + ''; + } + // builtins.listToAttrs ( + map (crossSystem: { + name = "nix-${crossSystem}"; + value = nixpkgsFor.${system}.cross.${crossSystem}.nix; + }) crossSystems + ) + // builtins.listToAttrs ( + map (stdenvName: { + name = "nix-${stdenvName}"; + value = nixpkgsFor.${system}.stdenvs."${stdenvName}Packages".nix; + }) stdenvs + ) + ) + ); + + devShells = + let + makeShell = + pkgs: stdenv: + let + nix = pkgs.callPackage ./package.nix { + inherit stdenv versionSuffix; + busybox-sandbox-shell = pkgs.busybox-sandbox-shell or pkgs.default-busybox-sandbox; + forDevShell = true; + }; + pre-commit = self.hydraJobs.pre-commit.${pkgs.system} or { }; + in (nix.override { buildUnreleasedNotes = true; officialRelease = false; - }).overrideAttrs (prev: { - # Required for clang-tidy checks - buildInputs = prev.buildInputs - ++ [ pkgs.just ] - ++ lib.optional (pre-commit ? enabledPackages) pre-commit.enabledPackages - ++ lib.optionals (stdenv.cc.isClang) [ pkgs.llvmPackages.llvm pkgs.llvmPackages.clang-unwrapped.dev ]; - nativeBuildInputs = prev.nativeBuildInputs - ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear - # Required for clang-tidy checks - ++ lib.optionals (stdenv.cc.isClang) [ pkgs.buildPackages.cmake pkgs.buildPackages.ninja pkgs.buildPackages.llvmPackages.llvm.dev ] - ++ lib.optional - (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) - # for some reason that seems accidental and was changed in - # NixOS 24.05-pre, clang-tools is pinned to LLVM 14 when - # default LLVM is newer. - (pkgs.buildPackages.clang-tools.override { inherit (pkgs.buildPackages) llvmPackages; }) - ++ [ - # FIXME(Qyriad): remove once the migration to Meson is complete. - pkgs.buildPackages.meson - pkgs.buildPackages.ninja - pkgs.buildPackages.cmake - - pkgs.buildPackages.clangbuildanalyzer - ]; - - src = null; - - installFlags = "sysconfdir=$(out)/etc"; - strictDeps = false; - - shellHook = '' - PATH=$prefix/bin:$PATH - unset PYTHONPATH - export MANPATH=$out/share/man:$MANPATH - - # Make bash completion work. - XDG_DATA_DIRS+=:$out/share - - ${lib.optionalString (pre-commit ? shellHook) pre-commit.shellHook} - ''; - } // lib.optionalAttrs (stdenv.buildPlatform.isLinux && pkgs.glibcLocales != null) { - # Required to make non-NixOS Linux not complain about missing locale files during configure in a dev shell - LOCALE_ARCHIVE = "${lib.getLib pkgs.glibcLocales}/lib/locale/locale-archive"; - }); + }).overrideAttrs + ( + prev: + { + # Required for clang-tidy checks + buildInputs = + prev.buildInputs + ++ [ + pkgs.just + pkgs.nixfmt + ] + ++ lib.optional (pre-commit ? enabledPackages) pre-commit.enabledPackages + ++ lib.optionals (stdenv.cc.isClang) [ + pkgs.llvmPackages.llvm + pkgs.llvmPackages.clang-unwrapped.dev + ]; + nativeBuildInputs = + prev.nativeBuildInputs + ++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear + # Required for clang-tidy checks + ++ lib.optionals (stdenv.cc.isClang) [ + pkgs.buildPackages.cmake + pkgs.buildPackages.ninja + pkgs.buildPackages.llvmPackages.llvm.dev + ] + ++ + lib.optional (stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform) + # for some reason that seems accidental and was changed in + # NixOS 24.05-pre, clang-tools is pinned to LLVM 14 when + # default LLVM is newer. + (pkgs.buildPackages.clang-tools.override { inherit (pkgs.buildPackages) llvmPackages; }) + ++ [ + # FIXME(Qyriad): remove once the migration to Meson is complete. + pkgs.buildPackages.meson + pkgs.buildPackages.ninja + pkgs.buildPackages.cmake + + pkgs.buildPackages.clangbuildanalyzer + ]; + + src = null; + + installFlags = "sysconfdir=$(out)/etc"; + strictDeps = false; + + shellHook = '' + PATH=$prefix/bin:$PATH + unset PYTHONPATH + export MANPATH=$out/share/man:$MANPATH + + # Make bash completion work. + XDG_DATA_DIRS+=:$out/share + + ${lib.optionalString (pre-commit ? shellHook) pre-commit.shellHook} + ''; + } + // lib.optionalAttrs (stdenv.buildPlatform.isLinux && pkgs.glibcLocales != null) { + # Required to make non-NixOS Linux not complain about missing locale files during configure in a dev shell + LOCALE_ARCHIVE = "${lib.getLib pkgs.glibcLocales}/lib/locale/locale-archive"; + } + ); in - forAllSystems (system: + forAllSystems ( + system: let - makeShells = prefix: pkgs: - lib.mapAttrs' - (k: v: lib.nameValuePair "${prefix}-${k}" v) - (forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName})); + makeShells = + prefix: pkgs: + lib.mapAttrs' (k: v: lib.nameValuePair "${prefix}-${k}" v) ( + forAllStdenvs (stdenvName: makeShell pkgs pkgs.${stdenvName}) + ); in - (makeShells "native" nixpkgsFor.${system}.native) // - (makeShells "static" nixpkgsFor.${system}.static) // - (forAllCrossSystems (crossSystem: let pkgs = nixpkgsFor.${system}.cross.${crossSystem}; in makeShell pkgs pkgs.stdenv)) // - { - default = self.devShells.${system}.native-stdenvPackages; - } + (makeShells "native" nixpkgsFor.${system}.native) + // (makeShells "static" nixpkgsFor.${system}.static) + // (forAllCrossSystems ( + crossSystem: + let + pkgs = nixpkgsFor.${system}.cross.${crossSystem}; + in + makeShell pkgs pkgs.stdenv + )) + // { + default = self.devShells.${system}.native-stdenvPackages; + } ); - }; + }; } diff --git a/lix-doc/package.nix b/lix-doc/package.nix index 86ab7501e..d3896e726 100644 --- a/lix-doc/package.nix +++ b/lix-doc/package.nix @@ -1,7 +1,4 @@ -{ - rustPlatform, - lib -}: +{ rustPlatform, lib }: rustPlatform.buildRustPackage { name = "lix-doc"; @@ -4,7 +4,7 @@ # This has an overhead of 0-4% on gcc and unmeasurably little on clang, in # Nix evaluation benchmarks. DEFAULT_SANITIZE_FLAGS = -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error -GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch $(DEFAULT_SANITIZE_FLAGS) +GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch $(DEFAULT_SANITIZE_FLAGS) -D_GLIBCXX_ASSERTIONS=1 GLOBAL_LDFLAGS += $(DEFAULT_SANITIZE_FLAGS) # Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers. ERROR_SWITCH_ENUM = -Werror=switch-enum diff --git a/maintainers/build-release-notes.nix b/maintainers/build-release-notes.nix index 9462e33d7..1acbe87f1 100644 --- a/maintainers/build-release-notes.nix +++ b/maintainers/build-release-notes.nix @@ -1,4 +1,8 @@ -{ lib, python3, writeShellScriptBin }: +{ + lib, + python3, + writeShellScriptBin, +}: writeShellScriptBin "build-release-notes" '' exec ${lib.getExe (python3.withPackages (p: [ p.python-frontmatter ]))} \ diff --git a/maintainers/build-release-notes.py b/maintainers/build-release-notes.py index 00c91e5da..2a154a61e 100644 --- a/maintainers/build-release-notes.py +++ b/maintainers/build-release-notes.py @@ -28,39 +28,49 @@ def format_issue(issue: str) -> str: return format_link(issue, "issues", "issues") def format_pr(pr: str) -> str: return format_link(pr, "pull", "pulls") -def format_cl(cl: str) -> str: - clid = int(cl) +def format_cl(clid: int) -> str: return f"[cl/{clid}]({GERRIT_BASE}/{clid})" -paths = pathlib.Path(sys.argv[1]).glob('*.md') -entries = [] -for p in paths: - try: - e = frontmatter.load(p) - if 'synopsis' not in e.metadata: - raise Exception('missing synopsis') - unknownKeys = set(e.metadata.keys()) - set(('synopsis', 'cls', 'issues', 'prs', 'significance')) - if unknownKeys: - raise Exception('unknown keys', unknownKeys) - entries.append((p, e)) - except Exception as e: - e.add_note(f"in {p}") - raise +def run_on_dir(d): + paths = pathlib.Path(d).glob('*.md') + entries = [] + for p in paths: + try: + e = frontmatter.load(p) + if 'synopsis' not in e.metadata: + raise Exception('missing synopsis') + unknownKeys = set(e.metadata.keys()) - set(('synopsis', 'cls', 'issues', 'prs', 'significance')) + if unknownKeys: + raise Exception('unknown keys', unknownKeys) + entries.append((p, e)) + except Exception as e: + e.add_note(f"in {p}") + raise -for p, entry in sorted(entries, key=lambda e: (-SIGNIFICANCECES[e[1].metadata.get('significance')], e[0])): - try: - header = entry.metadata['synopsis'] - links = [] - links += map(format_issue, str(entry.metadata.get('issues', "")).split()) - links += map(format_pr, str(entry.metadata.get('prs', "")).split()) - links += map(format_cl, str(entry.metadata.get('cls', "")).split()) - if links != []: - header += " " + " ".join(links) - if header: - print(f"- {header}") + def listify(l: list | int) -> list: + if not isinstance(l, list): + return [l] + else: + return l + + for p, entry in sorted(entries, key=lambda e: (-SIGNIFICANCECES[e[1].metadata.get('significance')], e[0])): + try: + header = entry.metadata['synopsis'] + links = [] + links += [format_issue(str(s)) for s in listify(entry.metadata.get('issues', []))] + links += [format_pr(str(s)) for s in listify(entry.metadata.get('prs', []))] + links += [format_cl(cl) for cl in listify(entry.metadata.get('cls', []))] + if links != []: + header += " " + " ".join(links) + if header: + print(f"- {header}") + print() + print(textwrap.indent(entry.content, ' ')) print() - print(textwrap.indent(entry.content, ' ')) - print() - except Exception as e: - e.add_note(f"in {p}") - raise + except Exception as e: + e.add_note(f"in {p}") + raise + +if __name__ == '__main__': + for d in sys.argv[1:]: + run_on_dir(d) diff --git a/maintainers/check-headers.nix b/maintainers/check-headers.nix new file mode 100644 index 000000000..a184bb401 --- /dev/null +++ b/maintainers/check-headers.nix @@ -0,0 +1,7 @@ +{ writeShellApplication, gnugrep }: +writeShellApplication { + name = "check-headers"; + + runtimeInputs = [ gnugrep ]; + text = builtins.readFile ./check-headers.sh; +} diff --git a/maintainers/check-headers.sh b/maintainers/check-headers.sh new file mode 100755 index 000000000..2b4dd248a --- /dev/null +++ b/maintainers/check-headers.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +set -eu + +# n.b. this might be printed multiple times if any violating header files are +# in different parallelism groups inside pre-commit. We cannot do anything about +# this. +explanation=$(cat <<'EOF' + +We found some header files that don't conform to the style guide. + +The Lix style guide requests that header files: +- Begin with `#pragma once` so they only get parsed once +- Contain a doxygen comment (`/**` or `///`) containing `@file`, for + example, `///@file`, which will make doxygen generate docs for them. + + When adding that, consider also adding a `@brief` with a sentence + explaining what the header is for. + +For more details: https://wiki.lix.systems/link/3#bkmrk-header-files +EOF +) + +check_file() { + grep -q "$1" "$2" || (echo "Missing pattern $1 in file $2" >&2; return 1) +} + +patterns=( + # makes a file get included only once even if it is included multiple times + '^#pragma once$' + # as used in ///@file, makes the file appear to doxygen + '@file' +) +fail=0 + +for pattern in "${patterns[@]}"; do + for file in "$@"; do + check_file "$pattern" "$file" || fail=1 + done +done + +if [[ $fail != 0 ]]; then + echo "$explanation" >&2 + exit 1 +else + echo OK +fi diff --git a/maintainers/release-notes b/maintainers/release-notes index c7a4e5074..477df31f1 100755 --- a/maintainers/release-notes +++ b/maintainers/release-notes @@ -8,7 +8,7 @@ # This does double duty for # - including rl-next # - marking where to insert new links (right after) -SUMMARY_MARKER_LINE='{{#include ./SUMMARY-rl-next.md}}' +SUMMARY_MARKER_LINE='release-notes/rl-next.md' # --- LIB --- @@ -79,9 +79,9 @@ if ! git diff --quiet --cached; then die "repo has staged changes, please commit or stash them" fi -if ! grep "$SUMMARY_MARKER_LINE" doc/manual/src/SUMMARY.md.in >/dev/null; then +if ! grep -F "$SUMMARY_MARKER_LINE" doc/manual/src/SUMMARY.md >/dev/null; then # would have been nice to catch this early, but won't be worth the extra infra - die "SUMMARY.md.in is missing the marker line '$SUMMARY_MARKER_LINE', which would be used for inserting a new release notes page. Please fix the script." + die "SUMMARY.md is missing the marker line '$SUMMARY_MARKER_LINE', which would be used for inserting a new release notes page. Please fix the script." fi if [[ ! -n "${VERSION:-}" ]]; then @@ -163,7 +163,7 @@ if ! $IS_PATCH; then # find the marker line, insert new link after it escaped_marker="$(echo "$SUMMARY_MARKER_LINE" | sed -e 's/\//\\\//g' -e 's/ /\\ /g')" escaped_line="$(echo "$NEW_SUMMARY_LINE" | sed -e 's/\//\\\//g' -e 's/ /\\ /g')" - logcmd sed -i -e "/$escaped_marker/a $escaped_line" doc/manual/src/SUMMARY.md.in + logcmd sed -i -e "/$escaped_marker/a $escaped_line" doc/manual/src/SUMMARY.md fi for f in doc/manual/rl-next/*.md; do @@ -172,7 +172,7 @@ for f in doc/manual/rl-next/*.md; do fi done -logcmd git add $file doc/manual/src/SUMMARY.md.in +logcmd git add $file doc/manual/src/SUMMARY.md logcmd git status logcmd git commit -m "release notes: $version_full" diff --git a/maintainers/release-process.md b/maintainers/release-process.md index 5d68b2861..f2b60d8e7 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -60,6 +60,7 @@ release: ```console $ sed -e 's/officialRelease = false;/officialRelease = true;/' -i flake.nix + $ sed -e '/rl-next.md/ d' -i doc/manual/src/SUMMARY.md ``` This removes the link to `rl-next.md` from the manual and sets diff --git a/meson.build b/meson.build index 2cedabad5..456be5aa2 100644 --- a/meson.build +++ b/meson.build @@ -344,6 +344,12 @@ add_project_arguments( '-Wimplicit-fallthrough', '-Werror=switch', '-Werror=switch-enum', + # Enable assertions in libstdc++ by default. Harmless on libc++. Benchmarked + # at ~1% overhead in `nix search`. + # + # FIXME: remove when we get meson 1.4.0 which will default this to on for us: + # https://mesonbuild.com/Release-notes-for-1-4-0.html#ndebug-setting-now-controls-c-stdlib-assertions + '-D_GLIBCXX_ASSERTIONS=1', language : 'cpp', ) @@ -351,8 +357,7 @@ if cxx.get_id() in ['gcc', 'clang'] # 2024-03-24: jade benchmarked the default sanitize reporting in clang and got # a regression of about 10% on hackage-packages.nix with clang. So we are trapping instead. # - # This has an overhead of 0-4% on gcc and unmeasurably little on clang, in - # Nix evaluation benchmarks. + # This has an unmeasurably low overhead in Nix evaluation benchmarks. # # N.B. Meson generates a completely nonsense warning here: # https://github.com/mesonbuild/meson/issues/9822 diff --git a/misc/clangbuildanalyzer.nix b/misc/clangbuildanalyzer.nix index a317e5144..cee8a0d77 100644 --- a/misc/clangbuildanalyzer.nix +++ b/misc/clangbuildanalyzer.nix @@ -1,6 +1,11 @@ # Upstreaming here, can be deleted once it's upstreamed: # https://github.com/NixOS/nixpkgs/pull/297102 -{ stdenv, lib, cmake, fetchFromGitHub }: +{ + stdenv, + lib, + cmake, + fetchFromGitHub, +}: stdenv.mkDerivation (finalAttrs: { pname = "clangbuildanalyzer"; version = "1.5.0"; @@ -12,9 +17,7 @@ stdenv.mkDerivation (finalAttrs: { sha256 = "sha256-kmgdk634zM0W0OoRoP/RzepArSipa5bNqdVgdZO9gxo="; }; - nativeBuildInputs = [ - cmake - ]; + nativeBuildInputs = [ cmake ]; meta = { description = "Tool for analyzing Clang's -ftrace-time files"; diff --git a/nix-support/nixfmt.nix b/nix-support/nixfmt.nix new file mode 100644 index 000000000..b51e26295 --- /dev/null +++ b/nix-support/nixfmt.nix @@ -0,0 +1,65 @@ +# Copy of `nixfmt-rfc-style` vendored from `nixpkgs` master: +# https://github.com/NixOS/nixpkgs/blob/ab6071eb54cc9b66dda436111d4f569e4e56cbf4/pkgs/by-name/ni/nixfmt-rfc-style/package.nix +{ + haskell, + haskellPackages, + fetchFromGitHub, +}: +let + inherit (haskell.lib.compose) justStaticExecutables; + raw-pkg = haskellPackages.callPackage ( + { + mkDerivation, + base, + cmdargs, + directory, + fetchzip, + filepath, + lib, + megaparsec, + mtl, + parser-combinators, + safe-exceptions, + scientific, + text, + transformers, + unix, + }: + mkDerivation { + pname = "nixfmt"; + version = "0.6.0-unstable-2024-03-14"; + src = fetchFromGitHub { + owner = "serokell"; + repo = "nixfmt"; + rev = "8d13b593fa8d8d6e5075f541f3231222a08e84df"; + hash = "sha256-HtXvzmfN4wk45qiKZ7V+/5WBV7jnTHfd7iBwF4XGl64="; + }; + isLibrary = true; + isExecutable = true; + libraryHaskellDepends = [ + base + megaparsec + mtl + parser-combinators + scientific + text + transformers + ]; + executableHaskellDepends = [ + base + cmdargs + directory + filepath + safe-exceptions + text + unix + ]; + jailbreak = true; + homepage = "https://github.com/serokell/nixfmt"; + description = "An opinionated formatter for Nix"; + license = lib.licenses.mpl20; + mainProgram = "nixfmt"; + } + ) { }; +in +justStaticExecutables raw-pkg diff --git a/package.nix b/package.nix index d096b5c73..e1d3cfcd5 100644 --- a/package.nix +++ b/package.nix @@ -69,9 +69,7 @@ __forDefaults ? { canRunInstalled = stdenv.buildPlatform.canExecute stdenv.hostPlatform; - boehmgc-nix = (boehmgc.override { - enableLargeConfig = true; - }).overrideAttrs { + boehmgc-nix = (boehmgc.override { enableLargeConfig = true; }).overrideAttrs { patches = [ # We do *not* include prev.patches (which doesn't exist in normal pkgs.boehmgc anyway) # because if the caller of this package passed a patched boehm as `boehmgc` instead of @@ -85,20 +83,22 @@ lix-doc = pkgs.callPackage ./lix-doc/package.nix { }; }, -}: let +}: +let inherit (__forDefaults) canRunInstalled; inherit (lib) fileset; version = lib.fileContents ./.version + versionSuffix; aws-sdk-cpp-nix = aws-sdk-cpp.override { - apis = [ "s3" "transfer" ]; + apis = [ + "s3" + "transfer" + ]; customMemoryManagement = false; }; - testConfigureFlags = [ - "RAPIDCHECK_HEADERS=${lib.getDev rapidcheck}/extras/gtest/include" - ]; + testConfigureFlags = [ "RAPIDCHECK_HEADERS=${lib.getDev rapidcheck}/extras/gtest/include" ]; # The internal API docs need these for the build, but if we're not building # Nix itself, then these don't need to be propagated. @@ -120,48 +120,60 @@ ./README.md ]; - topLevelBuildFiles = fileset.unions ([ - ./local.mk - ./Makefile - ./Makefile.config.in - ./mk - ] ++ lib.optionals buildWithMeson [ - ./meson.build - ./meson.options - ./meson - ./scripts/meson.build - ]); - - functionalTestFiles = fileset.unions [ + topLevelBuildFiles = fileset.unions ( + [ + ./local.mk + ./Makefile + ./Makefile.config.in + ./mk + ] + ++ lib.optionals buildWithMeson [ + ./meson.build + ./meson.options + ./meson + ./scripts/meson.build + ] + ); + + functionalTestFiles = fileset.unions [ ./tests/functional ./tests/unit (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) - ]; - -in stdenv.mkDerivation (finalAttrs: { + ]; +in +stdenv.mkDerivation (finalAttrs: { inherit pname version; src = fileset.toSource { root = ./.; - fileset = fileset.intersection baseFiles (fileset.unions ([ - configureFiles - topLevelBuildFiles - functionalTestFiles - ] ++ lib.optionals (!finalAttrs.dontBuild || internalApiDocs) [ - ./boehmgc-coroutine-sp-fallback.diff - ./doc - ./misc - ./precompiled-headers.h - ./src - ./COPYING - ./scripts/local.mk - ])); + fileset = fileset.intersection baseFiles ( + fileset.unions ( + [ + configureFiles + topLevelBuildFiles + functionalTestFiles + ] + ++ lib.optionals (!finalAttrs.dontBuild || internalApiDocs) [ + ./boehmgc-coroutine-sp-fallback.diff + ./doc + ./misc + ./precompiled-headers.h + ./src + ./COPYING + ./scripts/local.mk + ] + ) + ); }; VERSION_SUFFIX = versionSuffix; - outputs = [ "out" ] - ++ lib.optionals (!finalAttrs.dontBuild) [ "dev" "doc" ]; + outputs = + [ "out" ] + ++ lib.optionals (!finalAttrs.dontBuild) [ + "dev" + "doc" + ]; dontBuild = false; @@ -173,53 +185,61 @@ in stdenv.mkDerivation (finalAttrs: { # We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata. dontUseCmakeConfigure = true; - nativeBuildInputs = [ - bison - flex - python3 - ] ++ [ - (lib.getBin lowdown) - mdbook - mdbook-linkcheck - autoconf-archive - ] ++ lib.optional (!buildWithMeson) autoreconfHook ++ [ - pkg-config - - # Tests - git - mercurial - jq - lsof - ] ++ lib.optional stdenv.hostPlatform.isLinux util-linuxMinimal + nativeBuildInputs = + [ + bison + flex + python3 + ] + ++ [ + (lib.getBin lowdown) + mdbook + mdbook-linkcheck + autoconf-archive + ] + ++ lib.optional (!buildWithMeson) autoreconfHook + ++ [ + pkg-config + + # Tests + git + mercurial + jq + lsof + ] + ++ lib.optional stdenv.hostPlatform.isLinux util-linuxMinimal ++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes ++ lib.optional internalApiDocs doxygen ++ lib.optionals buildWithMeson [ meson ninja cmake - ]; + ]; - buildInputs = [ - curl - bzip2 - xz - brotli - editline - openssl - sqlite - libarchive - boost - lowdown - libsodium - toml11 - lix-doc - ] - ++ lib.optionals stdenv.hostPlatform.isLinux [ libseccomp busybox-sandbox-shell ] + buildInputs = + [ + curl + bzip2 + xz + brotli + editline + openssl + sqlite + libarchive + boost + lowdown + libsodium + toml11 + lix-doc + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + libseccomp + busybox-sandbox-shell + ] ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid # There have been issues building these dependencies ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform) aws-sdk-cpp-nix - ++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs - ; + ++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs; checkInputs = [ gtest @@ -228,9 +248,7 @@ in stdenv.mkDerivation (finalAttrs: { propagatedBuildInputs = lib.optionals (!finalAttrs.dontBuild) maybePropagatedInputs; - disallowedReferences = [ - boost - ]; + disallowedReferences = [ boost ]; # Needed for Meson to find Boost. # https://github.com/NixOS/nixpkgs/issues/86131. @@ -239,46 +257,47 @@ in stdenv.mkDerivation (finalAttrs: { BOOST_LIBRARYDIR = "${lib.getLib boost}/lib"; }; - preConfigure = lib.optionalString (!finalAttrs.dontBuild && !stdenv.hostPlatform.isStatic) '' - # Copy libboost_context so we don't get all of Boost in our closure. - # https://github.com/NixOS/nixpkgs/issues/45462 - mkdir -p $out/lib - cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib - rm -f $out/lib/*.a - '' + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isLinux) '' - chmod u+w $out/lib/*.so.* - patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.* - '' + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isDarwin) '' - for LIB in $out/lib/*.dylib; do - chmod u+w $LIB - install_name_tool -id $LIB $LIB - install_name_tool -delete_rpath ${boost}/lib/ $LIB || true - done - install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib - '' + '' - # Workaround https://github.com/NixOS/nixpkgs/issues/294890. - if [[ -n "''${doCheck:-}" ]]; then - appendToVar configureFlags "--enable-tests" - else - appendToVar configureFlags "--disable-tests" - fi - ''; - - configureFlags = [ - "--with-boost=${boost}/lib" - ] ++ lib.optionals stdenv.isLinux [ - "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" - ] ++ lib.optionals (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) [ - "LDFLAGS=-fuse-ld=gold" - ] + preConfigure = + lib.optionalString (!finalAttrs.dontBuild && !stdenv.hostPlatform.isStatic) '' + # Copy libboost_context so we don't get all of Boost in our closure. + # https://github.com/NixOS/nixpkgs/issues/45462 + mkdir -p $out/lib + cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib + rm -f $out/lib/*.a + '' + + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isLinux) '' + chmod u+w $out/lib/*.so.* + patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.* + '' + + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isDarwin) '' + for LIB in $out/lib/*.dylib; do + chmod u+w $LIB + install_name_tool -id $LIB $LIB + install_name_tool -delete_rpath ${boost}/lib/ $LIB || true + done + install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib + '' + + '' + # Workaround https://github.com/NixOS/nixpkgs/issues/294890. + if [[ -n "''${doCheck:-}" ]]; then + appendToVar configureFlags "--enable-tests" + else + appendToVar configureFlags "--disable-tests" + fi + ''; + + configureFlags = + [ "--with-boost=${boost}/lib" ] + ++ lib.optionals stdenv.isLinux [ "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" ] + ++ lib.optionals ( + stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux") + ) [ "LDFLAGS=-fuse-ld=gold" ] ++ lib.optional stdenv.hostPlatform.isStatic "--enable-embedded-sandbox-shell" ++ lib.optionals (finalAttrs.doCheck || internalApiDocs) testConfigureFlags ++ lib.optional (!canRunInstalled) "--disable-doc-gen" ++ [ (lib.enableFeature internalApiDocs "internal-api-docs") ] ++ lib.optional (!forDevShell) "--sysconfdir=/etc" - ++ [ - "TOML11_HEADERS=${lib.getDev toml11}/include" - ]; + ++ [ "TOML11_HEADERS=${lib.getDev toml11}/include" ]; mesonBuildType = lib.optional (buildWithMeson || forDevShell) "debugoptimized"; @@ -290,37 +309,37 @@ in stdenv.mkDerivation (finalAttrs: { doCheck = true; - mesonCheckFlags = lib.optionals (buildWithMeson || forDevShell) [ - "--suite=check" - ]; + mesonCheckFlags = lib.optionals (buildWithMeson || forDevShell) [ "--suite=check" ]; installFlags = "sysconfdir=$(out)/etc"; - postInstall = lib.optionalString (!finalAttrs.dontBuild) '' - mkdir -p $doc/nix-support - echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products - '' + lib.optionalString stdenv.hostPlatform.isStatic '' - mkdir -p $out/nix-support - echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products - '' + lib.optionalString stdenv.isDarwin '' - for lib in libnixutil.dylib libnixexpr.dylib; do - install_name_tool \ - -change "${lib.getLib boost}/lib/libboost_context.dylib" \ - "$out/lib/libboost_context.dylib" \ - "$out/lib/$lib" - done - '' + lib.optionalString internalApiDocs '' - mkdir -p $out/nix-support - echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> "$out/nix-support/hydra-build-products" - ''; + postInstall = + lib.optionalString (!finalAttrs.dontBuild) '' + mkdir -p $doc/nix-support + echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products + '' + + lib.optionalString stdenv.hostPlatform.isStatic '' + mkdir -p $out/nix-support + echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products + '' + + lib.optionalString stdenv.isDarwin '' + for lib in libnixutil.dylib libnixexpr.dylib; do + install_name_tool \ + -change "${lib.getLib boost}/lib/libboost_context.dylib" \ + "$out/lib/libboost_context.dylib" \ + "$out/lib/$lib" + done + '' + + lib.optionalString internalApiDocs '' + mkdir -p $out/nix-support + echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> "$out/nix-support/hydra-build-products" + ''; doInstallCheck = finalAttrs.doCheck; installCheckFlags = "sysconfdir=$(out)/etc"; installCheckTarget = "installcheck"; # work around buggy detection in stdenv - mesonInstallCheckFlags = [ - "--suite=installcheck" - ]; + mesonInstallCheckFlags = [ "--suite=installcheck" ]; preInstallCheck = lib.optionalString stdenv.hostPlatform.isDarwin '' export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES @@ -338,14 +357,11 @@ in stdenv.mkDerivation (finalAttrs: { strictDeps = true; # strictoverflow is disabled because we trap on signed overflow instead - hardeningDisable = [ "strictoverflow" ] - ++ lib.optional stdenv.hostPlatform.isStatic "pie"; + hardeningDisable = [ "strictoverflow" ] ++ lib.optional stdenv.hostPlatform.isStatic "pie"; meta.platforms = lib.platforms.unix; - passthru.perl-bindings = pkgs.callPackage ./perl { - inherit fileset stdenv buildWithMeson; - }; + passthru.perl-bindings = pkgs.callPackage ./perl { inherit fileset stdenv buildWithMeson; }; # Export the patched version of boehmgc. # flake.nix exports that into its overlay. diff --git a/perl/default.nix b/perl/default.nix index 53666716e..af700eabe 100644 --- a/perl/default.nix +++ b/perl/default.nix @@ -1,63 +1,80 @@ -{ lib, fileset -, stdenv -, perl, perlPackages -, autoconf-archive, autoreconfHook, pkg-config -, nix, curl, bzip2, xz, boost, libsodium, darwin -, meson -, ninja -, buildWithMeson ? false, +{ + lib, + fileset, + stdenv, + perl, + perlPackages, + autoconf-archive, + autoreconfHook, + pkg-config, + nix, + curl, + bzip2, + xz, + boost, + libsodium, + darwin, + meson, + ninja, + buildWithMeson ? false, }: -perl.pkgs.toPerlModule (stdenv.mkDerivation { - name = "nix-perl-${nix.version}"; +perl.pkgs.toPerlModule ( + stdenv.mkDerivation { + name = "nix-perl-${nix.version}"; - src = fileset.toSource { - root = ../.; - fileset = fileset.unions ([ - ../.version - ./lib - ] ++ lib.optionals (!buildWithMeson) [ - # FIXME(Qyriad): What the hell is this? - # What is it used for and do we still need it? - ./MANIFEST - ../m4 - ../mk - ./Makefile - ./Makefile.config.in - ./configure.ac - ./local.mk - ] ++ lib.optionals buildWithMeson [ - ./meson.build - ]); - }; + src = fileset.toSource { + root = ../.; + fileset = fileset.unions ( + [ + ../.version + ./lib + ] + ++ lib.optionals (!buildWithMeson) [ + # FIXME(Qyriad): What the hell is this? + # What is it used for and do we still need it? + ./MANIFEST + ../m4 + ../mk + ./Makefile + ./Makefile.config.in + ./configure.ac + ./local.mk + ] + ++ lib.optionals buildWithMeson [ ./meson.build ] + ); + }; - nativeBuildInputs = [ - pkg-config - ] ++ lib.optionals (!buildWithMeson) [ - autoconf-archive - autoreconfHook - ] ++ lib.optionals buildWithMeson [ - meson - ninja - ]; + nativeBuildInputs = + [ pkg-config ] + ++ lib.optionals (!buildWithMeson) [ + autoconf-archive + autoreconfHook + ] + ++ lib.optionals buildWithMeson [ + meson + ninja + ]; - buildInputs = - [ nix - curl - bzip2 - xz - perl - boost - perlPackages.DBI - perlPackages.DBDSQLite - ] - ++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium - ++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security; + buildInputs = + [ + nix + curl + bzip2 + xz + perl + boost + perlPackages.DBI + perlPackages.DBDSQLite + ] + ++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium + ++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security; - # Nixpkgs' Meson hook likes to set this to "plain". - mesonBuildType = "debugoptimized"; + # Nixpkgs' Meson hook likes to set this to "plain". + mesonBuildType = "debugoptimized"; - enableParallelBuilding = true; + enableParallelBuilding = true; - postUnpack = "sourceRoot=$sourceRoot/perl"; -}) + postUnpack = "sourceRoot=$sourceRoot/perl"; + } +) diff --git a/src/libcmd/built-path.hh b/src/libcmd/built-path.hh index e677bc810..da87a33b0 100644 --- a/src/libcmd/built-path.hh +++ b/src/libcmd/built-path.hh @@ -1,3 +1,5 @@ +#pragma once +///@file #include "derived-path.hh" #include "realisation.hh" diff --git a/src/libexpr/eval-error.hh b/src/libexpr/eval-error.hh index 2fb6bcf41..4f0e0d24c 100644 --- a/src/libexpr/eval-error.hh +++ b/src/libexpr/eval-error.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <algorithm> diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index e8bfe81a4..98fe6881e 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "config.hh" namespace nix { diff --git a/src/libexpr/fetchurl.nix b/src/libexpr/fetchurl.nix index 9d1b61d7f..50007c738 100644 --- a/src/libexpr/fetchurl.nix +++ b/src/libexpr/fetchurl.nix @@ -1,43 +1,75 @@ -{ system ? "" # obsolete -, url -, hash ? "" # an SRI hash - -# Legacy hash specification -, md5 ? "", sha1 ? "", sha256 ? "", sha512 ? "" -, outputHash ? - if hash != "" then hash else if sha512 != "" then sha512 else if sha1 != "" then sha1 else if md5 != "" then md5 else sha256 -, outputHashAlgo ? - if hash != "" then "" else if sha512 != "" then "sha512" else if sha1 != "" then "sha1" else if md5 != "" then "md5" else "sha256" - -, executable ? false -, unpack ? false -, name ? baseNameOf (toString url) -, impure ? false +{ + system ? "", # obsolete + url, + hash ? "", # an SRI hash + + # Legacy hash specification + md5 ? "", + sha1 ? "", + sha256 ? "", + sha512 ? "", + outputHash ? + if hash != "" then + hash + else if sha512 != "" then + sha512 + else if sha1 != "" then + sha1 + else if md5 != "" then + md5 + else + sha256, + outputHashAlgo ? + if hash != "" then + "" + else if sha512 != "" then + "sha512" + else if sha1 != "" then + "sha1" + else if md5 != "" then + "md5" + else + "sha256", + + executable ? false, + unpack ? false, + name ? baseNameOf (toString url), + impure ? false, }: -derivation ({ - builder = "builtin:fetchurl"; +derivation ( + { + builder = "builtin:fetchurl"; - # New-style output content requirements. - outputHashMode = if unpack || executable then "recursive" else "flat"; + # New-style output content requirements. + outputHashMode = if unpack || executable then "recursive" else "flat"; - inherit name url executable unpack; + inherit + name + url + executable + unpack + ; - system = "builtin"; + system = "builtin"; - # No need to double the amount of network traffic - preferLocalBuild = true; + # No need to double the amount of network traffic + preferLocalBuild = true; - impureEnvVars = [ - # We borrow these environment variables from the caller to allow - # easy proxy configuration. This is impure, but a fixed-output - # derivation like fetchurl is allowed to do so since its result is - # by definition pure. - "http_proxy" "https_proxy" "ftp_proxy" "all_proxy" "no_proxy" - ]; + impureEnvVars = [ + # We borrow these environment variables from the caller to allow + # easy proxy configuration. This is impure, but a fixed-output + # derivation like fetchurl is allowed to do so since its result is + # by definition pure. + "http_proxy" + "https_proxy" + "ftp_proxy" + "all_proxy" + "no_proxy" + ]; - # To make "nix-prefetch-url" work. - urls = [ url ]; -} // (if impure - then { __impure = true; } - else { inherit outputHashAlgo outputHash; })) + # To make "nix-prefetch-url" work. + urls = [ url ]; + } + // (if impure then { __impure = true; } else { inherit outputHashAlgo outputHash; }) +) diff --git a/src/libexpr/flake/call-flake.nix b/src/libexpr/flake/call-flake.nix index 4beb0b0fe..58b4a5542 100644 --- a/src/libexpr/flake/call-flake.nix +++ b/src/libexpr/flake/call-flake.nix @@ -4,69 +4,69 @@ let lockFile = builtins.fromJSON lockFileStr; - allNodes = - builtins.mapAttrs - (key: node: - let + allNodes = builtins.mapAttrs ( + key: node: + let - sourceInfo = - if key == lockFile.root - then rootSrc - else fetchTree (node.info or {} // removeAttrs node.locked ["dir"]); + sourceInfo = + if key == lockFile.root then + rootSrc + else + fetchTree (node.info or { } // removeAttrs node.locked [ "dir" ]); - subdir = if key == lockFile.root then rootSubdir else node.locked.dir or ""; + subdir = if key == lockFile.root then rootSubdir else node.locked.dir or ""; - outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir); + outPath = sourceInfo + ((if subdir == "" then "" else "/") + subdir); - flake = import (outPath + "/flake.nix"); + flake = import (outPath + "/flake.nix"); - inputs = builtins.mapAttrs - (inputName: inputSpec: allNodes.${resolveInput inputSpec}) - (node.inputs or {}); + inputs = builtins.mapAttrs (inputName: inputSpec: allNodes.${resolveInput inputSpec}) ( + node.inputs or { } + ); - # Resolve a input spec into a node name. An input spec is - # either a node name, or a 'follows' path from the root - # node. - resolveInput = inputSpec: - if builtins.isList inputSpec - then getInputByPath lockFile.root inputSpec - else inputSpec; + # Resolve a input spec into a node name. An input spec is + # either a node name, or a 'follows' path from the root + # node. + resolveInput = + inputSpec: if builtins.isList inputSpec then getInputByPath lockFile.root inputSpec else inputSpec; - # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the - # root node, returning the final node. - getInputByPath = nodeName: path: - if path == [] - then nodeName - else - getInputByPath - # Since this could be a 'follows' input, call resolveInput. - (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) - (builtins.tail path); + # Follow an input path (e.g. ["dwarffs" "nixpkgs"]) from the + # root node, returning the final node. + getInputByPath = + nodeName: path: + if path == [ ] then + nodeName + else + getInputByPath + # Since this could be a 'follows' input, call resolveInput. + (resolveInput lockFile.nodes.${nodeName}.inputs.${builtins.head path}) + (builtins.tail path); - outputs = flake.outputs (inputs // { self = result; }); + outputs = flake.outputs (inputs // { self = result; }); - result = - outputs - # We add the sourceInfo attribute for its metadata, as they are - # relevant metadata for the flake. However, the outPath of the - # sourceInfo does not necessarily match the outPath of the flake, - # as the flake may be in a subdirectory of a source. - # This is shadowed in the next // - // sourceInfo - // { - # This shadows the sourceInfo.outPath - inherit outPath; + result = + outputs + # We add the sourceInfo attribute for its metadata, as they are + # relevant metadata for the flake. However, the outPath of the + # sourceInfo does not necessarily match the outPath of the flake, + # as the flake may be in a subdirectory of a source. + # This is shadowed in the next // + // sourceInfo + // { + # This shadows the sourceInfo.outPath + inherit outPath; - inherit inputs; inherit outputs; inherit sourceInfo; _type = "flake"; - }; - - in - if node.flake or true then - assert builtins.isFunction flake.outputs; - result - else - sourceInfo - ) - lockFile.nodes; - -in allNodes.${lockFile.root} + inherit inputs; + inherit outputs; + inherit sourceInfo; + _type = "flake"; + }; + in + if node.flake or true then + assert builtins.isFunction flake.outputs; + result + else + sourceInfo + ) lockFile.nodes; +in +allNodes.${lockFile.root} diff --git a/src/libexpr/gc-small-vector.hh b/src/libexpr/gc-small-vector.hh index 94c3ad28b..c4bd1db26 100644 --- a/src/libexpr/gc-small-vector.hh +++ b/src/libexpr/gc-small-vector.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <boost/container/small_vector.hpp> diff --git a/src/libexpr/imported-drv-to-derivation.nix b/src/libexpr/imported-drv-to-derivation.nix index 9467e6a22..50864563e 100644 --- a/src/libexpr/imported-drv-to-derivation.nix +++ b/src/libexpr/imported-drv-to-derivation.nix @@ -1,21 +1,26 @@ -attrs @ { drvPath, outputs, name, ... }: +attrs@{ + drvPath, + outputs, + name, + ... +}: let - commonAttrs = (builtins.listToAttrs outputsList) // - { all = map (x: x.value) outputsList; - inherit drvPath name; - type = "derivation"; - }; + commonAttrs = (builtins.listToAttrs outputsList) // { + all = map (x: x.value) outputsList; + inherit drvPath name; + type = "derivation"; + }; - outputToAttrListElement = outputName: - { name = outputName; - value = commonAttrs // { - outPath = builtins.getAttr outputName attrs; - inherit outputName; - }; + outputToAttrListElement = outputName: { + name = outputName; + value = commonAttrs // { + outPath = builtins.getAttr outputName attrs; + inherit outputName; }; + }; outputsList = map outputToAttrListElement outputs; - -in (builtins.head outputsList).value +in +(builtins.head outputsList).value diff --git a/src/libexpr/pos-idx.hh b/src/libexpr/pos-idx.hh index e94fd85c6..406fc1b36 100644 --- a/src/libexpr/pos-idx.hh +++ b/src/libexpr/pos-idx.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <cinttypes> diff --git a/src/libexpr/pos-table.hh b/src/libexpr/pos-table.hh index 0b60c4f6d..704f24696 100644 --- a/src/libexpr/pos-table.hh +++ b/src/libexpr/pos-table.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <cinttypes> #include <numeric> diff --git a/src/libexpr/primops/derivation.nix b/src/libexpr/primops/derivation.nix index c0fbe8082..674408c6d 100644 --- a/src/libexpr/primops/derivation.nix +++ b/src/libexpr/primops/derivation.nix @@ -1,27 +1,35 @@ -/* This is the implementation of the ‘derivation’ builtin function. - It's actually a wrapper around the ‘derivationStrict’ primop. */ +/* + This is the implementation of the ‘derivation’ builtin function. + It's actually a wrapper around the ‘derivationStrict’ primop. +*/ -drvAttrs @ { outputs ? [ "out" ], ... }: +drvAttrs@{ + outputs ? [ "out" ], + ... +}: let strict = derivationStrict drvAttrs; - commonAttrs = drvAttrs // (builtins.listToAttrs outputsList) // - { all = map (x: x.value) outputsList; + commonAttrs = + drvAttrs + // (builtins.listToAttrs outputsList) + // { + all = map (x: x.value) outputsList; inherit drvAttrs; }; - outputToAttrListElement = outputName: - { name = outputName; - value = commonAttrs // { - outPath = builtins.getAttr outputName strict; - drvPath = strict.drvPath; - type = "derivation"; - inherit outputName; - }; + outputToAttrListElement = outputName: { + name = outputName; + value = commonAttrs // { + outPath = builtins.getAttr outputName strict; + drvPath = strict.drvPath; + type = "derivation"; + inherit outputName; }; + }; outputsList = map outputToAttrListElement outputs; - -in (builtins.head outputsList).value +in +(builtins.head outputsList).value diff --git a/src/libexpr/print-ambiguous.hh b/src/libexpr/print-ambiguous.hh index 50c260a9b..b615d1e5a 100644 --- a/src/libexpr/print-ambiguous.hh +++ b/src/libexpr/print-ambiguous.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "value.hh" diff --git a/src/libexpr/repl-exit-status.hh b/src/libexpr/repl-exit-status.hh index 08299ff61..f150b9597 100644 --- a/src/libexpr/repl-exit-status.hh +++ b/src/libexpr/repl-exit-status.hh @@ -1,4 +1,5 @@ #pragma once +///@file namespace nix { diff --git a/src/libfetchers/fetch-to-store.hh b/src/libfetchers/fetch-to-store.hh index eef269071..717450944 100644 --- a/src/libfetchers/fetch-to-store.hh +++ b/src/libfetchers/fetch-to-store.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "source-path.hh" #include "store-api.hh" diff --git a/src/libstore/derived-path-map.hh b/src/libstore/derived-path-map.hh index 4d72b301e..393cdedf7 100644 --- a/src/libstore/derived-path-map.hh +++ b/src/libstore/derived-path-map.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "types.hh" #include "derived-path.hh" diff --git a/src/libstore/path-references.hh b/src/libstore/path-references.hh index 7b44e3261..0553003f8 100644 --- a/src/libstore/path-references.hh +++ b/src/libstore/path-references.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "references.hh" #include "path.hh" diff --git a/src/libstore/remote-store-connection.hh b/src/libstore/remote-store-connection.hh index e4a9cacb9..44328b06b 100644 --- a/src/libstore/remote-store-connection.hh +++ b/src/libstore/remote-store-connection.hh @@ -1,3 +1,6 @@ +#pragma once +///@file + #include "remote-store.hh" #include "worker-protocol.hh" #include "pool.hh" diff --git a/src/libutil/args/root.hh b/src/libutil/args/root.hh index bb98732a1..f8124eaff 100644 --- a/src/libutil/args/root.hh +++ b/src/libutil/args/root.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include "args.hh" diff --git a/src/libutil/english.hh b/src/libutil/english.hh index 9c6c93571..d9289c663 100644 --- a/src/libutil/english.hh +++ b/src/libutil/english.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <iostream> diff --git a/src/libutil/escape-char.hh b/src/libutil/escape-char.hh index c7bae7ec0..e4b9da8ed 100644 --- a/src/libutil/escape-char.hh +++ b/src/libutil/escape-char.hh @@ -1,4 +1,6 @@ #pragma once +///@file + #include <ostream> namespace nix { diff --git a/src/libutil/escape-string.hh b/src/libutil/escape-string.hh index 7f0a9e701..2b06893dc 100644 --- a/src/libutil/escape-string.hh +++ b/src/libutil/escape-string.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <limits> #include <ostream> diff --git a/src/libutil/exit.hh b/src/libutil/exit.hh index 55f33e62f..27abc6a89 100644 --- a/src/libutil/exit.hh +++ b/src/libutil/exit.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <exception> diff --git a/src/libutil/print-elided.hh b/src/libutil/print-elided.hh index a99b15ca1..21bbf741c 100644 --- a/src/libutil/print-elided.hh +++ b/src/libutil/print-elided.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <ostream> diff --git a/src/libutil/shlex.hh b/src/libutil/shlex.hh index 4e7a48597..6ebe272ad 100644 --- a/src/libutil/shlex.hh +++ b/src/libutil/shlex.hh @@ -1,4 +1,5 @@ #pragma once +///@file #include <regex> #include <string> diff --git a/src/nix-channel/unpack-channel.nix b/src/nix-channel/unpack-channel.nix index 10515bc8b..84e324a4d 100644 --- a/src/nix-channel/unpack-channel.nix +++ b/src/nix-channel/unpack-channel.nix @@ -1,4 +1,8 @@ -{ name, channelName, src }: +{ + name, + channelName, + src, +}: derivation { builder = "builtin:unpack-channel"; diff --git a/src/nix-env/buildenv.nix b/src/nix-env/buildenv.nix index 0bac4c44b..c8955a94e 100644 --- a/src/nix-env/buildenv.nix +++ b/src/nix-env/buildenv.nix @@ -8,13 +8,15 @@ derivation { inherit manifest; # !!! grmbl, need structured data for passing this in a clean way. - derivations = - map (d: - [ (d.meta.active or "true") - (d.meta.priority or 5) - (builtins.length d.outputs) - ] ++ map (output: builtins.getAttr output d) d.outputs) - derivations; + derivations = map ( + d: + [ + (d.meta.active or "true") + (d.meta.priority or 5) + (builtins.length d.outputs) + ] + ++ map (output: builtins.getAttr output d) d.outputs + ) derivations; # Building user environments remotely just causes huge amounts of # network traffic, so don't do that. diff --git a/src/nix/doctor.cc b/src/nix/doctor.cc index 531f0ad86..da7a1d7a0 100644 --- a/src/nix/doctor.cc +++ b/src/nix/doctor.cc @@ -146,10 +146,9 @@ struct CmdDoctor : StoreCommand void checkTrustedUser(ref<Store> store) { - std::string_view trusted = store->isTrustedClient() - ? "trusted" - : "not trusted"; - checkInfo(fmt("You are %s by store uri: %s", trusted, store->getUri())); + auto trustedMay = store->isTrustedClient(); + std::string_view trustedness = trustedMay ? (*trustedMay ? "trusted" : "not trusted") : "unknown trust"; + checkInfo(fmt("You are %s by store uri: %s", trustedness, store->getUri())); } }; diff --git a/tests/functional/legacy-ssh-store.sh b/tests/functional/legacy-ssh-store.sh index 71b716b84..a75d55f34 100644 --- a/tests/functional/legacy-ssh-store.sh +++ b/tests/functional/legacy-ssh-store.sh @@ -1,4 +1,9 @@ source common.sh +store_uri="ssh://localhost?remote-store=$TEST_ROOT/other-store" + # Check that store ping trusted doesn't yet work with ssh:// -nix --store ssh://localhost?remote-store=$TEST_ROOT/other-store store ping --json | jq -e 'has("trusted") | not' +nix --store "$store_uri" store ping --json | jq -e 'has("trusted") | not' + +# Suppress grumpiness about multiple nixes on PATH +(nix --store "$store_uri" doctor || true) 2>&1 | grep 'You are unknown trust' diff --git a/tests/functional/local-store.sh b/tests/functional/local-store.sh index 89502f864..e3f0d771c 100644 --- a/tests/functional/local-store.sh +++ b/tests/functional/local-store.sh @@ -20,3 +20,6 @@ PATH3=$(nix path-info --store "local?root=$PWD/x" $CORRECT_PATH) # Ensure store ping trusted works with local store nix --store ./x store ping --json | jq -e '.trusted' + +# Suppress grumpiness about multiple nixes on PATH +(nix --store ./x doctor || true) 2>&1 | grep 'You are trusted by' diff --git a/tests/functional/remote-store.sh b/tests/functional/remote-store.sh index 7649964ef..856622e79 100644 --- a/tests/functional/remote-store.sh +++ b/tests/functional/remote-store.sh @@ -13,6 +13,8 @@ startDaemon if isDaemonNewer "2.15pre0"; then # Ensure that ping works trusted with new daemon nix store ping --json | jq -e '.trusted' + # Suppress grumpiness about multiple nixes on PATH + (nix doctor || true) 2>&1 | grep 'You are trusted by' else # And the the field is absent with the old daemon nix store ping --json | jq -e 'has("trusted") | not' diff --git a/tests/functional/repl_characterization/repl_characterization.cc b/tests/functional/repl_characterization/repl_characterization.cc index f3c6065aa..f84bbdaae 100644 --- a/tests/functional/repl_characterization/repl_characterization.cc +++ b/tests/functional/repl_characterization/repl_characterization.cc @@ -123,11 +123,6 @@ public: { runReplTestPath(nameBase, {}); } - - void runDebuggerTest(const std::string_view & nameBase) - { - runReplTestPath(nameBase, {"--debugger"}); - } }; TEST_F(ReplSessionTest, round_trip) diff --git a/tests/functional/repl_characterization/test-session.cc b/tests/functional/repl_characterization/test-session.cc index 52179a372..c3eb45b85 100644 --- a/tests/functional/repl_characterization/test-session.cc +++ b/tests/functional/repl_characterization/test-session.cc @@ -121,7 +121,7 @@ bool TestSession::readOutThen(ReadOutThenCallback cb) bool TestSession::waitForPrompt() { - bool notEof = readOutThen([&](std::span<char> s) -> ReadOutThenCallbackResult { + bool notEof = readOutThen([&](std::span<const char> s) -> ReadOutThenCallbackResult { bool foundPrompt = false; for (auto ch : s) { @@ -147,7 +147,7 @@ bool TestSession::waitForPrompt() void TestSession::wait() { - readOutThen([&](std::span<char> s) { + readOutThen([&](std::span<const char> s) { for (auto ch : s) { eater.feed(ch, [&](char c) { outputParser.feed(c); diff --git a/tests/functional/repl_characterization/test-session.hh b/tests/functional/repl_characterization/test-session.hh index 2552542fb..9961849fc 100644 --- a/tests/functional/repl_characterization/test-session.hh +++ b/tests/functional/repl_characterization/test-session.hh @@ -76,7 +76,7 @@ private: void wait(); enum class ReadOutThenCallbackResult { Stop, Continue }; - using ReadOutThenCallback = std::function<ReadOutThenCallbackResult(std::span<char>)>; + using ReadOutThenCallback = std::function<ReadOutThenCallbackResult(std::span<const char>)>; /** Reads some chunks of output, calling the callback provided for each * chunk and stopping if it returns Stop. * diff --git a/tests/unit/libstore-support/tests/test-data.hh b/tests/unit/libstore-support/tests/test-data.hh new file mode 100644 index 000000000..7aa1dd90d --- /dev/null +++ b/tests/unit/libstore-support/tests/test-data.hh @@ -0,0 +1,25 @@ +#pragma once + +#include "util.hh" +#include "types.hh" + +namespace nix { + +// TODO: These helpers should be available in all unit tests. + +/** + * The path to the unit test data directory. See the contributing guide + * in the manual for further details. + */ +static Path getUnitTestData() { + return getEnv("_NIX_TEST_UNIT_DATA").value(); +} + +/** + * Resolve a path under the unit test data directory to an absolute path. + */ +static Path getUnitTestDataPath(std::string_view path) { + return absPath(getUnitTestData() + "/" + path); +} + +} diff --git a/tests/unit/libstore/test-data/machines.bad_format b/tests/unit/libstore/data/machines.bad_format index 7255a1216..7255a1216 100644 --- a/tests/unit/libstore/test-data/machines.bad_format +++ b/tests/unit/libstore/data/machines.bad_format diff --git a/tests/unit/libstore/test-data/machines.valid b/tests/unit/libstore/data/machines.valid index 1a6c8017c..1a6c8017c 100644 --- a/tests/unit/libstore/test-data/machines.valid +++ b/tests/unit/libstore/data/machines.valid diff --git a/tests/unit/libstore/machines.cc b/tests/unit/libstore/machines.cc index 702461926..0277237bb 100644 --- a/tests/unit/libstore/machines.cc +++ b/tests/unit/libstore/machines.cc @@ -1,5 +1,6 @@ #include "machines.hh" #include "globals.hh" +#include "tests/test-data.hh" #include <gmock/gmock-matchers.h> @@ -17,7 +18,6 @@ using nix::getMachines; using nix::Machine; using nix::Machines; using nix::pathExists; -using nix::Settings; using nix::settings; class Environment : public ::testing::Environment { @@ -138,7 +138,7 @@ TEST(machines, getMachinesWithIncorrectFormat) { } TEST(machines, getMachinesWithCorrectFileReference) { - auto path = absPath("tests/unit/libstore/test-data/machines.valid"); + auto path = nix::getUnitTestDataPath("machines.valid"); ASSERT_TRUE(pathExists(path)); settings.builders = std::string("@") + path; @@ -165,6 +165,6 @@ TEST(machines, getMachinesWithIncorrectFileReference) { } TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) { - settings.builders = std::string("@") + absPath("tests/unit/libstore/test-data/machines.bad_format"); + settings.builders = std::string("@") + nix::getUnitTestDataPath("machines.bad_format"); EXPECT_THROW(getMachines(), FormatError); } diff --git a/tests/unit/libutil-support/tests/cli-literate-parser.cc b/tests/unit/libutil-support/tests/cli-literate-parser.cc index 023f86cd7..822f5e276 100644 --- a/tests/unit/libutil-support/tests/cli-literate-parser.cc +++ b/tests/unit/libutil-support/tests/cli-literate-parser.cc @@ -35,7 +35,7 @@ struct Parser : input(input) , rest(this->input) , prompt(config.prompt) - , indentString(std::string(config.indent, ' ')) + , indentString(config.indent, ' ') , lastWasOutput(false) , syntax{} { @@ -260,12 +260,11 @@ struct Parser std::vector<Node> newSyntax; auto shouldStart = true; - for (auto it = syntax.begin(); it != syntax.end(); ++it) { - Node node = std::move(*it); + for (auto & node : syntax) { std::visit( overloaded{ [&](Args & e) { - auto split = shell_split(std::string(e.text)); + auto split = shell_split(e.text); args.insert(args.end(), split.begin(), split.end()); }, [&](ShouldStart & e) { shouldStart = e.shouldStart; }, @@ -293,8 +292,7 @@ auto tidySyntax(View syntax) -> std::vector<Node> auto lastWasCommand = true; std::vector<Node> newSyntax; - for (auto it = syntax.begin(); it != syntax.end(); ++it) { - Node node = *it; + for (auto & node : syntax) { // Only compare `Command` and `Output` nodes. if (std::visit([&](auto && e) { return !e.shouldCompare(); }, node)) { continue; diff --git a/tests/unit/meson.build b/tests/unit/meson.build index a05776eca..ae850df47 100644 --- a/tests/unit/meson.build +++ b/tests/unit/meson.build @@ -85,6 +85,7 @@ libstore_test_support_sources = files( 'libstore-support/tests/derived-path.cc', 'libstore-support/tests/outputs-spec.cc', 'libstore-support/tests/path.cc', + 'libstore-support/tests/test-data.hh', ) libstore_test_support = library( @@ -142,7 +143,6 @@ test( '_NIX_TEST_UNIT_DATA': meson.project_source_root() / 'tests/unit/libstore/data', }, suite : 'check', - workdir : meson.project_source_root(), protocol : 'gtest', verbose : true, ) diff --git a/treefmt.toml b/treefmt.toml index 81df72cc2..0d8323d6e 100644 --- a/treefmt.toml +++ b/treefmt.toml @@ -1 +1,4 @@ -[formatter] +[formatter.nix] +command = "nixfmt" +includes = ["*.nix"] +excludes = ["tests/**"] |