Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide clear way to install specific package versions in developer environment #1732

Open
SolyomBalint opened this issue Feb 15, 2025 · 1 comment
Labels
enhancement New feature or request

Comments

@SolyomBalint
Copy link

As an embedded Linux developer, my developer environment often requires relatively old and specific package versions. Currently, there is no fully clean way for Nix to use an older version of a package. One way to achieve this in the current devenv is to use nix package versions. After a suitable commit hash is found it can be used as an input in devenv.yaml, or to define an overlay. For example:
devenv.yaml

inputs:
  nixpkgs_2025_01_22:
    url: https://github.com/NixOS/nixpkgs/archive/21808d22b1cda1898b71cf1a1beb524a97add2c4.tar.gz

devenv.nix

{
  pkgs,
  lib,
  config,
  inputs,
  ...
}:
let
  nixpkgs_2025_01_22 = import inputs.nixpkgs_2025_01_22 { system = pkgs.stdenv.system; };
in
{
  # packages
  packages = [
    nixpkgs_2025_01_22.gcc
    nixpkgs_2025_01_22.gnumake
    nixpkgs_2025_01_22.ninja
}

Neither solution is trivial for a beginner nor space efficient. Also, in production getting around such issues can be time-consuming. I have tried to ask the new devenv generate feature with the following prompt:

devenv generate --disable-telemetry an environment with cmake version 3.16

The following devenv.nix was generated:

{ pkgs, lib, config, ... }: {
  packages = [
    (pkgs.cmake.override { version = "3.16"; })
  ];

  # See full reference at https://devenv.sh/reference/options/
}

Unfortunately, this solution ends up in a hard-to-debug error message:

• Building shell ...
warning: creating lock file '/home/balintsolyom/personal/projects/learning_opengl/devenv.lock'
• Using Cachix: devenv
error:
       … while calling the 'derivationStrict' builtin
         at <nix/derivation-internal.nix>:9:12:
            8|
            9|   strict = derivationStrict drvAttrs;
             |            ^
           10|while evaluating derivation 'devenv-shell'
         whose name attribute is located at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/stdenv/generic/make-derivation.nix:336:7

       … while evaluating attribute 'DEVENV_PROFILE' of derivation 'devenv-shell'while calling the 'getAttr' builtin
         at <nix/derivation-internal.nix>:19:19:
           18|       value = commonAttrs // {
           19|         outPath = builtins.getAttr outputName strict;
             |                   ^
           20|         drvPath = strict.drvPath;while calling the 'derivationStrict' builtin
         at <nix/derivation-internal.nix>:9:12:
            8|
            9|   strict = derivationStrict drvAttrs;
             |            ^
           10|while evaluating derivation 'devenv-profile'
         whose name attribute is located at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/stdenv/generic/make-derivation.nix:336:7

       … while evaluating attribute 'passAsFile' of derivation 'devenv-profile'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/trivial-builders/default.nix:60:9:
           59|         inherit buildCommand name;
           60|         passAsFile = [ "buildCommand" ]
             |         ^
           61|           ++ (derivationArgs.passAsFile or [ ]);while evaluating the attribute 'passAsFile'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:87:5:
           86|     # XXX: The size is somewhat arbitrary
           87|     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else [ ];
             |     ^
           88|   }

       … while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:87:18:
           86|     # XXX: The size is somewhat arbitrary
           87|     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else [ ];
             |                  ^
           88|   }

       … in the argument of the not operator
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:87:48:
           86|     # XXX: The size is somewhat arbitrary
           87|     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else [ ];
             |                                                ^
           88|   }

       … while calling the 'lessThan' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:87:48:
           86|     # XXX: The size is somewhat arbitrary
           87|     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else [ ];
             |                                                ^
           88|   }

       … while calling the 'stringLength' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:87:21:
           86|     # XXX: The size is somewhat arbitrary
           87|     passAsFile = if builtins.stringLength pkgs >= 128*1024 then [ "pkgs" ] else [ ];
             |                     ^
           88|   }

       … while calling the 'toJSON' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:82:12:
           81|             nativeBuildInputs buildInputs;
           82|     pkgs = builtins.toJSON chosenOutputs;
             |            ^
           83|     extraPathsFrom = lib.optional includeClosures (writeClosure pathsForClosure);while calling the 'map' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/build-support/buildenv/default.nix:56:19:
           55| let
           56|   chosenOutputs = map (drv: {
             |                   ^
           57|     paths =

       … from call site
         at «github:cachix/devenv/1235cd13f47df6ad19c8a183c6eabc1facb7c399»/src/modules/top-level.nix:15:13:
           14|     name = "devenv-profile";
           15|     paths = lib.flatten (builtins.map drvOrPackageToPaths config.packages);
             |             ^
           16|     ignoreCollisions = true;while calling 'flatten'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:431:13:
          430|   */
          431|   flatten = x:
             |             ^
          432|     if isList x

       … while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:432:5:
          431|   flatten = x:
          432|     if isList x
             |     ^
          433|     then concatMap (y: flatten y) x

       … while calling the 'isList' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:432:8:
          431|   flatten = x:
          432|     if isList x
             |        ^
          433|     then concatMap (y: flatten y) x

       … while calling the 'map' builtin
         at «github:cachix/devenv/1235cd13f47df6ad19c8a183c6eabc1facb7c399»/src/modules/top-level.nix:15:26:
           14|     name = "devenv-profile";
           15|     paths = lib.flatten (builtins.map drvOrPackageToPaths config.packages);
             |                          ^
           16|     ignoreCollisions = true;

       … from call site
         at «github:cachix/devenv/1235cd13f47df6ad19c8a183c6eabc1facb7c399»/src/modules/top-level.nix:15:59:
           14|     name = "devenv-profile";
           15|     paths = lib.flatten (builtins.map drvOrPackageToPaths config.packages);
             |                                                           ^
           16|     ignoreCollisions = true;while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/attrsets.nix:1204:18:
         1203|         mapAttrs
         1204|           (name: value:
             |                  ^
         1205|             if isAttrs value && cond value

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/attrsets.nix:1207:18:
         1206|             then recurse (path ++ [ name ]) value
         1207|             else f (path ++ [ name ]) value);
             |                  ^
         1208|     inwhile calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:254:72:
          253|           # For definitions that have an associated option
          254|           declaredConfig = mapAttrsRecursiveCond (v: ! isOption v) (_: v: v.value) options;
             |                                                                        ^
          255|while evaluating the attribute 'value'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:816:9:
          815|     in warnDeprecation opt //
          816|       { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          817|         inherit (res.defsFinal') highestPrio;

while evaluating the option `packages':

       … while evaluating the attribute 'mergedValue'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:851:5:
          850|     # Type-check the remaining definitions, and merge them. Or throw if no definitions.
          851|     mergedValue =
             |     ^
          852|       if isDefined then

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:853:59:
          852|       if isDefined then
          853|         if all (def: type.check def.value) defsFinal then type.merge loc defsFinal
             |                                                           ^
          854|         else let allInvalid = filter (def: ! type.check def.value) defsFinal;

       … while calling 'merge'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:559:20:
          558|       check = isList;
          559|       merge = loc: defs:
             |                    ^
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:

       … while calling the 'map' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:560:9:
          559|       merge = loc: defs:
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
             |         ^
          561|           imap1 (m: def':

while calling the 'filter' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:560:27:
          559|       merge = loc: defs:
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
             |                           ^
          561|           imap1 (m: def':

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:560:35:
          559|       merge = loc: defs:
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
             |                                   ^
          561|           imap1 (m: def':

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:560:38:
          559|       merge = loc: defs:
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
             |                                      ^
          561|           imap1 (m: def':

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:334:29:
          333|   */
          334|   imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
             |                             ^
          335|

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:334:32:
          333|   */
          334|   imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
             |                                ^
          335|

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:561:21:
          560|         map (x: x.value) (filter (x: x ? value) (concatLists (imap1 (n: def:
          561|           imap1 (m: def':
             |                     ^
          562|             (mergeDefinitions

while evaluating the attribute 'optionalValue'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:863:5:
          862|
          863|     optionalValue =
             |     ^
          864|       if isDefined then { value = mergedValue; }

while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:864:7:
          863|     optionalValue =
          864|       if isDefined then { value = mergedValue; }
             |       ^
          865|       else {};

while evaluating the attribute 'values'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:845:9:
          844|       in {
          845|         values = defs''';
             |         ^
          846|         inherit (defs'') highestPrio;

       … while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:841:11:
          840|           # Avoid sorting if we don't have to.
          841|           if any (def: def.value._type or "" == "order") defs''.values
             |           ^
          842|           then sortProperties defs''.values

while calling the 'any' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:841:14:
          840|           # Avoid sorting if we don't have to.
          841|           if any (def: def.value._type or "" == "order") defs''.values
             |              ^
          842|           then sortProperties defs''.values

while evaluating the attribute 'values'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:944:7:
          943|     in {
          944|       values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
             |       ^
          945|       inherit highestPrio;

while calling the 'concatMap' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:944:16:
          943|     in {
          944|       values = concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs;
             |                ^
          945|       inherit highestPrio;

while calling the 'concatMap' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:831:17:
          830|         # Process mkMerge and mkIf properties.
          831|         defs' = concatMap (m:
             |                 ^
          832|           map (value: { inherit (m) file; inherit value; }) (addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:831:28:
          830|         # Process mkMerge and mkIf properties.
          831|         defs' = concatMap (m:
             |                            ^
          832|           map (value: { inherit (m) file; inherit value; }) (addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))

       … while calling the 'map' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:832:11:
          831|         defs' = concatMap (m:
          832|           map (value: { inherit (m) file; inherit value; }) (addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |           ^
          833|         ) defs;

       … while evaluating definitions from `/home/balintsolyom/personal/projects/learning_opengl/devenv.nix':

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:832:128:
          831|         defs' = concatMap (m:
          832|           map (value: { inherit (m) file; inherit value; }) (addErrorContext "while evaluating definitions from `${m.file}':" (dischargeProperties m.value))
             |                                                                                                                                ^
          833|         ) defs;

       … while calling 'dischargeProperties'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:903:25:
          902|   */
          903|   dischargeProperties = def:
             |                         ^
          904|     if def._type or "" == "merge" then

       … while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/modules.nix:904:5:
          903|   dischargeProperties = def:
          904|     if def._type or "" == "merge" then
             |     ^
          905|       concatMap dischargeProperties def.contents

       … while evaluating the attribute 'value'
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/types.nix:565:38:
          564|               elemType
          565|               [{ inherit (def) file; value = def'; }]
             |                                      ^
          566|             ).optionalValue

       … while calling the 'elemAt' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/lists.nix:334:43:
          333|   */
          334|   imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
             |                                           ^
          335|

       … while calling a functor (an attribute set with a '__functor' attribute)
         at /home/balintsolyom/personal/projects/learning_opengl/devenv.nix:3:6:
            2|   packages = [
            3|     (pkgs.cmake.override { version = "3.16"; })
             |      ^
            4|   ];

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/trivial.nix:966:7:
          965|     { # TODO: Should we add call-time "type" checking like built in?
          966|       __functor = self: f;
             |       ^
          967|       __functionArgs = args;

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:144:34:
          143|       # Re-call the function but with different arguments
          144|       overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
             |                                  ^
          145|       # Change the result of the function call by applying g to it

       … while calling a functor (an attribute set with a '__functor' attribute)
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:144:43:
          143|       # Re-call the function but with different arguments
          144|       overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
             |                                           ^
          145|       # Change the result of the function call by applying g to it

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/trivial.nix:966:7:
          965|     { # TODO: Should we add call-time "type" checking like built in?
          966|       __functor = self: f;
             |       ^
          967|       __functionArgs = args;

       … while calling anonymous lambda
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:136:17:
          135|     in
          136|     mirrorArgs (origArgs:
             |                 ^
          137|     let

       … while evaluating a branch condition
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:148:7:
          147|     in
          148|       if isAttrs result then
             |       ^
          149|         result // {

       … while calling the 'isAttrs' builtin
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:148:10:
          147|     in
          148|       if isAttrs result then
             |          ^
          149|         result // {

       … from call site
         at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/lib/customisation.nix:138:16:
          137|     let
          138|       result = f origArgs;
             |                ^
          139|

       error: at «github:cachix/devenv-nixpkgs/7bd9e84d0452f6d2e63b6e6da29fe73fac951857»/pkgs/by-name/cm/cmake/package.nix:1:1:
            1| { lib
             | ^
            2| , stdenv

       error: function 'anonymous lambda' called with unexpected argument 'version'
✖ Building shell in 6.06s
Error:   × Command `/nix/store/b3xyrhiwbdch46092bsvsnhy67119vsy-nix-2.24-devenv/bin/nix --show-trace --extra-experimental-features nix-command --extra-experimental-features flakes --option
  │ warn-dirty false --keep-going --max-jobs 8 --option eval-cache false --option extra-substituters https://devenv.cachix.org --option extra-trusted-public-keys devenv.cachix.org-
  │ 1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw= nixpkgs-python.cachix.org-1:hxjI7pFxTyuTHn2NkvWCrAUcNZLNS3ZAvfYNuYifcEU= print-dev-env --profile /home/balintsolyom/personal/projects/
  │ learning_opengl/.devenv/gc/shell -vv --log-format internal-json` failed with with exit code 1

It would be a huge enhancement for devenv if there was a standard way provided to access older versions of a given package.

@SolyomBalint SolyomBalint added the enhancement New feature or request label Feb 15, 2025
@trm109
Copy link

trm109 commented Feb 15, 2025

Definitely agree.

I think this functionality could be implemented by adding a robust custom package solution & documentation. I asked a similar question about documentation for implementing custom packages in the Discord. According to Domen, this is in the plans, but it may take some time to fully get there.

In the meantime, if your blocked by missing package versions, try out Flox. Last time I checked, that was one of their biggest selling points, although I've never used it so I'm not sure how good it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants