-
-
Notifications
You must be signed in to change notification settings - Fork 14.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mkShellMinimal: Create an ultra minimal nix-shell #132617
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -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 <nixpkgs> { }; | ||||||||
in | ||||||||
with nixpkgs; | ||||||||
mkShellMinimal { | ||||||||
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove this super-broad use of
Suggested change
|
||||||||
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. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{ 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"; | ||
|
||
# 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"; | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It comes at a very very little cost, but does enable shell completions. If that's not the design choice you want to make, I wonder if it should even set PATH. Maybe someone only wants to set another environment variable, in which case PATH is redundant. I guess it boils down to the question "when is it not a shell anymore?" which is obviously not clearly delineated, but needs an answer for this to be actually minimal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, in what regard is it minimal? I would define it as the combination of the number of store paths and the total byte size. The latter is generally so disproportionally determined by dependencies that the size of the shellHook (or similar) does not matter, as long as it doesn't increase store path count. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would say minimal with regards to closure size but from that we could support features to make the whole thing practical usable i.e. set |
||
''; | ||
}; | ||
|
||
# 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) | ||
roberth marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you use
pkgs.mkShellMinimal
above (and is more idiomatic IMO)