summary refs log tree commit diff
path: root/pkgs/development/beam-modules
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
committerAlyssa Ross <hi@alyssa.is>2021-08-04 10:43:07 +0000
commit62614cbef7da005c1eda8c9400160f6bcd6546b8 (patch)
treec2630f69080637987b68acb1ee8676d2681fe304 /pkgs/development/beam-modules
parentd9c82ed3044c72cecf01c6ea042489d30914577c (diff)
parente24069138dfec3ef94f211f1da005bb5395adc11 (diff)
downloadnixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.gz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.bz2
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.lz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.xz
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.tar.zst
nixpkgs-62614cbef7da005c1eda8c9400160f6bcd6546b8.zip
Merge branch 'nixpkgs-update' into master
Diffstat (limited to 'pkgs/development/beam-modules')
-rw-r--r--pkgs/development/beam-modules/build-erlang-mk.nix85
-rw-r--r--pkgs/development/beam-modules/build-hex.nix4
-rw-r--r--pkgs/development/beam-modules/build-mix.nix141
-rw-r--r--pkgs/development/beam-modules/build-rebar3.nix62
-rw-r--r--pkgs/development/beam-modules/default.nix146
-rw-r--r--pkgs/development/beam-modules/elixir_ls.nix71
-rw-r--r--pkgs/development/beam-modules/elvis-erlang/default.nix46
-rw-r--r--pkgs/development/beam-modules/elvis-erlang/rebar-deps.nix168
-rw-r--r--pkgs/development/beam-modules/erlang-ls/default.nix47
-rw-r--r--pkgs/development/beam-modules/erlang-ls/rebar-deps.nix219
-rw-r--r--pkgs/development/beam-modules/erlfmt/default.nix20
-rw-r--r--pkgs/development/beam-modules/fetch-hex.nix4
-rw-r--r--pkgs/development/beam-modules/fetch-mix-deps.nix58
-rw-r--r--pkgs/development/beam-modules/fetch-rebar-deps.nix6
-rw-r--r--pkgs/development/beam-modules/hex/default.nix12
-rw-r--r--pkgs/development/beam-modules/lib.nix4
-rwxr-xr-xpkgs/development/beam-modules/mix-bootstrap108
-rw-r--r--pkgs/development/beam-modules/mix-release.nix117
-rw-r--r--pkgs/development/beam-modules/pc/default.nix10
-rw-r--r--pkgs/development/beam-modules/pgsql/default.nix8
-rw-r--r--pkgs/development/beam-modules/rebar3-nix/default.nix18
-rw-r--r--pkgs/development/beam-modules/rebar3-proper/default.nix13
-rw-r--r--pkgs/development/beam-modules/rebar3-release.nix153
-rw-r--r--pkgs/development/beam-modules/webdriver/default.nix8
24 files changed, 1111 insertions, 417 deletions
diff --git a/pkgs/development/beam-modules/build-erlang-mk.nix b/pkgs/development/beam-modules/build-erlang-mk.nix
index 4dedf782b75..d1afa55387d 100644
--- a/pkgs/development/beam-modules/build-erlang-mk.nix
+++ b/pkgs/development/beam-modules/build-erlang-mk.nix
@@ -1,30 +1,33 @@
 { stdenv, writeText, erlang, perl, which, gitMinimal, wget, lib }:
 
-{ name, version
+{ name
+, version
 , src
 , setupHook ? null
-, buildInputs ? []
-, beamDeps ? []
+, buildInputs ? [ ]
+, beamDeps ? [ ]
 , postPatch ? ""
 , compilePorts ? false
 , installPhase ? null
 , buildPhase ? null
 , configurePhase ? null
-, meta ? {}
+, meta ? { }
 , enableDebugInfo ? false
-, ... }@attrs:
+, buildFlags ? [ ]
+, ...
+}@attrs:
 
-with stdenv.lib;
+with lib;
 
 let
   debugInfoFlag = lib.optionalString (enableDebugInfo || erlang.debugInfo) "+debug_info";
 
   shell = drv: stdenv.mkDerivation {
-          name = "interactive-shell-${drv.name}";
-          buildInputs = [ drv ];
-    };
+    name = "interactive-shell-${drv.name}";
+    buildInputs = [ drv ];
+  };
 
-  pkg = self: stdenv.mkDerivation ( attrs // {
+  pkg = self: stdenv.mkDerivation (attrs // {
     app_name = name;
     name = "${name}-${version}";
     inherit version;
@@ -33,39 +36,48 @@ let
 
     inherit src;
 
-    setupHook = if setupHook == null
-    then writeText "setupHook.sh" ''
-       addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
-    ''
-    else setupHook;
+    setupHook =
+      if setupHook == null
+      then
+        writeText "setupHook.sh" ''
+          addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
+        ''
+      else setupHook;
 
-    buildInputs = [ erlang perl which gitMinimal wget ];
+    buildInputs = buildInputs ++ [ erlang perl which gitMinimal wget ];
     propagatedBuildInputs = beamDeps;
 
-    configurePhase = if configurePhase == null
-    then ''
-      runHook preConfigure
+    buildFlags = [ "SKIP_DEPS=1" ]
+      ++ lib.optional (enableDebugInfo || erlang.debugInfo) ''ERL_OPTS="$ERL_OPTS +debug_info"''
+      ++ buildFlags;
+
+    configurePhase =
+      if configurePhase == null
+      then ''
+        runHook preConfigure
 
-      # We shouldnt need to do this, but it seems at times there is a *.app in
-      # the repo/package. This ensures we start from a clean slate
-      make SKIP_DEPS=1 clean
+        # We shouldnt need to do this, but it seems at times there is a *.app in
+        # the repo/package. This ensures we start from a clean slate
+        make SKIP_DEPS=1 clean
 
-      runHook postConfigure
-    ''
-    else configurePhase;
+        runHook postConfigure
+      ''
+      else configurePhase;
 
-    buildPhase = if buildPhase == null
-    then ''
+    buildPhase =
+      if buildPhase == null
+      then ''
         runHook preBuild
 
-        make SKIP_DEPS=1 ERL_OPTS="$ERL_OPTS ${debugInfoFlag}"
+        make $buildFlags "''${buildFlagsArray[@]}"
 
         runHook postBuild
-    ''
-    else buildPhase;
+      ''
+      else buildPhase;
 
-    installPhase =  if installPhase == null
-    then ''
+    installPhase =
+      if installPhase == null
+      then ''
         runHook preInstall
 
         mkdir -p $out/lib/erlang/lib/${name}
@@ -85,13 +97,14 @@ let
         fi
 
         runHook postInstall
-    ''
-    else installPhase;
+      ''
+      else installPhase;
 
     passthru = {
       packageName = name;
       env = shell self;
       inherit beamDeps;
     };
-});
-in fix pkg
+  });
+in
+fix pkg
diff --git a/pkgs/development/beam-modules/build-hex.nix b/pkgs/development/beam-modules/build-hex.nix
index 27ce64582f3..1ebe3760ec8 100644
--- a/pkgs/development/beam-modules/build-hex.nix
+++ b/pkgs/development/beam-modules/build-hex.nix
@@ -1,11 +1,11 @@
-{ stdenv, buildRebar3, fetchHex }:
+{ lib, buildRebar3, fetchHex }:
 
 { name, version, sha256
 , builder ? buildRebar3
 , hexPkg ? name
 , ... }@attrs:
 
-with stdenv.lib;
+with lib;
 
 let
   pkg = self: builder (attrs // {
diff --git a/pkgs/development/beam-modules/build-mix.nix b/pkgs/development/beam-modules/build-mix.nix
index 9aebad2dabf..728d249c97d 100644
--- a/pkgs/development/beam-modules/build-mix.nix
+++ b/pkgs/development/beam-modules/build-mix.nix
@@ -3,98 +3,83 @@
 { name
 , version
 , src
-, setupHook ? null
-, buildInputs ? []
-, beamDeps ? []
+, buildInputs ? [ ]
+, nativeBuildInputs ? [ ]
+, beamDeps ? [ ]
+, propagatedBuildInputs ? [ ]
 , postPatch ? ""
 , compilePorts ? false
-, installPhase ? null
-, buildPhase ? null
-, configurePhase ? null
-, meta ? {}
+, meta ? { }
 , enableDebugInfo ? false
-, ... }@attrs:
-
-with stdenv.lib;
+, mixEnv ? "prod"
+, ...
+}@attrs:
 
+with lib;
 let
-
-  debugInfoFlag = lib.optionalString (enableDebugInfo || elixir.debugInfo) "--debug-info";
-
   shell = drv: stdenv.mkDerivation {
-          name = "interactive-shell-${drv.name}";
-          buildInputs = [ drv ];
-    };
-
-  bootstrapper = ./mix-bootstrap;
+    name = "interactive-shell-${drv.name}";
+    buildInputs = [ drv ];
+  };
 
