6

By "install packages" I mean to evaluate Nix build expressions (using nix-env, nix-shell -p, etc.) to build from source instead of using a substitute.

Also cross-posted to Unix& Linux because, as Charles Duffy pointed out, it is more on topic if it is about command-line tools or configuration. Still leaving this here because I assume forcing a package to always compile from source is possible by only using the Nix language, I just don't yet know how. (Or if it is in fact not possible, someone will point it out, and then this question does belong here.)

toraritte
  • 6,300
  • 3
  • 46
  • 67

1 Answers1

4

Either set the substitute option to false in nix.conf (the default is true) or use --option substitute false when invoking a Nix command.

nix-env --options substitute false -i hello

nix-shell --options substitute false -p hello

Might not be the droids you are looking for

As Robert Hensing (comment, chat), Henri Menke (comment), and Vladimír Čunát (comment) pointed out, this may not be the thing that you are really after.

To elaborate: I have been using the most basic Nix features confidently, but got to a point where I need to maintain and deploy a custom fork of a large application written in C, which is quite intimidating at the outset.

Tried to attack the problem the simplest way to just fetch my fork and re-build it with the new source, so I boiled it down to this question. Although, I suspect that the right direction for me is something along the lines of Nixpkgs/Create and debug packages in the NixOS Wiki.

Only re-build the package itself

Vladimír Čunát commented that "disabling substitutes makes you rebuild everything that's missing locally, even though I suspect that people asking such a question often only want to rebuild the specified package itself."

(This is probably achieved with nix-build or "just" overriding the original package but could be wrong. The latter is mention (maybe demonstrated even?) in the NixOS wiki article Development environment with nix-shell but haven't been able to read it thoroughly yet.)

Test for reproducibility

One might arrive to formulating this same question if they want to make sure that subsequent builds are deterministic. As Henri Menke comments, one should use nix-build --check for that.

The --check option is easy to miss; it's not documented in man nix-build or at nix-build in the Nix manual, but at nix-store --realize because (as man nix-build explains it):

nix-build is essentially a wrapper around nix-instantiate (to translate a high-level Nix expression to a low-level store derivation) and nix-store --realise (to build the store derivation) [and so] all options not listed here are passed to nix-store --realise, except for --arg and --attr / -A which are passed to nix-instantiate.

See detailed examples in the Nix manual at 18.1. Spot-Checking Build Determinism and the next section right after it.


The relevant parts for the substitute configuration option under the nix.conf section from the Nix manual:

Name

nix.conf — Nix configuration file

Description

Nix reads settings from two configuration files:

  • The system-wide configuration file sysconfdir/nix/nix.conf (i.e. /etc/nix/nix.conf on most systems), or $NIX_CONF_DIR/nix.conf if NIX_CONF_DIR is set.

  • The user configuration file $XDG_CONFIG_HOME/nix/nix.conf, or ~/.config/nix/nix.conf if XDG_CONFIG_HOME is not set.

You can override settings on the command line using the --option flag, e.g. --option keep-outputs false.

The following settings are currently available:

[..]

substitute
If set to true (default), Nix will use binary substitutes if available. This option can be disabled to force building from source.

(Formerly known as use-binary-caches.)


Notes

Setting substitute to false (either with --options or in nix.conf) won't recompile the package if the command issue multiple times. That is, hello above would be compiled from source the first time, and then it will access the already present store path if the command issued again.

This is where it gets fuzzy: it is clear that no recompilation takes place because unless the package's Nix build expression doesn't change, the store output hash won't change either, making the next compilation output equivalent to the previous one, hence the action would be superfluous.

So if one would do some light hacking on a package, and just wanted to try it out locally (e.g., with nix-shell) then one would have to use -I nixpkgs=a/local/nixpkgs/dir to pick up those changes - and eventually do a recompilation? Or should one use nix-build?

See also question How to nix-build again a built store path?

toraritte
  • 6,300
  • 3
  • 46
  • 67
  • 1
    If you want to rebuild an existing store path to check whether it is reproducible, just use `nix-build --check`. – Henri Menke Feb 14 '21 at 10:08