Should mkDerivation list attributes such as buildInputs be sorted?

In packaging, do we care about the order that packages appear in buildInputs etc.?

I’m asking because sorting these has the advantage of easing refactorings without disturbing users.

One example for this would be generic multi-version derivations with version and/or platform specific dependencies.

Take this pseudo-code for example:

  buildInputs = [
    foo
  ] ++ lib.optionals (isPlatformX) [
    libX
  ] ++ lib.optionals (isPlatformY) [
    libY
  ] ++ lib.optionals (lib.versionAtLeast version "1.0") [
    bar
  ];

If you wanted to provide a new dependency for version 2.0, you’d do this:

  buildInputs = [
    foo
  ] ++ lib.optionals (isPlatformX) [
    libX
  ] ++ lib.optionals (isPlatformY) [
    libY
  ] ++ lib.optionals (lib.versionAtLeast version "1.0") [
    bar
  ] ++ lib.optionals (lib.versionAtLeast version "2.0") [
    baz
  ];

But what if you wanted to drop support for versions <1.0 now? You’d want to do this:

  buildInputs = [
    foo
    bar
  ] ++ lib.optionals (isPlatformX) [
    libX
  ] ++ lib.optionals (isPlatformY) [
    libY
  ] ++ lib.optionals (lib.versionAtLeast version "2.0") [
    baz
  ];

However, that would result in a rebuild of all versions of the package because the order of buildInputs is now different.

If the list was normalised, you’d be able to change the order you declare the elements in as much as you wanted to without affecting the derivation.

What would be reasons against normalising mkDerivation arguments?

1 Like

I guess the main risk would be any derivations where specific inputs need to appear before/after other inputs in order for it to build/run correctly?

2 Likes

Are there any practical examples of that?

I feel like arguably such derivations should not exist in the first place, because breakage caused by that sounds extremely hard to debug.

If there is a better way than relying on list order, surely that way should be taken, so I’d love to see if there are any packages where it’s impossible to do this any other way.

1 Like

I assume, at minimum, anything that builds a *PATH or a sequence of potentially-overriding arguments could be order sensitive under the right circumstances. Yeah?

I can’t say I know of one, but I’d bet at least a few exist. Grepping around, this smells about like I’d expect:

2 Likes

If there are very few known instances of order being important, an opt-out might be appropriate.

Propagation is the most common culprit. For example, if you have anything built with python3.pkgs.buildPythonApplication, it might shadow Python environment created with python3.withPackages … that comes after it.

That’s why we are clearing propagation out in e.g. Meson, gtk-doc, etc.:

1 Like

Yep, I’d just like to know what those circumstances are :slight_smile: I’m not saying it’s not a valid use case, but it’s one I find hard to imagine. How often do we really have two dependencies with matching things in PATH, where one is a subset of the other but needs to replace some binaries for some reason? And is there perhaps a better solution for those cases?

Having an explicit opt-in would actually help with debugging such derivations, so I think this is an argument for what @Atemu suggests. Assuming the exceptions can be detected.

1 Like