-  pkg = self: stdenv.mkDerivation ( attrs // {
+  pkg = self: stdenv.mkDerivation (attrs // {
     name = "${name}-${version}";
-    inherit version;
-
-    dontStrip = true;
-
-    inherit src;
-
-    setupHook = if setupHook == null
-    then writeText "setupHook.sh" ''
-       addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
-    ''
-    else setupHook;
-
-    inherit buildInputs;
-    propagatedBuildInputs = [ hex elixir ] ++ beamDeps;
-
-    configurePhase = if configurePhase == null
-    then ''
-      runHook preConfigure
-      ${erlang}/bin/escript ${bootstrapper}
-      runHook postConfigure
-    ''
-    else configurePhase ;
-
-
-    buildPhase = if buildPhase == null
-    then ''
-        runHook preBuild
-
-        export HEX_OFFLINE=1
-        export HEX_HOME=`pwd`
-        export MIX_ENV=prod
-        export MIX_NO_DEPS=1
-
-        mix compile ${debugInfoFlag} --no-deps-check
-
-        runHook postBuild
-    ''
-    else buildPhase;
-
-    installPhase = if installPhase == null
-    then ''
-        runHook preInstall
-
-        MIXENV=prod
-
-        if [ -d "_build/shared" ]; then
-          MIXENV=shared
+    inherit version src;
+
+    MIX_ENV = mixEnv;
+    MIX_DEBUG = if enableDebugInfo then 1 else 0;
+    HEX_OFFLINE = 1;
+
+    # add to ERL_LIBS so other modules can find at runtime.
+    # http://erlang.org/doc/man/code.html#code-path
+    # Mix also searches the code path when compiling with the --no-deps-check flag
+    setupHook = attrs.setupHook or
+      writeText "setupHook.sh" ''
+      addToSearchPath ERL_LIBS "$1/lib/erlang/lib"
+    '';
+
+    buildInputs = buildInputs ++ [ ];
+    nativeBuildInputs = nativeBuildInputs ++ [ elixir hex ];
+    propagatedBuildInputs = propagatedBuildInputs ++ beamDeps;
+
+    buildPhase = attrs.buildPhase or ''
+      runHook preBuild
+      export HEX_HOME="$TEMPDIR/hex"
+      export MIX_HOME="$TEMPDIR/mix"
+      mix compile --no-deps-check
+      runHook postBuild
+    '';
+
+    installPhase = attrs.installPhase or ''
+      runHook preInstall
+
+      # This uses the install path convention established by nixpkgs maintainers
+      # for all beam packages. Changing this will break compatibility with other
+      # builder functions like buildRebar3 and buildErlangMk.
+      mkdir -p "$out/lib/erlang/lib/${name}-${version}"
+
+      # Some packages like db_connection will use _build/shared instead of
+      # honoring the $MIX_ENV variable.
+      for reldir in _build/{$MIX_ENV,shared}/lib/${name}/{src,ebin,priv,include} ; do
+        if test -d $reldir ; then
+          # Some builds produce symlinks (eg: phoenix priv dircetory). They must
+          # be followed with -H flag.
+          cp  -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir"
         fi
+      done
 
-        mkdir -p "$out/lib/erlang/lib/${name}-${version}"
-        for reldir in src ebin priv include; do
-          fd="_build/$MIXENV/lib/${name}/$reldir"
-          [ -d "$fd" ] || continue
-          cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$fd"
-          success=1
-        done
+      runHook postInstall
+    '';
 
-        runHook postInstall
-    ''
-    else installPhase;
+    # stripping does not have any effect on beam files
+    # it is however needed for dependencies with NIFs like bcrypt for example
+    dontStrip = false;
 
     passthru = {
       packageName = name;
       env = shell self;
       inherit beamDeps;
     };
-});
-in fix pkg
+  });
+in
+fix pkg
diff --git a/pkgs/development/beam-modules/build-rebar3.nix b/pkgs/development/beam-modules/build-rebar3.nix
index 224d111026a..0dfd68f0993 100644
--- a/pkgs/development/beam-modules/build-rebar3.nix
+++ b/pkgs/development/beam-modules/build-rebar3.nix
@@ -1,30 +1,34 @@
-{ stdenv, writeText, erlang, rebar3, openssl, libyaml,
-  pc, lib }:
+{ stdenv, writeText, erlang, rebar3WithPlugins, openssl, libyaml, lib }:
 
-{ name, version
+{ name
+, version
 , src
 , setupHook ? null
-, buildInputs ? [], beamDeps ? [], buildPlugins ? []
+, buildInputs ? [ ]
+, beamDeps ? [ ]
+, buildPlugins ? [ ]
 , postPatch ? ""
-, compilePorts ? false
 , installPhase ? null
 , buildPhase ? null
 , configurePhase ? null
-, meta ? {}
+, meta ? { }
 , enableDebugInfo ? false
-, ... }@attrs:
+, ...
+}@attrs:
 
-with stdenv.lib;
+with lib;
 
 let
   debugInfoFlag = lib.optionalString (enableDebugInfo || erlang.debugInfo) "debug-info";
 
-  ownPlugins = buildPlugins ++ (if compilePorts then [pc] else []);
+  rebar3 = rebar3WithPlugins {
+    plugins = buildPlugins;
+  };
 
   shell = drv: stdenv.mkDerivation {
-          name = "interactive-shell-${drv.name}";
-          buildInputs = [ drv ];
-    };
+    name = "interactive-shell-${drv.name}";
+    buildInputs = [ drv ];
+  };
 
   customPhases = filterAttrs
     (_: v: v != null)
@@ -36,35 +40,26 @@ let
     inherit version;
 
     buildInputs = buildInputs ++ [ erlang rebar3 openssl libyaml ];
-    propagatedBuildInputs = unique (beamDeps ++ ownPlugins);
-
-    dontStrip = true;
-    # The following are used by rebar3-nix-bootstrap
-    inherit compilePorts;
-    buildPlugins = ownPlugins;
+    propagatedBuildInputs = unique beamDeps;
 
     inherit src;
 
+    # stripping does not have any effect on beam files
+    # it is however needed for dependencies with NIFs
+    # false is the default but we keep this for readability
+    dontStrip = false;
+
     setupHook = writeText "setupHook.sh" ''
-       addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
+      addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
     '';
 
     postPatch = ''
       rm -f rebar rebar3
     '' + postPatch;
 
-    configurePhase = ''
-      runHook preConfigure
-      ${erlang}/bin/escript ${rebar3.bootstrapper} ${debugInfoFlag}
-      runHook postConfigure
-    '';
-
     buildPhase = ''
       runHook preBuild
