Building GNU hello with custom version

I’m trying to build GNU hello with version 2.9 (nixpkgs defaults to 2.10). I used the following nix expression for a nix-shell:

let pkgs = import <nixpkgs> {};
    hello29 = pkgs.hello.overrideAttrs (_oldAttrs: rec { version = "2.9"; });
in
  pkgs.mkShell { buildInputs = [ hello29 ]; }

While this causes nix to compile GNU hello, it still uses the sources for 2.10, so I’m still running hello 2.10 in the shell.

Maybe the src attribute is not automatically recalculated when version changes? Can I somehow enforce that?

1 Like

Maybe the src attribute is not automatically recalculated when version changes? Can I somehow enforce that?

That is indeed true. The src attribute is not used for generating building instructions, but rather a meta information, which should be provided in packages.

If you want to build an older version of the package, you could either override the src statement( with something like fetchurl or fetchFromGithub and an older version of the gnu hello source files) or you could check out an older version of the nixpkgs repo and use that:

nix-shell -I nixpkgs=path-to-your-local-nixpkgs-repo -p pkgs.your-package
1 Like

That’s (unfortunately) correct. You also have to override the src attribute to ensure an older version is fetched.

See Avoid rec expresions in nixpkgs? - #4 by jtojnar onwards for a recent technical discussion.

1 Like

Can someone go into more technical detail on this?

here is the relevant hello nix derivation

{ stdenv, fetchurl }:

stdenv.mkDerivation rec {
  pname = "hello";
  version = "2.10";

  src = fetchurl {
    url = "mirror://gnu/hello/${pname}-${version}.tar.gz";
    sha256 = "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i";
  };

One would suspect that since fetchUrl uses version it should now point to a different version.
(The sha256 would be incorrect but that’s another point all together)

I guess because it only overrides “attributes”; and the attribute at that point is src

Here is a little demo I was playing with:

let pkgs = import <nixpkgs> {};
in
let my-pkg = pkgs.stdenv.mkDerivation rec {
          name = "my-pkg";
          version = "1.3";
          src = builtins.fetchurl {
          		url = "http://ftp.gnu.org/gnu/hello/hello-${version}.tar.gz";
          		sha256 = "1xi3jv67fq3mx9wlqba2hpxbcj4m5lms04hi0mh1f366zdhw5vi1";
          	};
          };
    override-pkg = my-pkg.overrideAttrs (_oldAttrs: rec {
    		version = "2.0";
    	});
in
	pkgs.lib.traceVal "${override-pkg.version} ${override-pkg.src}"

overrideAttrs just calls mkDerivation again with the same calculated arguments, only replacing the arguments that were returned by the function passed to overrideAttrs:

Since you did not return a new src, the overridden derivation used the old one, which used the version value that was in scope when it was created (line 5 in your example).

Nix needs to be even lazier :wink:
Moar lazy please.