Smaller stdenv for shells

I want to raise attention about this blogpost from @fzakaria : A minimal nix-shell | Farid Zakaria’s Blog, which talks about a smaller stdenv for mkShell.

Currently, mkShell uses stdenv, which pulls a C compiler resulting in a closure size of ~300M. Even stdenvNoCC still pulls other utilities, like sed or awk, which results in a ~50M closure size.

Should nixpkgs include an even smaller stdenv? I’ve got many projects for which I just need a couple of CLI tools, but I need to pay the price of pulling sed, awk and friends every time.

By using pkgsMusl’s bash and coreutils, I was able to get down to 6.5M size.

let
  pkgs = import <nixpkgs> {};
  stdenvMinimal = pkgs.stdenvNoCC.override {
    cc = null;
    preHook = "";
    allowedRequisites = null;
    initialPath = [pkgs.pkgsCross.musl64.busybox];
    shell = "${pkgs.pkgsCross.musl64.bash}/bin/bash";
    extraNativeBuildInputs = [];
  };
in
  pkgs.mkShell.override {stdenv = stdenvMinimal;} {
    name = "shell-minimal";
  }
$ nix path-info -Sh $(nix-build -A inputDerivation ./shell-minimal.nix)
/nix/store/l8rsmzpds1z4qbq60p9v8snkv9rd3zh0-shell-minimal          6.5M

$ nix path-info -Sh $(nix-build -A inputDerivation ./shell-nocc.nix)
/nix/store/xrp31fx9lkkm1j5rmyw7qn515s0gnkdb-shell-nocc    64.4M

$ nix path-info -Sh $(nix-build -A inputDerivation ./shell-stdenv.nix)
/nix/store/wvbkpq1ws8jdgbmc4npfas69cklc28ij-shell-standard       316.9M

The source for the 3 shells: https://github.com/viperML/shell-size

6 Likes

Could you explain why that is? Do the projects all live on separate machines that get destroyed regularly?
Normally you have to download the closure once and can then reuse it until you upgrade it.

It’s very cool to see, though, that you can actually go down to 6.5MB!

2 Likes

Every time, as in: every time I gargabe collect, create a new project, or clone some else’s project.

For example, my blog only requires hugo. If you want to use its devshell, you would have to pull the rest of stdenvNoCC.

2 Likes

Nice!
Still surprising that glibc is so big.
Maybe we can install it without all the i8n stuff too?

Since likely there are coreutils on the machine, I think creating a new shell derivation with a builder that doesn’t use mkdir is possible too.

All it should bring is just bash.

I envisioned a layer strategy or composing of features onto mkShell

4 Likes

For some discussion on @fzakaria’s blog post, see Minimal nix-shell

2 Likes

Wrote a simple flake, for anyone to quickly use in their projects:

4 Likes

pkgs.mkShell.override { stdenv = pkgs.stdenvNoCC; } strikes me as bad discoverability. Should mkShell be moved into stdenv?

1 Like

It’s also at pkgs.mkShellNoCC, if that helps

3 Likes