Using non-free libraries in flakes

Hello!

I’m trying to use nix flakes to package some development code and
provide the relevant development environment. However, one of the
python libraries I need uses mkl, and nix develop refuses to fully
evaluate because of this (as it’s unfree).

What then, should I do to enable the use of this unfree library in a
flake?

Thanks,

Sam

3 Likes

This should be the same for most nix packages usage:

$ cat ~/.config/nixpkgs/config.nix
{
  allowUnfree = true;
}

It’s set to true there. Error is as follows:

error: --- ThrownError -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
Package ‘mkl-2020.1.217’ in /nix/store/2gvpjwk27dng6c6vw3q3dpfdbza91wmn-source/pkgs/development/libraries/science/math/mkl/default.nix:151 has an unfree license (‘issl’), refusing to evaluate.

a) For `nixos-rebuild` you can set
  { nixpkgs.config.allowUnfree = true; }
in configuration.nix to override this.

b) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
  { allowUnfree = true; }
to ~/.config/nixpkgs/config.nix.

(use '--show-trace' to show detailed location information)

nix-shell with flake-compatibility works, however.

Thanks,

Sam

do you mind pasting the command that’s failing?

you mention nix develop, but that’s not an official nix command (at least on 2.3.7)

EDIT: I guess nix develop is only available on the nixFlakes verions of nix cli.

Flakes evaluations are pure and therefor don’t source configuration from the user’s home.

The issue is that when using nixpkgs.legacyPackages.x86_64-linux.mkl, that instance of nixpkgs has already been configured. Instead, try importing and constructing another instance of nixpkgs with allowUnfree = true; in the config.

Before:

{
  description = "Flake utils demo";

  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let pkgs = nixpkgs.legacyPackages.${system}; in
      {
        defaultPackage = pkgs.mkl;
      }
    );
}

After:

{
  description = "Flake utils demo";

  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          config = { allowUnfree = true; };
        };
      in 
      {
        defaultPackage = pkgs.mkl;
      }
    );
}
9 Likes

So does this also mean that flakes do not take into account local overlays, and really anything else mentioned pkgs/top-level/impure.nix?

Actually, I haven’t checked what it does with paths starting with ~/. But it’s not in the spirit of Flakes if it works.

One of the goals is to allow caching of evaluations, which requires to turn off sources of impurities. So builtins like builtins.currentTime, builtins.currentSystem, builtins.getEnv are also disabled or return default values.

4 Likes

This works, mostly. If I want to specify a specific version of nixpkgs
with

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-20.03";

I get an error about attribute currentSystem being missing:

warning: updating lock file '.../flake.lock':
* Updated 'nixpkgs': 'github:NixOS/nixpkgs/cb1996818edf506c0d1665ab147c253c558a7426' -> 'github:NixOS/nixpkgs/feb9c28902eca0384484004e0b7dfe5ac8661d6c'
warning: Git tree '...' is dirty
error: --- EvalError ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nix
at: (90:39) in file: /nix/store/hbqx9yg7zc2w70l3myhgrsyhblib5bxm-source/pkgs/top-level/impure.nix

    89|                 else (if args ? localSystem then {}
    90|                       else { system = builtins.currentSystem; }) // localSystem;
      >                                       ^
    91| })

attribute 'currentSystem' missing
(use '--show-trace' to show detailed location information)

Thanks,

Sam

As @zimbatm mentioned

One of the goals is to allow caching of evaluations, which requires to turn off sources of impurities. So builtins like builtins.currentTime , builtins.currentSystem , builtins.getEnv are also disabled or return default values.

you’ll want to replace it with your actual system

nix-repl> lib.platforms.all
[ "aarch64-linux" "armv5tel-linux" "armv6l-linux" "armv7a-linux" "armv7l-linux" "mipsel-linux" "i686-cygwin" "i686-freebsd" "i686-linux" "i686-netbsd" "i686-openbsd" "x86_64-cygwin" "x86_64-freebsd" "x86_64-linux" "x86_64-netbsd" "x86_64-openbsd" "x86_64-solaris" "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" "x86_64-windows" "i686-windows" "wasm64-wasi" "wasm32-wasi" "x86_64-redox" "powerpc64le-linux" "riscv32-linux" "riscv64-linux" "arm-none" "armv6l-none" "aarch64-none" "avr-none" "i686-none" "x86_64-none" "powerpc-none" "msp430-none" "riscv64-none" "riscv32-none" "vc4-none" "js-ghcjs" "aarch64-genode" "i686-genode" "x86_64-genode" ]

in your case, it’s likely x86_64-linux assuming you’re on a 64bit linux machine

1 Like

Like this assuming you only care about one system type: https://github.com/ryantm/nixpkgs-update/blob/5749f0029adbf4599b27f5b60a4d7d3d9b88c28d/flake.nix#L20

1 Like

I potentially care about more than one system type. I had been using
flake-utils and eachDefaultSystem. I ended up adding inherit system;
in the import nixpkgs... and it works.

Thanks,

Sam

2 Likes

Anyone has any idea how to solve this for the nix run and nix shell command?

For example:

nix run nixpkgs/release-20.09#non-free-software
nix shell nixpkgs/release-20.09#non-free-software
2 Likes

I tend to use NIXPKGS_ALLOW_UNFREE=1 nix {run,shell} --impure nixpkgs/release-20.09#package for one offs.

6 Likes

Thank you, I wasn’t aware it supported impure, that solves my problem for one-offs.

2 Likes

Related: check-meta.nix: Fix message for `nix build` users as well by doronbehar · Pull Request #101367 · NixOS/nixpkgs · GitHub .

Not something I am proud of but I prefer it to either using --impure or importing the pkgs with a proper config, I forked nixpkgs with allowUnfree in check-meta.nix that always returns true:

  allowUnfree = config.allowUnfree or true
    || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";

Despise me

I found this post after hitting the same problem and searching on Google. If anyone else finds this in the future the below works for me. Note the inherit system in the nixpkgs argument

{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, flake-utils, nixpkgs}:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          config = { allowUnfree = true; };
        };
      in {
        devShell = pkgs.mkShell {
          buildInputs = with pkgs;[
            wrangler
            cloudflared
          ];
        };
      }
    );
}
10 Likes

Wow. That finally helped me.

That’s completely non-obvious to me, as the original spelling had .legacyPackages.${system}, so I was trying all manner of syntax where I crammed the .legacyPackages in as well. Also, import nixpkgs { system = ${system}; ... which apparently is not equivalent.

All this is Very Hard ™ to figure out without a full understanding of the Nix language and all the various relations between NixOs, flakes, home-manager etc.

Just for anyone else who like a visual demonstration: before

flake-utils.lib.eachDefaultSystem (system: let
  pkgs = nixpkgs.legacyPackages.${system};

after

flake-utils.lib.eachDefaultSystem (system: let
  pkgs = import nixpkgs { inherit system; config.allowUnfree = true; };