Question about packaging ElixirLS

Hello, I’m trying to package ElixirLS. As it described in the Building and running section, it has to be built with the mix elixir_ls.release command, which builds language server components as a bunch of .ez archives and adds shell/Bat scripts to run them.

I have come up with a working derivation:

{ stdenv, elixir, erlang, git, cacert
}:
stdenv.mkDerivation rec {
  name = "elixir-ls-${version}";
  version = "0.2.26";
  src = builtins.fetchGit {
    url = https://github.com/elixir-lsp/elixir-ls;
    rev = "ba1c9cb86545298c487cf77a166c203fc44ce8dd";
  };
  buildInputs = [elixir erlang git cacert];
  buildPhase = ''
    mkdir -p $PWD/.hex
    export HOME=$PWD/.hex

    mix local.hex --force
    mix local.rebar --force

    mix deps.get
    mix compile
  '';
  installPhase = ''
    mkdir -p $out/bin

    mix elixir_ls.release --destination $out/bin
  '';
}

While it works, I have a question about the approach used here. Is mkDerivation the right tool for the job? Nixpkgs manual mentions buildHex and buildMix. I cannot use buildHex because ElixirLS is not published in Hex, and it seems like buildMix is intended to use for “library” packages.

Also, it fails if I don’t override HOME in buildPhase, because mix local.hex tries to write to $HOME, which is not writable:

these derivations will be built:
  /nix/store/fc3660sa7ifmj3ng7xlx3jxqjb7bc2jz-elixir-ls-0.2.26.drv
building '/nix/store/fc3660sa7ifmj3ng7xlx3jxqjb7bc2jz-elixir-ls-0.2.26.drv'...
unpacking sources
unpacking source archive /nix/store/0ylyd74314yvzwxwshnss1ywqnn02cgf-source
source root is source
patching sources
configuring
no configure script, doing nothing
building
** (File.Error) could not make directory (with -p) "/homeless-shelter/.mix/archives/hex-0.20.1": no such file or directory
    (elixir) lib/file.ex:314: File.mkdir_p!/1
    (mix) lib/mix/tasks/archive.install.ex:113: Mix.Tasks.Archive.Install.install/3
    (mix) lib/mix/local/installer.ex:107: Mix.Local.Installer.local_install/3
    (mix) lib/mix/task.ex:331: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2
builder for '/nix/store/fc3660sa7ifmj3ng7xlx3jxqjb7bc2jz-elixir-ls-0.2.26.drv' failed with exit code 1
error: build of '/nix/store/fc3660sa7ifmj3ng7xlx3jxqjb7bc2jz-elixir-ls-0.2.26.drv' failed
direnv: error ../.envrc is blocked. Run `direnv allow` to approve its content.

This feels like a hack, is there any better way to do it?

Thanks!

Hello. Just a heads up to tell you that i see this. There is work in progress to clean up a bit the state of the beam ecosystem.

For now i would say that this is an acceptable solution. We need to provide a better solution for how to build, but what you have is probably the best solution so far.

1 Like

I tried this derivation in NixOS today and it doesn’t work (it worked in Nix on macOS though); it fails on mix local.hex with the following error:

** (Mix) httpc request failed with: {:failed_connect, [{:to_address, {'repo.hex.pm', 443}}, {:inet, [:inet], :nxdomain}]}

Could not install Hex because Mix could not download metadata at https://repo.hex.pm/installs/hex-1.x.csv.

Apparently, networking isn’t available inside a buildPhase (/etc/resolv.conf is not accessible). Is there any workaround for this?

You’ll need to add --option sandbox relaxed to your nix-build command.
This also took me some time to find out…

DianaOlympos was already so kind to add this to the Nixpkgs BEAM manual (master).
But I’m not sure if this has already landed there.

PS: Additionally you can add to your derivation __noChroot = true; to get a proper error message.

1 Like