Skip to content

Instantly share code, notes, and snippets.

@b-rodrigues
Forked from CMCDragonkai/nix_inputs.md
Created February 28, 2024 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save b-rodrigues/c677b59126d05d43347ed9623ddd5b0c to your computer and use it in GitHub Desktop.
Save b-rodrigues/c677b59126d05d43347ed9623ddd5b0c to your computer and use it in GitHub Desktop.
Understanding Nix Inputs #nix

Understanding Nix Inputs

Every Nix derivation produces a Nix store output that has 3 things:

  • Executables
  • Libraries
  • Data

Executables are always exported using the PATH environment variable. This is pretty much automatic.

Libraries are exported in environment variables that are dependent on the language environment you are in. For example PYTHONPATH for Python. Or C_INCLUDE_PATH for gcc. This is usually done via a setup hook.

Data is often not exported with any special environment variables, unless you explicitly refer to them. You can do this within a Nix expression by simply interpolating the derivation as a string which will evaluate to their Nix store path.

During the transformation from a Nix derivation to a Nix output. We differentiate build environments from runtime environments. Here we are not considering cross-compilation. We are assuming that build and run environments are on the same machine.

  • buildInputs - Dependencies that should exist in the runtime environment.
  • propagatedBuildInputs - Dependencies that should exist in the runtime environment and also propagated to downstream runtime environments.
  • nativeBuildInputs - Dependencies that should only exist in the build environment.
  • propagatedNativeBuildInputs - Dependencies that should only exist in the build environment and also propagated to downstream build environments.

The above is not strictly true all the time because it depends on the derivation functions you are using.

The specific derivation function may have a different interpretation of what "propagation" means. And what environment variables they will propagate.

But basically we can see that most Python modules for a Python package must exist at runtime. They must also be propagated to downstream runtime environments, because any Python package that loads your package must be able to load your package's dependencies. This is why Python packages that export Python modules need to be in propagatedBuildInputs.

However consider C libraries that get compiled into shared objects. These shared objects are linked into by your C executable. Downstream users of your executable don't need to know about your the shared objects that your executable uses. This is why C packages that expose C libraries are put into buildInputs and not propagatedBuildInputs.

Note that when we use nix-shell, we are essentially entering into the build environment. This could mean that packages that are in propagatedBuildInputs or buildInputs which expose CLI executables may not appear in the build environment. It is important to realise this is a may as it depends on the derivation interpretation.

It's important to be explicit. So if you want something to always appear in the build environment and runtime environment, then it should be added to both.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment