Package version arguments vs. generic package arguments

I have recently seen PRs, where the commonly-used pattern:

Derivation:

{ jdk, ...}:

all-packages.nix:

somepackage = {
  jdk = jdk8;
};

is replaced by, or not used in favor of, another commonly-used pattern:

{ jdk8, ...}:

let
  jdk = jdk8;
in mkDerivation {
  # ...
  buildInputs = [ jdk8 ];
  # ...
}

I wonder if there is any consensus on which pattern is preferred. Personally, I dislike the latter pattern, because it makes overriding packages less intuitive. E.g.

somepackage.override { jdk = jdk11; };

becomes:

somepackage.override { jdk8 = jdk11; };

Moreover, if the jdk8 attribute is later changed to jdk11, overrides that a user may have become invalid, because the jdk8 attribute is not available anymore.

I can see that for packages that are very strongly tied to particular versions of a runtime or library, it makes sense to hardcode the dependency. However, newer versions of e.g. Java runtimes or CUDA toolkits are generally backwards compatible.

Any opinions?

2 Likes

That’s mostly what happened in #89731. I tried to override as much as possible in all-packages.nix, and only change the derivation file when I got a build error with the new jdk. In some other cases it was infeasible to override from all-package.nix, e.g. in chromium, also in that case I changed the derivation file.

Sorry, I probably shouldn’t have cited this PR (which is very useful), so I have removed the link.

It’s something I just noticed in various PRs that both patterns occur and reviewers sometimes ask people to modify derivations in one direction or the other.

I found this thread while researching examples for a good way to do the jdk version in the clojure derivation more configurable. In this particular case, I want to default to jdk11 (since clojure officially only supports java LTS releases).

I see pros and cons on both proposed patterns, I’d like to know what do you think about a 3rd pattern:

{ pkgs 
, jdkPkg ? pkgs.pkg11  
, ...}:

mkDerivation {
  # ...
  buildInputs = [ jdkPkg ];
  # ...
}

IMO that makes clear that there is a preferred jdk version, but overriding packages is still intuitive and changes to the version will not break user overrides. Also, it makes unnecessary to update all-packages.nix

This is also my experience, and because of this, my personal preference is to:

  • generally: use jdk in default.nix (pointing to the latest JDK)
  • when a package does not work with the latest JDK: use jdk8 (or whatever) in the package’s default.nix.

This helps us detect problems as soon as possible, and reduces spreading information between all-packages.nix and default.nix.

You’re right that, for packages that need a particular JDK version, overriding the JDK becomes a bit awkward - but that should be the exception rather than the norm anyway.

(I’m not strongly opposed to using jdk in default.nix and overriding it as needed in all-packages.nix, though. By the way, for python we should explicitly use python3 as discussed in Should `python` point to python3? - #7 by jonringer)

This recently also came up in Retirement of old OpenJDK releases? and there doesn’t seem to be consensus about it, btw :wink: .

There is no consensus and it’s an easy thing to bikeshed about.

I have an opinion (as stated in the first post). But I care more about having a rule than it being my preferred rule, since now PR submitters will get comments (or not) based on which reviewer looks at a PR. This also happens in somewhat similar cases (e.g. should the darwin frameworks that a derivation uses be enumerated in all-packages.nix or can a derivation just use e.g. darwin.Security).

Or perhaps we don’t need a rule, but we should not hold up PRs based on such preferences.

1 Like

Totally agree, but it seems difficult to find a consensus.

I want to create a PR for the clojure derivation, but now I’m even more unsure about the pattern to use. BTW, do you see problems with the 3rd pattern I proposed in my previous post?

In general, I favor putting the jdk = jdk8 in all-packages.nix, since it makes sprints such as https://github.com/NixOS/nixpkgs/pull/89731 easier to handle.

Other then that, the very uncommon (for AFAIK) pattern with pkgs imported to the derivation, might introduce an unjustified increase in evaluation time - I can’t find a metric for that, but in general using pkgs inside a derivation feels bad to me.

2 Likes