Skip to content

Instantly share code, notes, and snippets.

@toraritte
Created September 30, 2022 10:03
Show Gist options
  • Select an option

  • Save toraritte/e32d4b2e32f07844ad4ae6ee9b204e4f to your computer and use it in GitHub Desktop.

Select an option

Save toraritte/e32d4b2e32f07844ad4ae6ee9b204e4f to your computer and use it in GitHub Desktop.
Progress notes on trying to figure out `overrideAttrs`

Wanted to use the latest TreeSheets, so updated its Nix expression, and ran

nix-shell -I nixpkgs=~/clones/nixpkgs/ -v -p treesheets

Worked like a charm. Then asked if there is a better way (see post), and overrideAttrs was suggested.

NOTE: Do sudo nix-collect-garbage before starting experimenting from scratch.

The plan

Things didn't go smooth on first try, so let's try to make these experiments with slightly more rigour.

Step 0. sudo nix-collect-garbage

Not sure if it matters, but can't hurt. When I first did these steps in anger, the builds failed, then changed seemingly unrelated stuff, and they worked. So:

a. Examine the Nix store after each step for the produced artifacts, b. Write down all the observations

Step 1. Build TreeSheets at this Nixpkgs commit.

git co c55cc9b08c309d26aeac52f88f43702607247b89
nix-shell -I nixpkgs=~/clones/nixpkgs/ -v -p treesheets

Step 2. Do the same on my fork

git co treesheets-to-3130231751_2022-09-26
nix-shell -I nixpkgs=~/clones/nixpkgs/ -v -p treesheets

Step 3. Modify default.nix in step 1. so that it "stands alone"

That is, to be able to build it like nix-build temp.nix and not as nix-shell -I ... -p treesheets.

The Nix expression below seemed to work when messing around, but now pay careful attention to rev, sha256, and version (especially the latter because it seems to have a crucial role - or, at least, has some influence, because some builds seemed to fail when it was not set).

Again, when at this point, try the following, but deviate from it according to the outcomes of a substep:

a. Copy the Nix expression from Step 1. verbatim. b. As step b., but use the Nix expression from Step 2. (again, verbatim) c. Change version to always-latest (because this is supposed to be a helper Nix expression to be used ad hoc, and not an official package)

let
  # This  is  from   Step  1.,  so  the   state  of  the
  # dependencies should  not wreak havoc  when building.
  # (And yet,  it seemed to do  so, but this is  why I'm
  # starting from scratch.)
  nixpkgs_commit = "c55cc9b08c309d26aeac52f88f43702607247b89";
in

{ pkgs
# This is sloppy, but wanted to make it as simple as possible.
? import (builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/${nixpkgs_commit}.zip") {}
}:

# All of  the dependencies are coming  from `pkgs`, so
# took the easy way out and just dropped everything in
# scope.

# QUESTION: Does this affect the outcome?

with pkgs;

# Copy paste contents from (and modify according to the above plan):
# https://github.com/NixOS/nixpkgs/blob/c55cc9b08c309d26aeac52f88f43702607247b89/pkgs/applications/office/treesheets/default.nix

QUESTION nix-shell vs nix-build When I frist tried this with nix-shell, it dropped me into a shell with all of Treesheets' dependencies in scope, but Treesheets itself wasn't built of course, so I did nix-build <temp.nix>. Now, why does nix-shell -p work differently? Or maybe it doesn't, I just don't understand yet. Maybe nix-shell -p works exactly the same, but it specifies the target of -p as a dependency, which is then dropped in the resulting shell so that one can use it to build whatever one is developing. Right?

So if I wanted to drop into a shell with the above <temp.nix>'s TreeSheets, I would have to write another Nix expression (e.g., temp-shell.nix), where <temp.nix> is a dependency, thus forcing it to be built. In theory, because I have no clue how to do that.

Step 4. Try out overrideAttrs

This is how far I got:

let
  nixpkgs_commit = "c55cc9b08c309d26aeac52f88f43702607247b89";
in

{ pkgs
? import (builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/${nixpkgs_commit}.zip") {}
}:

with pkgs;
treesheets.overrideAttrs ( previousAttrs: {
  pname = "treesheets";
  version = "always_latest";
  src = fetchFromGitHub {
    owner = "aardappel";
    repo = "treesheets";
    # rev = "120c10d4d9ea1ce76db5c1bbd6f5d705b397b57d";
    # sha256 = "oXgOvvRoZpueEeWnD3jsc6y5RIAzkXzLeEe7BSErBpw=";
    rev = "4778c343ac78a3b3ccdaf079187b53d8cd64e235";
    sha256 = "sha256-UyltzT9B+7/hME7famQa/XgrDPaNw3apwchKgxwscOo=";
  };
})

It works, but it doesn't seem to have any effect.

How to use overrideAttrs?

Looked up overrideAttrs in the manual, but the example snippet lacks any context, and have more questions now:

4.2. <pkg>.overrideAttrs

The function overrideAttrs allows overriding the attribute set passed to a stdenv.mkDerivation call, producing a new derivation based on the original one. This function is available on all derivations produced by the stdenv.mkDerivation function, which is most packages in the nixpkgs expression pkgs.

Example usage:

helloWithDebug = pkgs.hello.overrideAttrs (finalAttrs: previousAttrs: {
  separateDebugInfo = true;
});

In the above example, the separateDebugInfo attribute is overridden to be true, thus building debug info for helloWithDebug, while all other attributes will be retained from the original hello package.

The argument previousAttrs is conventionally used to refer to the attr set originally passed to stdenv.mkDerivation.

The argument finalAttrs refers to the final attributes passed to mkDerivation, plus the finalPackage attribute which is equal to the result of mkDerivation or subsequent overrideAttrs calls.

If only a one-argument function is written, the argument has the meaning of previousAttrs.

Note Note that separateDebugInfo is processed only by the stdenv.mkDerivation function, not the generated, raw Nix derivation. Thus, using overrideDerivation will not work in this case, as it overrides only the attributes of the final derivation. It is for this reason that overrideAttrs should be preferred in (almost) all cases to overrideDerivation, i.e. to allow using stdenv.mkDerivation to process input arguments, as well as the fact that it is easier to use (you can use the same attribute names you see in your Nix code, instead of the ones generated (e.g. buildInputs vs nativeBuildInputs), and it involves less typing).

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