How to use a newer version of bzip2 in a nix-shell

Hello everyone!

I’m really excited to use NixOs and learn how to make the most out of it!

Now I need to change the version of bzip2 for a OpenEmbedded project based on
archives that are incompatible with the current stable bzip version 1.0.6,
present in nixos-stable.

I use a FHSUserEnv for the build environnement, where I tried to install another
version from unstable. But the unstable version enters in conflict with the
stable one. Here is a minimal reproduciton:

{ pkgs ? import <nixpkgs> {}, ...}:

let
    unstable = import <nixos-unstable> {};
in
with pkgs;
(pkgs.buildFHSUserEnv {
  name = "bzip2-env";

  targetPkgs = pkgs: (with pkgs; [
    unstable.bzip2
  ]);
}).env

When running nix-shell, I get, among other collisions:

collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzless' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzless'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzcat' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzcat'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzfgrep' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzfgrep'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzdiff' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzdiff'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzip2' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzip2'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzmore' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzmore'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzip2recover' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzip2recover'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bunzip2' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bunzip2'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzegrep' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzegrep'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzgrep' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzgrep'
collision between `/nix/store/966d6qhlsy64idfq1sfx5j0lyalyxc38-bzip2-1.0.6.0.1-bin/bin/bzcmp' and `/nix/store/fk8lj79i2jsd8psj3sk9qn9zfhmhf74s-bzip2-1.0.6.0.1-bin/bin/bzcmp'

How can I express that I want the unstable package to replace the stable one?

I also tried to use an overlay:

self: super:
{
  bzip2 = super.bzip2.overrideAttrs (old: {
    version = "1.0.8";
    patches = [];
  });
}

My problem with this, is that this seems to trigger way to much package
recompilation. All bzip2-dependant get to be rebuilt.

Is there a lighter solution using overlays ?

I feel like I’m missing something as my use case seems to enter in nix’s field.

maybe try lib.hiPrio or lib.lowPrio ?

Thanks ! I finally found how to use this:

{ pkgs ? import <nixpkgs> {}, ...}:

let
    unstable = import <nixos-unstable> {};
in
with pkgs;
(pkgs.buildFHSUserEnv {
  name = "bzip2-env";

  targetPkgs = pkgs: (with pkgs; [
    (hiPrio unstable.bzip2)
  ]);
}).env

Looks like the resulting bzip2 isn’t actually compatible with the installed libc:

$ bzip2 --version
Inconsistency detected by ld.so: dl-call-libc-early-init.c: 37: _dl_call_libc_early_init: Assertion `sym != NULL' failed!

Do I use hiPrio correctly?

Is my use case far from what nix offers ?

Do you really need a buildFHSUserEnv ?
BuildFHSUserEnv tries to mimic a traditional linux distro, and comes with the same limitations: you cannot mix two versions of the same library.
With mkShell you would probably not have this issue.

1 Like

Thanks for the reply. I needed this for an environment where FHSUserEnv is required: an OpenEmbedded project.

Now I solved this using an ubuntu docker container, so I don’t need any of this anymore. I was just curious of how to do that in a Nixos, with an FHSUserEnv or in my nix configuration. I also tried with an overlay. But every possiblity ended up being too hard for a nix newbie like me.

An easy solution (if it works) is to use buildFHSUserEnv without an override but with an old nixpkgs which contains the right revision of bzip2.

To use another version of nixpkgs, instead of nix-shell run nix-shell -I nixpkgs=channel:nixos-19.03 for example.

Note that using an old nixpkgs has security implications, though.