Elixir and Erlang version override

I’m aware that this can (maybe should) be done by pinning an old version of nixpkgs. Anyhow I’m struggling to understand why this doesn’t work:

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

    nativeBuildInputs = with pkgs; [

        (elixir.override{
            version = "1.13.2";
            minimumOTPVersion = "22";
            maximumOTPVersion = "24";
            erlang = (erlang.override {
                version = "24.3.4.17";
                });
         })
    ];
}

(pinning to 24 here is just for https://hexdocs.pm/elixir/1.13.2/compatibility-and-deprecations.html, i assume it’s not part of the problem?)

Then

/nix/store/pii4mjz4ycc4sidbv7fy6n724z76qrsm-erlang-24.3.4.17
/nix/store/bwbwyz4yk13wnk3zfx1hwx9v18rl9cw1-elixir-1.13.2

are built. But when I ask for the version:

[nix-shell:~/test]$ realpath $(which elixirc)
/nix/store/bwbwyz4yk13wnk3zfx1hwx9v18rl9cw1-elixir-1.13.2/bin/elixirc

[nix-shell:~/test]$ elixirc --version
Erlang/OTP 27 [erts-15.2.7.3] [source] [64-bit] [smp:22:22] [ds:22:22:10] [async-threads:1] [jit:ns]

Elixir 1.18.4 (compiled with Erlang/OTP 27)

Clearly elixir version is 1.18.4 and OTP 27 which is what i also get by just doing nix-shell -p elixir.

Any pointers to why it builds, and that I still get 1.18.4 would be appreciated.

1 Like

Overriding a version does nothing but making you rebuild the old thing with a different name.

You need to override full source.

Though for elixir things are slightly different anyway.

  1. You need a beam package set with the overriden Erlang
  2. Use that to create a proper elixir which again overrides the source.

I will lookup an example later when the kids are in bed.

1 Like

This probably won’t be exactly what you’re looking for, but here’s how I typically setup my Elixir dev flakes:

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

  outputs = { self, nixpkgs, ... }:
    let
      system = "x86_64-linux";

      pkgs = import nixpkgs { inherit system; };
      beamPkgs = with pkgs.beam_minimal; packagesWith interpreters.erlang_27;
      erlang = beamPkgs.erlang;
      elixir = beamPkgs.elixir_1_17;
    in
    {
      devShells."${system}".default = pkgs.mkShell {
        buildInputs = [
          erlang
          elixir

          beamPkgs.hex
          beamPkgs.elixir-ls

          pkgs.inotifyTools
          pkgs.nodejs
        ];

        ERL_INCLUDE_PATH = "${erlang}/lib/erlang/usr/include";
        ERL_AFLAGS = "-kernel shell_history enabled";

        shellHook = ''
          # Allow mix to work on local directory
          mkdir -p .nix-mix
          mkdir -p .nix-hex
          export MIX_HOME=$PWD/.nix-mix
          export HEX_HOME=$PWD/.nix-hex
          export ERL_LIBS=$HEX_HOME/lib/erlang/lib

          # Concat paths
          export PATH=$MIX_HOME/bin:$PATH
          export PATH=$MIX_HOME/escripts:$PATH
          export PATH=$HEX_HOME/bin:$PATH

          # "Run: `mix archive.install hex phx_new` for phoenix."
        '';
      };
    };
}

The manual has additional information, though you’ve probably already checked that. Not gonna lie, things are a bit awkward right now, ergonomically. I’m not sure if that’s avoidable or not, but rest assured you aren’t the only one who’s had some head-scratchers. :slight_smile:

2 Likes

Yeah, this is exactly what I was referring to yesterday, but I got distracted by my kids and bedtime stories.

Also, I might borrow some parts of the shell hook.

2 Likes

It’s a combination of my own derping around, a blog post (I think?) where somebody had that neat idea for per-project hex storage, and possibly slop at one point or another. I also have one that works for livebook and Nx, mostly, if you want to see it.

1 Like