From 459771518d44f60b59a19381d07b12297908215d Mon Sep 17 00:00:00 2001 From: Farid Zakaria Date: Tue, 3 Aug 2021 21:31:42 -0700 Subject: [PATCH 1/2] mkShellMinimal: Create an ultra minimal nix-shell This shell is inspired by my post https://fzakaria.com/2021/08/02/a-minimal-nix-shell.html and a follow-up post by https://github.com/jappeace/mt-shell The goal is to provide the facility to create an ultra-lightweight nix-shell that only has bash as the direct dependency. Users can set environment variables and add packages but the feature-set is purposely minimal. Update pkgs/build-support/mkshell/minimal.nix Co-authored-by: tomberek Update pkgs/build-support/mkshell/minimal.nix Co-authored-by: Ben Siraphob Update pkgs/build-support/mkshell/minimal.nix Co-authored-by: Robert Hensing --- doc/builders/special.xml | 1 + .../special/mkshellMinimal.section.md | 38 ++++++++++++ pkgs/build-support/mkshell/minimal.nix | 62 +++++++++++++++++++ pkgs/top-level/all-packages.nix | 1 + 4 files changed, 102 insertions(+) create mode 100644 doc/builders/special/mkshellMinimal.section.md create mode 100644 pkgs/build-support/mkshell/minimal.nix diff --git a/doc/builders/special.xml b/doc/builders/special.xml index 8902ce5c81329..7c052db223a0d 100644 --- a/doc/builders/special.xml +++ b/doc/builders/special.xml @@ -7,4 +7,5 @@ + diff --git a/doc/builders/special/mkshellMinimal.section.md b/doc/builders/special/mkshellMinimal.section.md new file mode 100644 index 0000000000000..667b65006248e --- /dev/null +++ b/doc/builders/special/mkshellMinimal.section.md @@ -0,0 +1,38 @@ +# pkgs.mkShellMinimal {#sec-pkgs-mkShellMinimal} + +`pkgs.mkShellMinimal` is similar to `mkShell` but does not rely on the +`stdenv` or even `bash`. It has a much smaller footprint and feature-set than +`mkShell` and is useful if you care about your closure size or being very explicit +about the dependencies (i.e. coreutils vs. busybox). + +## Usage {#sec-pkgs-mkShellMinimal-usage} + +```nix +let + nixpkgs = import { }; +in +with nixpkgs; +mkShellMinimal { + name = "my-minimal-shell"; + + # Place your dependencies here + packages = [ ]; + + # You can do typical environment variable setting + FOO = "bar"; +} +``` + +This shell can be started with `nix-shell` and has zero dependencies. + +```bash +❯ nix path-info -rSsh $(nix-build shell.nix) +This derivation is not meant to be built, unless you want to capture the dependency closure. + +/nix/store/8ka1hnlf06z3h2rpd00b4d9w5yxh0n39-setup 376.0 376.0 +/nix/store/nprykggfqhdkn4r5lxxknjvlqc4qm1yl-builder.sh 280.0 280.0 +/nix/store/xd8d72ccrxhaz3sxlmiqjnn1z0zwfhm8-my-minimal-shell 744.0 1.4K +``` + +`mkShellMinimal` is buildable as opposed to `mkShell`. This is useful if you want to upload the +transitive closure of the shell to a remote nix-store. diff --git a/pkgs/build-support/mkshell/minimal.nix b/pkgs/build-support/mkshell/minimal.nix new file mode 100644 index 0000000000000..546138befe7a5 --- /dev/null +++ b/pkgs/build-support/mkshell/minimal.nix @@ -0,0 +1,62 @@ +{ writeTextFile, writeScript, system }: + +# A special kind of derivation that is only meant to be consumed by the +# nix-shell. This differs from the traditional `mkShell` in that: +# It does not come with traditional stdenv (i.e. coreutils). +# Its only dependency is essentially bash. +{ +# a list of packages to add to the shell environment +# we simplify here rather than `native` or `propagated` since +# this is only ever used to be in a nix-shell; which is by default +# the current system +packages ? [ ], ... }@attrs: +derivation ({ + inherit system; + + name = "minimal-nix-shell"; + + # What is the need for this reference to stdenv? + # Well Nix itself, checks to see if this attribute exists + # and sources the file. + # We will setup our nix-shell environment here and do things + # like clear the $PATH + # reference: https://github.com/NixOS/nix/blob/94ec9e47030c2a7280503d338f0dca7ad92811f5/src/nix-build/nix-build.cc#L494 + "stdenv" = writeTextFile rec { + name = "setup"; + executable = true; + destination = "/${name}"; + text = '' + set -e + + # This is needed for `--pure` to work as expected. + # https://github.com/NixOS/nix/issues/5092 + PATH= + + for p in $packages; do + export PATH=$p/bin:$PATH + done + ''; + }; + + # Typically `mkShell` is not buildable. This has made it in practice, difficult to upload + # the dependency closure to a binary cache. Rather than add a confusing attribute to capture this + # let's just make the nix-shell buildable but message to the user that it doesn't make much sense. + # + # + # The builtin `export` dumps all current environment variables, + # which is where all build input references end up (e.g. $PATH for + # binaries). By writing this to $out, Nix can find and register + # them as runtime dependencies (since Nix greps for store paths + # through $out to find them) + # https://github.com/NixOS/nixpkgs/pull/95536/files#diff-282a02cc3871874f16401347d8fadc90d59d7ab11f6a99eaa5173c3867e1a160R358 + # + # For purity you generally don't want to rely on /bin/sh but since this derivation is *strictly* for a nix-shell + # we can rely on the fact that the underlying system is POSIX compliant. + builder = writeScript "builder.sh" '' + #!/bin/sh + echo + echo "This derivation is not meant to be built, unless you want to capture the dependency closure."; + echo + export > $out + ''; +} // attrs) diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 1e3d3178ea0b3..b8391f30223bc 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -623,6 +623,7 @@ in mkShell = callPackage ../build-support/mkshell { }; mkShellNoCC = mkShell.override { stdenv = stdenvNoCC; }; + mkShellMinimal = callPackage ../build-support/mkshell/minimal.nix { }; nixBufferBuilders = import ../build-support/emacs/buffer.nix { inherit (pkgs) lib writeText; inherit (emacs.pkgs) inherit-local; }; From d6a34c27a82dd5d0e52c6d3f47f1d20979d36bf8 Mon Sep 17 00:00:00 2001 From: Farid Zakaria Date: Mon, 29 Nov 2021 09:24:54 -0800 Subject: [PATCH 2/2] Update pkgs/build-support/mkshell/minimal.nix Co-authored-by: Sandro --- pkgs/build-support/mkshell/minimal.nix | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/build-support/mkshell/minimal.nix b/pkgs/build-support/mkshell/minimal.nix index 546138befe7a5..b630a0aa22ee1 100644 --- a/pkgs/build-support/mkshell/minimal.nix +++ b/pkgs/build-support/mkshell/minimal.nix @@ -15,11 +15,8 @@ derivation ({ name = "minimal-nix-shell"; - # What is the need for this reference to stdenv? - # Well Nix itself, checks to see if this attribute exists - # and sources the file. - # We will setup our nix-shell environment here and do things - # like clear the $PATH + # Nix checks if the stdenv attribute exists and sources that + # We use it here to setup the pure enviroment and do to clear envs like PATH # reference: https://github.com/NixOS/nix/blob/94ec9e47030c2a7280503d338f0dca7ad92811f5/src/nix-build/nix-build.cc#L494 "stdenv" = writeTextFile rec { name = "setup";