-      HOME=. rebar3 compile
-      ${if compilePorts then ''
-        HOME=. rebar3 pc compile
-      '' else ''''}
+      HOME=. rebar3 bare compile -path ""
       runHook postBuild
     '';
 
@@ -72,10 +67,9 @@ let
       runHook preInstall
       mkdir -p "$out/lib/erlang/lib/${name}-${version}"
       for reldir in src ebin priv include; do
-        fd="_build/default/lib/${name}/$reldir"
-        [ -d "$fd" ] || continue
-        cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$fd"
-        success=1
+        [ -d "$reldir" ] || continue
+        # $out/lib/erlang/lib is a convention used in nixpkgs for compiled BEAM packages
+        cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir"
       done
       runHook postInstall
     '';
@@ -91,4 +85,4 @@ let
     };
   } // customPhases);
 in
-  fix pkg
+fix pkg
diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix
index efd68988c9b..b6be8c3e7fb 100644
--- a/pkgs/development/beam-modules/default.nix
+++ b/pkgs/development/beam-modules/default.nix
@@ -1,12 +1,12 @@
-{ stdenv, pkgs, erlang }:
+{ lib, pkgs, erlang }:
 
 let
-  inherit (stdenv.lib) makeExtensible;
+  inherit (lib) makeExtensible;
 
-  lib = pkgs.callPackage ./lib.nix {};
+  lib' = pkgs.callPackage ./lib.nix { };
 
   # FIXME: add support for overrideScope
-  callPackageWithScope = scope: drv: args: stdenv.lib.callPackageWith scope drv args;
+  callPackageWithScope = scope: drv: args: lib.callPackageWith scope drv args;
   mkScope = scope: pkgs // scope;
 
   packages = self:
@@ -14,69 +14,77 @@ let
       defaultScope = mkScope self;
       callPackage = drv: args: callPackageWithScope defaultScope drv args;
     in
-      rec {
-        inherit callPackage erlang;
-        beamPackages = self;
-
-        rebar = callPackage ../tools/build-managers/rebar { };
-        rebar3 = callPackage ../tools/build-managers/rebar3 { };
-
-        # rebar3 port compiler plugin is required by buildRebar3
-        pc_1_6_0 = callPackage ./pc {};
-        pc = pc_1_6_0;
-
-        fetchHex = callPackage ./fetch-hex.nix { };
-
-        fetchRebar3Deps = callPackage ./fetch-rebar-deps.nix { };
-        rebar3Relx = callPackage ./rebar3-release.nix { };
-
-        buildRebar3 = callPackage ./build-rebar3.nix {};
-        buildHex = callPackage ./build-hex.nix {};
-        buildErlangMk = callPackage ./build-erlang-mk.nix {};
-        buildMix = callPackage ./build-mix.nix {};
-
-        # BEAM-based languages.
-        elixir = elixir_1_10;
-
-        elixir_1_10 = lib.callElixir ../interpreters/elixir/1.10.nix {
-          inherit rebar erlang;
-          debugInfo = true;
-        };
-
-        elixir_1_9 = lib.callElixir ../interpreters/elixir/1.9.nix {
-          inherit rebar erlang;
-          debugInfo = true;
-        };
-
-        elixir_1_8 = lib.callElixir ../interpreters/elixir/1.8.nix {
-          inherit rebar erlang;
-          debugInfo = true;
-        };
-
-        elixir_1_7 = lib.callElixir ../interpreters/elixir/1.7.nix {
-          inherit rebar erlang;
-          debugInfo = true;
-        };
-
-        elixir_1_6 = lib.callElixir ../interpreters/elixir/1.6.nix {
-          inherit rebar erlang;
-          debugInfo = true;
-        };
-
-        # Remove old versions of elixir, when the supports fades out:
-        # https://hexdocs.pm/elixir/compatibility-and-deprecations.html
-
-        lfe = lfe_1_3;
-        lfe_1_2 = lib.callLFE ../interpreters/lfe/1.2.nix { inherit erlang buildRebar3 buildHex; };
-        lfe_1_3 = lib.callLFE ../interpreters/lfe/1.3.nix { inherit erlang buildRebar3 buildHex; };
-
-        # Non hex packages. Examples how to build Rebar/Mix packages with and
-        # without helper functions buildRebar3 and buildMix.
-        hex = callPackage ./hex {};
-        webdriver = callPackage ./webdriver {};
-        relxExe = callPackage ../tools/erlang/relx-exe {};
-
-        # An example of Erlang/C++ package.
-        cuter = callPackage ../tools/erlang/cuter {};
+    rec {
+      inherit callPackage erlang;
+      beamPackages = self;
+
+      inherit (callPackage ../tools/build-managers/rebar3 { }) rebar3 rebar3WithPlugins;
+      rebar = callPackage ../tools/build-managers/rebar { };
+
+      pc = callPackage ./pc { };
+      rebar3-proper = callPackage ./rebar3-proper { };
+      rebar3-nix = callPackage ./rebar3-nix { };
+
+      fetchHex = callPackage ./fetch-hex.nix { };
+
+      fetchRebar3Deps = callPackage ./fetch-rebar-deps.nix { };
+      rebar3Relx = callPackage ./rebar3-release.nix { };
+
+      buildRebar3 = callPackage ./build-rebar3.nix { };
+      buildHex = callPackage ./build-hex.nix { };
+      buildErlangMk = callPackage ./build-erlang-mk.nix { };
+      buildMix = callPackage ./build-mix.nix { };
+      fetchMixDeps = callPackage ./fetch-mix-deps.nix { };
+      mixRelease = callPackage ./mix-release.nix { };
+
+      erlang-ls = callPackage ./erlang-ls { };
+      erlfmt = callPackage ./erlfmt { };
+      elvis-erlang = callPackage ./elvis-erlang { };
+
+      # BEAM-based languages.
+      elixir = elixir_1_12;
+
+      elixir_1_12 = lib'.callElixir ../interpreters/elixir/1.12.nix {
+        inherit erlang;
+        debugInfo = true;
       };
-in makeExtensible packages
+
+      elixir_1_11 = lib'.callElixir ../interpreters/elixir/1.11.nix {
+        inherit erlang;
+        debugInfo = true;
+      };
+
+      elixir_1_10 = lib'.callElixir ../interpreters/elixir/1.10.nix {
+        inherit erlang;
+        debugInfo = true;
+      };
+
+      elixir_1_9 = lib'.callElixir ../interpreters/elixir/1.9.nix {
+        inherit erlang;
+        debugInfo = true;
+      };
+
+      elixir_1_8 = lib'.callElixir ../interpreters/elixir/1.8.nix {
+        erlang = pkgs.beam.interpreters.erlangR23;
+        debugInfo = true;
+      };
+
+      # Remove old versions of elixir, when the supports fades out:
+      # https://hexdocs.pm/elixir/compatibility-and-deprecations.html
+      elixir_1_7 = lib'.callElixir ../interpreters/elixir/1.7.nix {
+        inherit erlang;
+        debugInfo = true;
+      };
+
+      elixir_ls = callPackage ./elixir_ls.nix { inherit elixir fetchMixDeps mixRelease; };
+
+      lfe = lfe_1_3;
+      lfe_1_3 = lib'.callLFE ../interpreters/lfe/1.3.nix { inherit erlang buildRebar3 buildHex; };
+
+      # Non hex packages. Examples how to build Rebar/Mix packages with and
+      # without helper functions buildRebar3 and buildMix.
+      hex = callPackage ./hex { };
+      webdriver = callPackage ./webdriver { };
+    };
+in
+makeExtensible packages
diff --git a/pkgs/development/beam-modules/elixir_ls.nix b/pkgs/development/beam-modules/elixir_ls.nix
new file mode 100644
index 00000000000..5afab0e1bab
--- /dev/null
+++ b/pkgs/development/beam-modules/elixir_ls.nix
@@ -0,0 +1,71 @@
+{ lib, elixir, fetchFromGitHub, fetchMixDeps, mixRelease }:
+# Based on the work of Hauleth
+# None of this would have happened without him
+
+mixRelease rec {
+  pname = "elixir-ls";
+  version = "0.7.0";
+
+  src = fetchFromGitHub {
+    owner = "elixir-lsp";
+    repo = "elixir-ls";
+    rev = "v${version}";
+    sha256 = "0d0hqc35hfjkpm88vz21mnm2a9rxiqfrdi83whhhh6d2ba216b7s";
+    fetchSubmodules = true;
+  };
+
+  mixFodDeps = fetchMixDeps {
+    pname = "mix-deps-${pname}";
+    inherit src version;
+    sha256 = "0r9x223imq4j9pn9niskyaybvk7jmq8dxcyzk7kwfsi128qig1a1";
+  };
+
+  # elixir_ls is an umbrella app
+  # override configurePhase to not skip umbrella children
+  configurePhase = ''
+    runHook preConfigure
+    mix deps.compile --no-deps-check
+    runHook postConfigure
+  '';
+
+  # elixir_ls require a special step for release
+  # compile and release need to be performed together because
+  # of the no-deps-check requirement
+  buildPhase = ''
+    runHook preBuild
+    mix do compile --no-deps-check, elixir_ls.release
+    runHook postBuild
+  '';
+
+  installPhase = ''
+    runHook preInstall
+    mkdir -p $out/bin
+    cp -Rv release $out/lib
+    # Prepare the wrapper script
+    substitute release/language_server.sh $out/bin/elixir-ls \
+      --replace 'exec "''${dir}/launch.sh"' "exec $out/lib/launch.sh"
+    chmod +x $out/bin/elixir-ls
+    # prepare the launcher
+    substituteInPlace $out/lib/launch.sh \
+      --replace "ERL_LIBS=\"\$SCRIPTPATH:\$ERL_LIBS\"" \
+                "ERL_LIBS=$out/lib:\$ERL_LIBS" \
+      --replace "exec elixir" "exec ${elixir}/bin/elixir"
+    runHook postInstall
+  '';
+
+  meta = with lib; {
+    homepage = "https://github.com/elixir-lsp/elixir-ls";
+    description = ''
+      A frontend-independent IDE "smartness" server for Elixir.
+      Implements the "Language Server Protocol" standard and provides debugger support via the "Debug Adapter Protocol"
+    '';
+    longDescription = ''
+      The Elixir Language Server provides a server that runs in the background, providing IDEs, editors, and other tools with information about Elixir Mix projects.
+      It adheres to the Language Server Protocol, a standard for frontend-independent IDE support.
+      Debugger integration is accomplished through the similar VS Code Debug Protocol.
+    '';
+    license = licenses.asl20;
+    platforms = platforms.unix;
+    maintainers = teams.beam.members;
+  };
+}
diff --git a/pkgs/development/beam-modules/elvis-erlang/default.nix b/pkgs/development/beam-modules/elvis-erlang/default.nix
new file mode 100644
index 00000000000..81888bdde21
--- /dev/null
+++ b/pkgs/development/beam-modules/elvis-erlang/default.nix
@@ -0,0 +1,46 @@
+{ fetchFromGitHub, fetchgit, fetchHex, rebar3WithPlugins, rebar3-nix, rebar3Relx
+, buildRebar3, writeScript, lib }:
+
+let
+  owner = "inaka";
+  repo = "elvis";
+in rebar3Relx rec {
+  releaseType = "escript";
+  # The package name "elvis" is already taken
+  pname = "elvis-erlang";
+  version = "1.0.1";
+  src = fetchFromGitHub {
+    inherit owner repo;
+    sha256 = "139mgd4cwc0vazxfnssyym61jd9g45wn1nc53mjfzx5dkrrn4dc5";
+    rev = version;
+  };
+  beamDeps = builtins.attrValues (import ./rebar-deps.nix {
+    inherit fetchHex fetchgit fetchFromGitHub;
+    builder = buildRebar3;
+  });
+  passthru.updateScript = writeScript "update.sh" ''
+    #!/usr/bin/env nix-shell
+    #!nix-shell -i bash -p bash common-updater-scripts git nix-prefetch-git gnutar gzip "rebar3WithPlugins {globalPlugins = [beamPackages.rebar3-nix];}"
+
+    set -euo pipefail
+
+    latest=$(list-git-tags https://github.com/${owner}/${repo}.git | sort -V | tail -1)
+    if [ "$latest" != "${version}" ]; then
+      nixpkgs="$(git rev-parse --show-toplevel)"
+      nix_path="$nixpkgs/pkgs/development/beam-modules/elvis-erlang"
+      update-source-version elvis-erlang "$latest" --version-key=version --print-changes --file="$nix_path/default.nix"
+      tmpdir=$(mktemp -d)
+      cp -R $(nix-build $nixpkgs --no-out-link -A elvis-erlang.src)/* "$tmpdir"
+      (cd "$tmpdir" && HOME=. rebar3 nix lock -o "$nix_path/rebar-deps.nix")
+    else
+      echo "${repo} is already up-to-date"
+    fi
+  '';
+  meta = with lib; {
+    homepage = "https://github.com/inaka/elvis";
+    description = "Erlang Style Reviewer";
+    platforms = platforms.unix;
+    license = licenses.asl20;
+    maintainers = with lib.maintainers; [ dlesl ];
+  };
+}
diff --git a/pkgs/development/beam-modules/elvis-erlang/rebar-deps.nix b/pkgs/development/beam-modules/elvis-erlang/rebar-deps.nix
new file mode 100644
index 00000000000..93c3db16eb9
--- /dev/null
+++ b/pkgs/development/beam-modules/elvis-erlang/rebar-deps.nix
@@ -0,0 +1,168 @@
+# Generated by rebar3_nix
+let fetchOnly = { src, ... }: src;
+in { builder ? fetchOnly, fetchHex, fetchgit, fetchFromGitHub, overrides ? (x: y: { }) }:
+let
+  self = packages // (overrides self packages);
+  packages = with self; {
+    unicode_util_compat = builder {
+      name = "unicode_util_compat";
+      version = "0.7.0";
+      src = fetchHex {
+        pkg = "unicode_util_compat";
+        version = "0.7.0";
+        sha256 = "sha256-Je7m1n32GWDPanlCOVZlmbCeF+Zo03ACR7xJhjgVJSE=";
+      };
+      beamDeps = [ ];
+    };
+    ssl_verify_fun = builder {
+      name = "ssl_verify_fun";
+      version = "1.1.6";
+      src = fetchHex {
+        pkg = "ssl_verify_fun";
+        version = "1.1.6";
+        sha256 = "sha256-vbDSRx9FPIj/OQjnaG+G+b4yfQZcwewW+kVAGX6gRoA=";
+      };
+      beamDeps = [ ];
+    };
+    parse_trans = builder {
+      name = "parse_trans";
+      version = "3.4.0";
+      src = fetchHex {
+        pkg = "parse_trans";
+        version = "3.4.0";
+        sha256 = "sha256-+Z42iDC+pEVSIk434ElDpUh08IuFkEhd6NE4MrY6LcM=";
+      };
+      beamDeps = [ ];
+    };
+    mimerl = builder {
+      name = "mimerl";
+      version = "1.2.0";
+      src = fetchHex {
+        pkg = "mimerl";
+        version = "1.2.0";
+        sha256 = "sha256-8nhYVlCqWBmGJkY46/aY+LsZ3yl/Zq2RsYkQ38bhkyM=";
+      };
+      beamDeps = [ ];
+    };
+    metrics = builder {
+      name = "metrics";
+      version = "1.0.1";
+      src = fetchHex {
+        pkg = "metrics";
+        version = "1.0.1";
+        sha256 = "sha256-abCa3dxPdKQHFq5U0UD5O+sPuJeNhjbq3tDDG28JnxY=";
+      };
+      beamDeps = [ ];
+    };
+    idna = builder {
+      name = "idna";
+      version = "6.1.1";
+      src = fetchHex {
+        pkg = "idna";
+        version = "6.1.1";
+        sha256 = "sha256-kjdut4lEEu0ZrEdeSob3tBPBufu1vRbczVeTQVeUTOo=";
+      };
+      beamDeps = [ unicode_util_compat ];
+    };
+    certifi = builder {
+      name = "certifi";
+      version = "2.6.1";
+      src = fetchHex {
+        pkg = "certifi";
+        version = "2.6.1";
+        sha256 = "sha256-UkyXtJkbOEndXBemMSI4licsawr0RneLpGdaHf9Tu34=";
+      };
+      beamDeps = [ ];
+    };
+    zipper = builder {
+      name = "zipper";
+      version = "1.0.1";
+      src = fetchHex {
+        pkg = "zipper";
+        version = "1.0.1";
+        sha256 = "sha256-ah/T4fDMHR31ZCyaDOIXgDZBGwpclkKFHR2idr1zfC0=";
+      };
+      beamDeps = [ ];
+    };
+    lager = builder {
+      name = "lager";
+      version = "3.9.1";
+      src = fetchHex {
+        pkg = "lager";
+        version = "3.9.1";
+        sha256 = "sha256-P1m6daBKmeXxi/kcifRtzlNvg8bLQV/ibm51pivvN9w=";
+      };
+      beamDeps = [ goldrush ];
+    };
+    katana_code = builder {
+      name = "katana_code";
+      version = "1.1.2";
+      src = fetchHex {
+        pkg = "katana_code";
+        version = "1.1.2";
+        sha256 = "sha256-5+YWKkToJqA/aLUDt9kpgbiUv4NMHvDmR3g/fWaIAhw=";
+      };
+      beamDeps = [ ];
+    };
+    jsx = builder {
+      name = "jsx";
+      version = "2.10.0";
+      src = fetchHex {
+        pkg = "jsx";
+        version = "2.10.0";
+        sha256 = "sha256-moPjcEgHKYAWlo21Bvn60PAn3jdUbrg4s64QZMOgrWI=";
+      };
+      beamDeps = [ ];
+    };
+    hackney = builder {
+      name = "hackney";
+      version = "1.17.1";
+      src = fetchHex {
+        pkg = "hackney";
+        version = "1.17.1";
+        sha256 = "sha256-0sup48gQOtAyBiPp8cM+jTeKFeqr4u6K5EGJjz01oYw=";
+      };
+      beamDeps = [ certifi idna metrics mimerl parse_trans ssl_verify_fun unicode_util_compat ];
+    };
+    goldrush = builder {
+      name = "goldrush";
+      version = "0.1.9";
+      src = fetchHex {
+        pkg = "goldrush";
+        version = "0.1.9";
+        sha256 = "sha256-mctBKM/8syJ1geXU2APVQT+mQ/TrllI/d9nmk32ZTOs=";
+      };
+      beamDeps = [ ];
+    };
+    getopt = builder {
+      name = "getopt";
+      version = "1.0.2";
+      src = fetchHex {
+        pkg = "getopt";
+        version = "1.0.2";
+        sha256 = "sha256-oAKa6kMi+4KmH2h2ptnGbcmHi2y2H6oT3zGHOE/U6iY=";
+      };
+      beamDeps = [ ];
+    };
+    elvis_core = builder {
+      name = "elvis_core";
+      version = "1.1.2";
+      src = fetchHex {
+        pkg = "elvis_core";
+        version = "1.1.2";
+        sha256 = "sha256-xO5Cp6fC/FZ/Pqa1FQFkzWgpDxEA6bGaTPiG2Kocpzw=";
+      };
+      beamDeps = [ katana_code zipper ];
+    };
+    egithub = builder {
+      name = "egithub";
+      version = "0.7.0";
+      src = fetchHex {
+        pkg = "egithub";
+        version = "0.7.0";
+        sha256 = "sha256-4AnOEe/YAI0PntWdnEiOPpq+MCoPLNbWY+TMJnVvzEw=";
+      };
+      beamDeps = [ goldrush hackney jsx lager ];
+    };
+  };
+in self
diff --git a/pkgs/development/beam-modules/erlang-ls/default.nix b/pkgs/development/beam-modules/erlang-ls/default.nix
new file mode 100644
index 00000000000..7635e46237b
--- /dev/null
+++ b/pkgs/development/beam-modules/erlang-ls/default.nix
@@ -0,0 +1,47 @@
+{ fetchFromGitHub, fetchHex, rebar3Relx, buildRebar3, rebar3-proper, lib }:
+let
+  version = "0.17.0";
+  owner = "erlang-ls";
+  repo = "erlang_ls";
+  deps = import ./rebar-deps.nix {
+    inherit fetchHex fetchFromGitHub;
+    builder = buildRebar3;
+    overrides = (self: super: {
+      proper = super.proper.overrideAttrs (_: {
+        configurePhase = "true";
+      });
+    });
+  };
+in
+rebar3Relx {
+  pname = "erlang-ls";
+  inherit version;
+  src = fetchFromGitHub {
+    inherit owner repo;
+    sha256 = "0szg9hx436cvy80sh94dzmf2rainnw3fjc84bv3hlzjwwzmxj9aw";
+    rev = version;
+  };
+  releaseType = "escript";
+  beamDeps = builtins.attrValues deps;
+  buildPlugins = [ rebar3-proper ];
+  buildPhase = "HOME=. make";
+  # based on https://github.com/erlang-ls/erlang_ls/blob/main/.github/workflows/build.yml
+  # these tests are excessively long and we should probably skip them
+  checkPhase = ''
+    HOME=. epmd -daemon
+    HOME=. rebar3 ct
+    HOME=. rebar3 proper --constraint_tries 100
+  '';
+  doCheck = true;
+  installPhase = ''
+    mkdir -p $out/bin
+    cp _build/default/bin/erlang_ls $out/bin/
+    cp _build/dap/bin/els_dap $out/bin/
+  '';
+  meta = with lib; {
+    homepage = "https://github.com/erlang-ls/erlang_ls";
+    description = "The Erlang Language Server";
+    platforms = platforms.unix;
+    license = licenses.asl20;
+  };
+}
diff --git a/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix b/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix
new file mode 100644
index 00000000000..5d55ce0c523
--- /dev/null
+++ b/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix
@@ -0,0 +1,219 @@
+# Generated by rebar3_nix
+let fetchOnly = { src, ... }: src;
+in { builder ? fetchOnly, fetchHex, fetchFromGitHub, overrides ? (x: y: { }) }:
+let
+  self = packages // (overrides self packages);
+  packages = with self; {
+    getopt = builder {
+      name = "getopt";
+      version = "1.0.1";
+      src = fetchHex {
+        pkg = "getopt";
+        version = "1.0.1";
+        sha256 = "sha256-U+Grg7nOtlyWctPno1uAkum9ybPugHIUcaFhwQxZlZw=";
+      };
+      beamDeps = [ ];
+    };
+    zipper = builder {
+      name = "zipper";
+      version = "1.0.1";
+      src = fetchHex {
+        pkg = "zipper";
+        version = "1.0.1";
+        sha256 = "sha256-ah/T4fDMHR31ZCyaDOIXgDZBGwpclkKFHR2idr1zfC0=";
+      };
+      beamDeps = [ ];
+    };
+    quickrand = builder {
+      name = "quickrand";
+      version = "2.0.1";
+      src = fetchHex {
+        pkg = "quickrand";
+        version = "2.0.1";
+        sha256 = "sha256-FNtn1K72uIFYEOyfPM714yS3O1bK42h/mddSuFvdTJY=";
+      };
+      beamDeps = [ ];
+    };
+    providers = builder {
+      name = "providers";
+      version = "1.8.1";
+      src = fetchHex {
+        pkg = "providers";
+        version = "1.8.1";
+        sha256 = "sha256-5FdFrenEdqmkaeoIQOQYqxk2DcRPAaIzME4RikRIa6A=";
+      };
+      beamDeps = [ getopt ];
+    };
+    katana_code = builder {
+      name = "katana_code";
+      version = "0.2.1";
+      src = fetchHex {
+        pkg = "katana_code";
+        version = "0.2.1";
+        sha256 = "sha256-hEitP1bZgU+YoovmUPcZG91QZXXjRcwW1YZmCxD26ZI=";
+      };
+      beamDeps = [ ];
+    };
+    bucs = builder {
+      name = "bucs";
+      version = "1.0.16";
+      src = fetchHex {
+        pkg = "bucs";
+        version = "1.0.16";
+        sha256 = "sha256-/2pccqUArXrsHuO6FkrjxFDq3uiYsNFR4frKGKyNDWI=";
+      };
+      beamDeps = [ ];
+    };
+    yamerl = builder {
+      name = "yamerl";
+      version = "0.8.1";
+      src = fetchHex {
+        pkg = "yamerl";
+        version = "0.8.1";
+        sha256 = "sha256-lssw+dZDRP7Q74qS6fFvIH3mwE3/9PNmdSynn1vOsj8=";
+      };
+      beamDeps = [ ];
+    };
+    uuid = builder {
+      name = "uuid";
+      version = "2.0.1";
+      src = fetchHex {
+        pkg = "uuid_erl";
+        version = "2.0.1";
+        sha256 = "sha256-q1fKzNUfFwAR5fREzoZfhLQWBeSDqe/MRowa+uyHVTs=";
+      };
+      beamDeps = [ quickrand ];
+    };
+    tdiff = builder {
+      name = "tdiff";
+      version = "0.1.2";
+      src = fetchHex {
+        pkg = "tdiff";
+        version = "0.1.2";
+        sha256 = "sha256-4MLhaPmSUqWIl2jVyPHmUQoYRZLUz6BrIneKGNM9eHU=";
+      };
+      beamDeps = [ ];
+    };
+    redbug = builder {
+      name = "redbug";
+      version = "2.0.6";
+      src = fetchHex {
+        pkg = "redbug";
+        version = "2.0.6";
+        sha256 = "sha256-qtlJhnH0q5HqylCZ/oWmFhgVimNuYoaJLE989K8XHQQ=";
+      };
+      beamDeps = [ ];
+    };
+    rebar3_format = builder {
+      name = "rebar3_format";
+      version = "0.8.2";
+      src = fetchHex {
+        pkg = "rebar3_format";
+        version = "0.8.2";
+        sha256 = "sha256-yo/ydjjCFpWT0USdrL6IlWNBk+0zNOkGtU/JfwgfUhM=";
+      };
+      beamDeps = [ katana_code ];
+    };
+    ranch = builder {
+      name = "ranch";
+      version = "2.0.0";
+      src = fetchHex {
+        pkg = "ranch";
+        version = "2.0.0";
+        sha256 = "sha256-wgpIQMfWYjwZgS06fIKLLxvRU+8PEky2nFT+UdikKuA=";
+      };
+      beamDeps = [ ];
+    };
+    jsx = builder {
+      name = "jsx";
+      version = "3.0.0";
+      src = fetchHex {
+        pkg = "jsx";
+        version = "3.0.0";
+        sha256 = "sha256-N77KBDX1yoovRfdqRiEedkGPvvgMNvA2HCSfx1BZ3G0=";
+      };
+      beamDeps = [ ];
+    };
+    erlfmt = builder {
+      name = "erlfmt";
+      version = "git";
+      src = fetchFromGitHub {
+        owner = "whatsapp";
+        repo = "erlfmt";
+        rev = "2e93fc4a646111357642b0179a2a63151868d890";
+        sha256 = "0n7kygycn05aqdp5dyj192mja89l4nxv2wg16qg2c0bmw9s7j2mr";
+      };
+      beamDeps = [ ];
+    };
+    ephemeral = builder {
+      name = "ephemeral";
+      version = "2.0.4";
+      src = fetchHex {
+        pkg = "ephemeral";
+        version = "2.0.4";
+        sha256 = "sha256-Syk9gPdfnEV1/0ucjoiaVoAvQLAYv1fnTxlkTv7myFA=";
+      };
+      beamDeps = [ bucs ];
+    };
+    elvis_core = builder {
+      name = "elvis_core";
+      version = "1.1.1";
+      src = fetchHex {
+        pkg = "elvis_core";
+        version = "1.1.1";
+        sha256 = "sha256-ORyVuqSfJxjX+0mLzwgEbd/CAs8Kq2Oy5DknFIXJ3EI=";
+      };
+      beamDeps = [ katana_code zipper ];
+    };
+    docsh = builder {
+      name = "docsh";
+      version = "0.7.2";
+      src = fetchHex {
+        pkg = "docsh";
+        version = "0.7.2";
+        sha256 = "sha256-Tn20YbsHVA0rw9NmuFE/AZdxLQSVu4V0TzZ9OBUHYTQ=";
+      };
+      beamDeps = [ providers ];
+    };
+    proper_contrib = builder {
+      name = "proper_contrib";
+      version = "0.2.0";
+      src = fetchHex {
+        pkg = "proper_contrib";
+        version = "0.2.0";
+        sha256 = "sha256-jFRRL1zr9JKaG1eqMDfcKk2xe93uOrXUenB14icVCBU=";
+      };
+      beamDeps = [ proper ];
+    };
+    proper = builder {
+      name = "proper";
+      version = "1.3.0";
+      src = fetchHex {
+        pkg = "proper";
+        version = "1.3.0";
+        sha256 = "sha256-SqGS/M3dA/2+UP72IL6dTS+SY1tU9V+4OuwYWZRAPLw=";
+      };
+      beamDeps = [ ];
+    };
+    meck = builder {
+      name = "meck";
+      version = "0.9.0";
+      src = fetchHex {
+        pkg = "meck";
+        version = "0.9.0";
+        sha256 = "sha256-+BPpDdC4myUWoCAaNV6EsavHi1dRqgy/ZpqdhagQrGM=";
+      };
+      beamDeps = [ ];
+    };
+    coveralls = builder {
+      name = "coveralls";
+      version = "2.2.0";
+      src = fetchHex {
+        pkg = "coveralls";
+        version = "2.2.0";
+        sha256 = "sha256-zVTbCqjGS1OSgBicVhns7hOkaiiw8ct3RUTdzBZiBKM=";
+      };
+      beamDeps = [ jsx ];
+    };
+  };
+in self
diff --git a/pkgs/development/beam-modules/erlfmt/default.nix b/pkgs/development/beam-modules/erlfmt/default.nix
new file mode 100644
index 00000000000..da577f2264c
--- /dev/null
+++ b/pkgs/development/beam-modules/erlfmt/default.nix
@@ -0,0 +1,20 @@
+{ fetchFromGitHub, rebar3Relx, lib }:
+
+rebar3Relx rec {
+  pname = "erlfmt";
+  version = "1.0.0";
+  releaseType = "escript";
+  src = fetchFromGitHub {
+    owner = "WhatsApp";
+    repo = "erlfmt";
+    sha256 = "19apbs9xr4j8qjb3sv9ilknqjw4a7bvp8jvwrjiwvwnxzzm2kjm6";
+    rev = "v${version}";
+  };
+  meta = with lib; {
+    homepage = "https://github.com/WhatsApp/erlfmt";
+    description = "An automated code formatter for Erlang";
+    platforms = platforms.unix;
+    license = licenses.asl20;
+    maintainers = with lib.maintainers; [ dlesl ];
+  };
+}
diff --git a/pkgs/development/beam-modules/fetch-hex.nix b/pkgs/development/beam-modules/fetch-hex.nix
index c55a7a80ff3..7f84e236070 100644
--- a/pkgs/development/beam-modules/fetch-hex.nix
+++ b/pkgs/development/beam-modules/fetch-hex.nix
@@ -1,10 +1,10 @@
-{ stdenv, fetchurl }:
+{ lib, stdenv, fetchurl }:
 
 { pkg, version, sha256
 , meta ? {}
 }:
 
-with stdenv.lib;
+with lib;
 
 stdenv.mkDerivation ({
   name = "hex-source-${pkg}-${version}";
diff --git a/pkgs/development/beam-modules/fetch-mix-deps.nix b/pkgs/development/beam-modules/fetch-mix-deps.nix
new file mode 100644
index 00000000000..0c6f4e35a90
--- /dev/null
+++ b/pkgs/development/beam-modules/fetch-mix-deps.nix
@@ -0,0 +1,58 @@
+{ stdenvNoCC, lib, elixir, hex, rebar, rebar3, cacert, git }:
+
+{ pname
+, version
+, sha256
+, src
+, mixEnv ? "prod"
+, debug ? false
+, meta ? { }
+, patches ? []
+, ...
+}@attrs:
+
+stdenvNoCC.mkDerivation (attrs // {
+  nativeBuildInputs = [ elixir hex cacert git ];
+
+  MIX_ENV = mixEnv;
+  MIX_DEBUG = if debug then 1 else 0;
+  DEBUG = if debug then 1 else 0; # for rebar3
+  # the api with `mix local.rebar rebar path` makes a copy of the binary
+  MIX_REBAR = "${rebar}/bin/rebar";
+  MIX_REBAR3 = "${rebar3}/bin/rebar3";
+  # there is a persistent download failure with absinthe 1.6.3
+  # those defaults reduce the failure rate
+  HEX_HTTP_CONCURRENCY = 1;
+  HEX_HTTP_TIMEOUT = 120;
+
+  configurePhase = attrs.configurePhase or ''
+    runHook preConfigure
+    export HEX_HOME="$TEMPDIR/.hex";
+    export MIX_HOME="$TEMPDIR/.mix";
+    export MIX_DEPS_PATH="$TEMPDIR/deps";
+
+    # Rebar
+    export REBAR_GLOBAL_CONFIG_DIR="$TMPDIR/rebar3"
+    export REBAR_CACHE_DIR="$TMPDIR/rebar3.cache"
+    runHook postConfigure
+  '';
+
+  inherit patches;
+
+  dontBuild = true;
+
+  installPhase = attrs.installPhase or ''
+    runHook preInstall
+    mix deps.get --only ${mixEnv}
+    find "$TEMPDIR/deps" -path '*/.git/*' -a ! -name HEAD -exec rm -rf {} +
+    cp -r --no-preserve=mode,ownership,timestamps $TEMPDIR/deps $out
+    runHook postInstall
+  '';
+
+  outputHashAlgo = "sha256";
+  outputHashMode = "recursive";
+  outputHash = sha256;
+
+  impureEnvVars = lib.fetchers.proxyImpureEnvVars;
+  inherit meta;
+})
diff --git a/pkgs/development/beam-modules/fetch-rebar-deps.nix b/pkgs/development/beam-modules/fetch-rebar-deps.nix
index 389e07beca6..d858b3d81af 100644
--- a/pkgs/development/beam-modules/fetch-rebar-deps.nix
+++ b/pkgs/development/beam-modules/fetch-rebar-deps.nix
@@ -1,10 +1,10 @@
-{ stdenv, rebar3 }:
+{ lib, stdenv, rebar3 }:
 
 { name, version, sha256, src
 , meta ? {}
 }:
 
-with stdenv.lib;
+with lib;
 
 stdenv.mkDerivation ({
   name = "rebar-deps-${name}-${version}";
@@ -28,6 +28,6 @@ stdenv.mkDerivation ({
   outputHashMode = "recursive";
   outputHash = sha256;
 
-  impureEnvVars = stdenv.lib.fetchers.proxyImpureEnvVars;
+  impureEnvVars = lib.fetchers.proxyImpureEnvVars;
   inherit meta;
 })
diff --git a/pkgs/development/beam-modules/hex/default.nix b/pkgs/development/beam-modules/hex/default.nix
index 26070ce73bf..836740a7933 100644
--- a/pkgs/development/beam-modules/hex/default.nix
+++ b/pkgs/development/beam-modules/hex/default.nix
@@ -1,4 +1,4 @@
-{ stdenv, fetchFromGitHub, writeText, elixir }:
+{ lib, stdenv, fetchFromGitHub, writeText, elixir }:
 
 let
   shell = drv: stdenv.mkDerivation {
@@ -8,13 +8,13 @@ let
 
   pkg = self: stdenv.mkDerivation rec {
     pname = "hex";
-    version = "0.20.5";
+    version = "0.21.2";
 
     src = fetchFromGitHub {
       owner = "hexpm";
       repo = "hex";
       rev = "v${version}";
-      sha256 = "1wz6n4qrmsb4kkww6lrdbs99xzwp4dyjjmr8m4drcwn3sd2k9ba6";
+      sha256 = "18vwrc5b7pyi3nifmx5hd5wbz8fy3h6sfvkmskjg5acmz66fys0g";
     };
 
     setupHook = writeText "setupHook.sh" ''
@@ -45,13 +45,13 @@ let
 
     meta = {
       description = "Package manager for the Erlang VM https://hex.pm";
-      license = stdenv.lib.licenses.mit;
+      license = lib.licenses.mit;
       homepage = "https://github.com/hexpm/hex";
-      maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
+      maintainers = with lib.maintainers; [ ericbmerritt ];
     };
 
     passthru = {
       env = shell self;
     };
 };
-in stdenv.lib.fix pkg
+in lib.fix pkg
diff --git a/pkgs/development/beam-modules/lib.nix b/pkgs/development/beam-modules/lib.nix
index db40c47794f..1b021cf9347 100644
--- a/pkgs/development/beam-modules/lib.nix
+++ b/pkgs/development/beam-modules/lib.nix
@@ -1,4 +1,4 @@
-{ pkgs, stdenv }:
+{ pkgs, lib }:
 
 rec {
 
@@ -7,7 +7,7 @@ rec {
   callPackageWith = autoArgs: fn: args:
     let
       f = if pkgs.lib.isFunction fn then fn else import fn;
-      auto = builtins.intersectAttrs (stdenv.lib.functionArgs f) autoArgs;
+      auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
     in f (auto // args);
 
   callPackage = callPackageWith pkgs;
diff --git a/pkgs/development/beam-modules/mix-bootstrap b/pkgs/development/beam-modules/mix-bootstrap
deleted file mode 100755
index 7e31def71fa..00000000000
--- a/pkgs/development/beam-modules/mix-bootstrap
+++ /dev/null
@@ -1,108 +0,0 @@
-#!/usr/bin/env escript
-%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*-
-%%! -smp enable
-%%% ---------------------------------------------------------------------------
-%%% @doc
-%%% The purpose of this command is to prepare a mix project so that mix
-%%% understands that the dependencies are all already installed. If you want a
-%%% hygienic build on nix then you must run this command before running mix. I
-%%% suggest that you add a `Makefile` to your project and have the bootstrap
-%%% command be a dependency of the build commands. See the nix documentation for
-%%% more information.
-%%%
-%%% This command designed to have as few dependencies as possible so that it can
-%%% be a dependency of root level packages like mix. To that end it does many
-%%% things in a fairly simplistic way. That is by design.
-%%%
-%%% ### Assumptions
-%%%
-%%% This command makes the following assumptions:
-%%%
-%%% * It is run in a nix-shell or nix-build environment
-%%% * that all dependencies have been added to the ERL_LIBS
-%%%   Environment Variable
-
--record(data, {version
-              , erl_libs
-              , root
-              , name}).
--define(LOCAL_HEX_REGISTRY, "registry.ets").
-
-main(Args) ->
-    {ok, RequiredData} = gather_required_data_from_the_environment(Args),
-    ok = bootstrap_libs(RequiredData).
-
-%% @doc
-%% This takes an app name in the standard OTP <name>-<version> format
-%% and returns just the app name. Why? Because rebar doesn't
-%% respect OTP conventions in some cases.
--spec fixup_app_name(file:name()) -> string().
-fixup_app_name(Path) ->
-    BaseName = filename:basename(Path),
-    case string:split(BaseName, "-") of
-        [Name, _Version] -> Name;
-        Name -> Name
-    end.
-
-
--spec gather_required_data_from_the_environment([string()]) -> {ok, #data{}}.
-gather_required_data_from_the_environment(_) ->
-    {ok, #data{ version = guard_env("version")
-              , erl_libs = os:getenv("ERL_LIBS", [])
-              , root = code:root_dir()
-              , name = guard_env("name")}}.
-
--spec guard_env(string()) -> string().
-guard_env(Name) ->
-    case os:getenv(Name) of
-        false ->
-            stderr("Expected Environment variable ~s! Are you sure you are "
-                   "running in a Nix environment? Either a nix-build, "
-                   "nix-shell, etc?~n", [Name]),
-            erlang:halt(1);
-        Variable ->
-            Variable
-    end.
-
--spec bootstrap_libs(#data{}) -> ok.
-bootstrap_libs(#data{erl_libs = ErlLibs}) ->
-    io:format("Bootstrapping dependent libraries~n"),
-    Target = "_build/prod/lib/",
-    Paths = string:tokens(ErlLibs, ":"),
-    CopiableFiles =
-        lists:foldl(fun(Path, Acc) ->
-                            gather_directory_contents(Path) ++ Acc
-                    end, [], Paths),
-    lists:foreach(fun (Path) ->
-                          ok = link_app(Path, Target)
-                  end, CopiableFiles).
-
--spec gather_directory_contents(string()) -> [{string(), string()}].
-gather_directory_contents(Path) ->
-    {ok, Names} = file:list_dir(Path),
-    lists:map(fun(AppName) ->
-                 {filename:join(Path, AppName), fixup_app_name(AppName)}
-              end, Names).
-
-%% @doc
-%% Makes a symlink from the directory pointed at by Path to a
-%% directory of the same name in Target. So if we had a Path of
-%% {`foo/bar/baz/bash`, `baz`} and a Target of `faz/foo/foos`, the symlink
-%% would be `faz/foo/foos/baz`.
--spec link_app({string(), string()}, string()) -> ok.
-link_app({Path, TargetFile}, TargetDir) ->
-    Target = filename:join(TargetDir, TargetFile),
-    ok = make_symlink(Path, Target).
-
--spec make_symlink(string(), string()) -> ok.
-make_symlink(Path, TargetFile) ->
-    file:delete(TargetFile),
-    ok = filelib:ensure_dir(TargetFile),
-    io:format("Making symlink from ~s to ~s~n", [Path, TargetFile]),
-    ok = file:make_symlink(Path, TargetFile).
-
-%% @doc
-%% Write the result of the format string out to stderr.
--spec stderr(string(), [term()]) -> ok.
-stderr(FormatStr, Args) ->
-    io:put_chars(standard_error, io_lib:format(FormatStr, Args)).
diff --git a/pkgs/development/beam-modules/mix-release.nix b/pkgs/development/beam-modules/mix-release.nix
new file mode 100644
index 00000000000..80e8721302e
--- /dev/null
+++ b/pkgs/development/beam-modules/mix-release.nix
@@ -0,0 +1,117 @@
+{ stdenv, lib, elixir, erlang, findutils, hex, rebar, rebar3, fetchMixDeps, makeWrapper, git, ripgrep }:
+
+{ pname
+, version
+, src
+, nativeBuildInputs ? [ ]
+, meta ? { }
+, enableDebugInfo ? false
+, mixEnv ? "prod"
+, compileFlags ? [ ]
+  # mix fixed output derivation dependencies
+, mixFodDeps ? null
+  # mix dependencies generated by mix2nix
+  # this assumes each dependency is built by buildMix or buildRebar3
+  # each dependency needs to have a setup hook to add the lib path to $ERL_LIBS
+  # this is how mix will find dependencies
+, mixNixDeps ? { }
+, ...
+}@attrs:
+let
+  # remove non standard attributes that cannot be coerced to strings
+  overridable = builtins.removeAttrs attrs [ "compileFlags" "mixNixDeps" ];
+in
+assert mixNixDeps != { } -> mixFodDeps == null;
+stdenv.mkDerivation (overridable // {
+  # rg is used as a better grep to search for erlang references in the final release
+  nativeBuildInputs = nativeBuildInputs ++ [ erlang hex elixir makeWrapper git ripgrep ];
+  buildInputs = builtins.attrValues mixNixDeps;
+
+  MIX_ENV = mixEnv;
+  MIX_DEBUG = if enableDebugInfo then 1 else 0;
+  HEX_OFFLINE = 1;
+  DEBUG = if enableDebugInfo then 1 else 0; # for Rebar3 compilation
+  # the api with `mix local.rebar rebar path` makes a copy of the binary
+  # some older dependencies still use rebar
+  MIX_REBAR = "${rebar}/bin/rebar";
+  MIX_REBAR3 = "${rebar3}/bin/rebar3";
+
+  postUnpack = ''
+    export HEX_HOME="$TEMPDIR/hex"
+    export MIX_HOME="$TEMPDIR/mix"
+
+    # Rebar
+    export REBAR_GLOBAL_CONFIG_DIR="$TEMPDIR/rebar3"
+    export REBAR_CACHE_DIR="$TEMPDIR/rebar3.cache"
+
+    ${lib.optionalString (mixFodDeps != null) ''
+      # compilation of the dependencies will require
+      # that the dependency path is writable
+      # thus a copy to the TEMPDIR is inevitable here
+      export MIX_DEPS_PATH="$TEMPDIR/deps"
+      cp --no-preserve=mode -R "${mixFodDeps}" "$MIX_DEPS_PATH"
+    ''
+    }
+
+  '' + (attrs.postUnpack or "");
+
+  configurePhase = attrs.configurePhase or ''
+    runHook preConfigure
+
+    # this is needed for projects that have a specific compile step
+    # the dependency needs to be compiled in order for the task
+    # to be available
+    # Phoenix projects for example will need compile.phoenix
+    mix deps.compile --no-deps-check --skip-umbrella-children
+
+    runHook postConfigure
+  '';
+
+  buildPhase = attrs.buildPhase or ''
+    runHook preBuild
+
+    mix compile --no-deps-check ${lib.concatStringsSep " " compileFlags}
+
+    runHook postBuild
+  '';
+
+
+  installPhase = attrs.installPhase or ''
+    runHook preInstall
+
+    mix release --no-deps-check --path "$out"
+
+    runHook postInstall
+  '';
+
+  # Stripping of the binary is intentional
+  # even though it does not affect beam files
+  # it is necessary for NIFs binaries
+  postFixup = ''
+    if [ -e "$out/bin/${pname}.bat" ]; then # absent in special cases, i.e. elixir-ls
+      rm "$out/bin/${pname}.bat" # windows file
+    fi
+    # contains secrets and should not be in the nix store
+    # TODO document how to handle RELEASE_COOKIE
+    # secrets should not be in the nix store.
+    # This is only used for connecting multiple nodes
+    if [ -e $out/releases/COOKIE ]; then # absent in special cases, i.e. elixir-ls
+      rm $out/releases/COOKIE
+    fi
+    # removing unused erlang reference from resulting derivation to reduce
+    # closure size
+    if [ -e $out/erts-* ]; then
+      echo "ERTS found in $out - removing references to erlang to reduce closure size"
+      # there is a link in $out/erts-*/bin/start always
+      # sometimes there are links in dependencies like bcrypt compiled binaries
+      for file in $(rg "${erlang}/lib/erlang" "$out" --text --files-with-matches); do
+        substituteInPlace "$file" --replace "${erlang}/lib/erlang" "$out"
+      done
+    fi
+  '';
+
+  # TODO investigate why the resulting closure still has
+  # a reference to erlang.
+  # uncommenting the following will fail the build
+  # disallowedReferences = [ erlang ];
+})
diff --git a/pkgs/development/beam-modules/pc/default.nix b/pkgs/development/beam-modules/pc/default.nix
index d30b0fbdbd2..2896a325e0e 100644
--- a/pkgs/development/beam-modules/pc/default.nix
+++ b/pkgs/development/beam-modules/pc/default.nix
@@ -1,13 +1,13 @@
-{ stdenv, buildHex }:
+{ lib, buildHex }:
 
 buildHex {
   name = "pc";
-  version = "1.6.0";
-  sha256 = "0xq411ig5ny3iilkkkqa4vm3w3dgjc9cfzkqwk8pm13dw9mcm8h0";
+  version = "1.12.0";
+  sha256 = "1gdvixy4j560qjdiv5qjgnl5wl3rrn231dv1m4vdq4b9l4g4p27x";
 
   meta = {
-    description = ''a rebar3 port compiler for native code'';
-    license = stdenv.lib.licenses.mit;
+    description = "a rebar3 port compiler for native code";
+    license = lib.licenses.mit;
     homepage = "https://github.com/blt/port_compiler";
   };
 }
diff --git a/pkgs/development/beam-modules/pgsql/default.nix b/pkgs/development/beam-modules/pgsql/default.nix
index c7e7aee1001..df6561b7cf1 100644
--- a/pkgs/development/beam-modules/pgsql/default.nix
+++ b/pkgs/development/beam-modules/pgsql/default.nix
@@ -1,4 +1,4 @@
-{stdenv, fetchFromGitHub, buildRebar3 }:
+{ lib, stdenv, fetchFromGitHub, buildRebar3 }:
 
 let
   shell = drv: stdenv.mkDerivation {
@@ -21,9 +21,9 @@ let
 
     meta = {
       description = "Erlang PostgreSQL Driver";
-      license = stdenv.lib.licenses.mit;
+      license = lib.licenses.mit;
       homepage = "https://github.com/semiocast/pgsql";
-      maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
+      maintainers = with lib.maintainers; [ ericbmerritt ];
     };
 
     passthru = {
@@ -31,4 +31,4 @@ let
     };
 
 };
-in stdenv.lib.fix pkg
+in lib.fix pkg
diff --git a/pkgs/development/beam-modules/rebar3-nix/default.nix b/pkgs/development/beam-modules/rebar3-nix/default.nix
new file mode 100644
index 00000000000..50bd2965835
--- /dev/null
+++ b/pkgs/development/beam-modules/rebar3-nix/default.nix
@@ -0,0 +1,18 @@
+{ lib, buildRebar3, fetchFromGitHub }:
+buildRebar3 rec {
+  name = "rebar3_nix";
+  version = "0.1.1";
+  src = fetchFromGitHub {
+    owner = "erlang-nix";
+    repo = name;
+    rev = "v${version}";
+    sha256 = "10ijc06qvv5hqv0qy3w7mbv9pshdb8bvy0f3phr1vd5hksbk731y";
+  };
+
+  meta = {
+    description = "nix integration for rebar3";
+    license = lib.licenses.bsd3;
+    homepage = "https://github.com/erlang-nix/rebar3_nix";
+    maintainers = with lib.maintainers; [ dlesl gleber ];
+  };
+}
diff --git a/pkgs/development/beam-modules/rebar3-proper/default.nix b/pkgs/development/beam-modules/rebar3-proper/default.nix
new file mode 100644
index 00000000000..2955beeeb5b
--- /dev/null
+++ b/pkgs/development/beam-modules/rebar3-proper/default.nix
@@ -0,0 +1,13 @@
+{ lib, buildHex }:
+
+buildHex {
+  name = "rebar3_proper";
+  version = "0.12.1";
+  sha256 = "1f174fb6h2071wr7qbw9aqqvnglzsjlylmyi8215fhrmi38w94b6";
+
+  meta = {
+    description = "rebar3 proper plugin";
+    license = lib.licenses.bsd3;
+    homepage = "https://github.com/ferd/rebar3_proper";
+  };
+}
diff --git a/pkgs/development/beam-modules/rebar3-release.nix b/pkgs/development/beam-modules/rebar3-release.nix
index 1ec9f244d6c..59771c34029 100644
--- a/pkgs/development/beam-modules/rebar3-release.nix
+++ b/pkgs/development/beam-modules/rebar3-release.nix
@@ -1,83 +1,108 @@
-{ stdenv, writeText, erlang, rebar3, openssl,
-  lib }:
+{ stdenv
+, erlang
+, rebar3WithPlugins
+, openssl
+, lib
+}:
 
-{ name, version
+{ pname
+, version
 , src
+, beamDeps ? [ ]
+, buildPlugins ? [ ]
 , checkouts ? null
 , releaseType
-, buildInputs ? []
+, buildInputs ? [ ]
 , setupHook ? null
 , profile ? "default"
 , installPhase ? null
 , buildPhase ? null
 , configurePhase ? null
-, meta ? {}
-, enableDebugInfo ? false
-, ... }@attrs:
+, meta ? { }
+, ...
+}@attrs:
 
-with stdenv.lib;
+with lib;
 
 let
   shell = drv: stdenv.mkDerivation {
-          name = "interactive-shell-${drv.name}";
-          buildInputs = [ drv ];
-    };
+    name = "interactive-shell-${drv.pname}";
+    buildInputs = [ drv ];
+  };
 
   customPhases = filterAttrs
     (_: v: v != null)
     { inherit setupHook configurePhase buildPhase installPhase; };
 
-  pkg = self: stdenv.mkDerivation (attrs // {
-
-    name = "${name}-${version}";
-    inherit version;
-
-    buildInputs = buildInputs ++ [ erlang rebar3 openssl ];
-    propagatedBuildInputs = [checkouts];
-
-    dontStrip = true;
-
-    inherit src;
-
-    setupHook = writeText "setupHook.sh" ''
-       addToSearchPath ERL_LIBS "$1/lib/erlang/lib/"
-    '';
-
-    configurePhase = ''
-      runHook preConfigure
-      ${if checkouts != null then
-          ''cp --no-preserve=all -R ${checkouts}/_checkouts .''
-        else
-          ''''}
-      runHook postConfigure
-    '';
-
-    buildPhase = ''
-      runHook preBuild
-      HOME=. DEBUG=1 rebar3 as ${profile} ${if releaseType == "escript"
-                                            then '' escriptize''
-                                            else '' release''}
-      runHook postBuild
-    '';
-
-    installPhase = ''
-      runHook preInstall
-      dir=${if releaseType == "escript"
-            then ''bin''
-            else ''rel''}
-      mkdir -p "$out/$dir"
-      cp -R --preserve=mode "_build/${profile}/$dir" "$out"
-      runHook postInstall
-    '';
-
-    meta = {
-      inherit (erlang.meta) platforms;
-    } // meta;
-
-    passthru = {
-      packageName = name;
-      env = shell self;
-   };
-  } // customPhases);
+  # When using the `beamDeps` argument, it is important that we use
+  # `rebar3WithPlugins` here even when there are no plugins. The vanilla
+  # `rebar3` package is an escript archive with bundled dependencies which can
+  # interfere with those in the app we are trying to build. `rebar3WithPlugins`
+  # doesn't have this issue since it puts its own deps last on the code path.
+  rebar3 = rebar3WithPlugins {
+    plugins = buildPlugins;
+  };
+
+  pkg =
+    assert beamDeps != [ ] -> checkouts == null;
+    self: stdenv.mkDerivation (attrs // {
+
+      name = "${pname}-${version}";
+      inherit version pname;
+
+      buildInputs = buildInputs ++ [ erlang rebar3 openssl ] ++ beamDeps;
+
+      # ensure we strip any native binaries (eg. NIFs, ports)
+      stripDebugList = lib.optional (releaseType == "release") "rel";
+
+      inherit src;
+
+      REBAR_IGNORE_DEPS = beamDeps != [ ];
+
+      configurePhase = ''
+        runHook preConfigure
+        ${lib.optionalString (checkouts != null)
+        "cp --no-preserve=all -R ${checkouts}/_checkouts ."}
+        runHook postConfigure
+      '';
+
+      buildPhase = ''
+        runHook preBuild
+        HOME=. DEBUG=1 rebar3 as ${profile} ${if releaseType == "escript"
+                                              then "escriptize"
+                                              else "release"}
+        runHook postBuild
+      '';
+
+      installPhase = ''
+        runHook preInstall
+        dir=${if releaseType == "escript"
+              then "bin"
+              else "rel"}
+        mkdir -p "$out/$dir" "$out/bin"
+        cp -R --preserve=mode "_build/${profile}/$dir" "$out"
+        ${lib.optionalString (releaseType == "release")
+          "find $out/rel/*/bin -type f -executable -exec ln -s -t $out/bin {} \\;"}
+        runHook postInstall
+      '';
+
+      postInstall = ''
+        for dir in $out/rel/*/erts-*; do
+          echo "ERTS found in $dir - removing references to erlang to reduce closure size"
+          for f in $dir/bin/{erl,start}; do
+            substituteInPlace "$f" --replace "${erlang}/lib/erlang" "''${dir/\/erts-*/}"
+          done
+        done
+      '';
+
+      meta = {
+        inherit (erlang.meta) platforms;
+      } // meta;
+
+      passthru = ({
+        packageName = pname;
+        env = shell self;
+      } // (if attrs ? passthru then attrs.passthru else { }));
+    } // customPhases);
 in
-  fix pkg
+fix pkg
diff --git a/pkgs/development/beam-modules/webdriver/default.nix b/pkgs/development/beam-modules/webdriver/default.nix
index 8f06f8ed7a8..1255ec59c3a 100644
--- a/pkgs/development/beam-modules/webdriver/default.nix
+++ b/pkgs/development/beam-modules/webdriver/default.nix
@@ -1,4 +1,4 @@
-{stdenv, fetchFromGitHub, writeText, erlang }:
+{ lib, stdenv, fetchFromGitHub, writeText, erlang }:
 
 let
   shell = drv: stdenv.mkDerivation {
@@ -27,9 +27,9 @@ let
 
     meta = {
       description = "WebDriver implementation in Erlang";
-      license = stdenv.lib.licenses.mit;
+      license = lib.licenses.mit;
       homepage = "https://github.com/Quviq/webdrv";
-      maintainers = with stdenv.lib.maintainers; [ ericbmerritt ];
+      maintainers = with lib.maintainers; [ ericbmerritt ];
     };
 
     passthru = {
@@ -37,4 +37,4 @@ let
     };
 
 };
-in stdenv.lib.fix pkg
+in lib.fix pkg