summary refs log tree commit diff
path: root/pkgs/development/beam-modules
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/beam-modules')
-rw-r--r--pkgs/development/beam-modules/default.nix2
-rw-r--r--pkgs/development/beam-modules/elixir-ls/default.nix12
-rw-r--r--pkgs/development/beam-modules/mix-release.nix162
-rw-r--r--pkgs/development/beam-modules/rebar3-release.nix3
4 files changed, 115 insertions, 64 deletions
diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix
index 421d5f7ffbc..b7b2cc9c7dc 100644
--- a/pkgs/development/beam-modules/default.nix
+++ b/pkgs/development/beam-modules/default.nix
@@ -43,7 +43,7 @@ let
       elvis-erlang = callPackage ./elvis-erlang { };
 
       # BEAM-based languages.
-      elixir = elixir_1_14;
+      elixir = elixir_1_15;
 
       elixir_1_15 = lib'.callElixir ../interpreters/elixir/1.15.nix {
         inherit erlang;
diff --git a/pkgs/development/beam-modules/elixir-ls/default.nix b/pkgs/development/beam-modules/elixir-ls/default.nix
index 949331f2fe4..9475ed35f88 100644
--- a/pkgs/development/beam-modules/elixir-ls/default.nix
+++ b/pkgs/development/beam-modules/elixir-ls/default.nix
@@ -4,16 +4,16 @@
 
 let
   pname = "elixir-ls";
-  version = "0.16.0";
+  version = "0.17.3";
   src = fetchFromGitHub {
     owner = "elixir-lsp";
     repo = "elixir-ls";
     rev = "v${version}";
-    hash = "sha256-tEKwM5o3uXJ0cLY5USnQJ+HOGTSv6NDJvq+F/iqFEWs=";
+    hash = "sha256-E+tlnkwJiyG8x29um/G7OqIDCJ/laDMTm3z7VvdWy6s=";
     fetchSubmodules = true;
   };
 in
-mixRelease  {
+mixRelease {
   inherit pname version src elixir;
 
   stripDebug = true;
@@ -21,7 +21,7 @@ mixRelease  {
   mixFodDeps = fetchMixDeps {
     pname = "mix-deps-${pname}";
     inherit src version elixir;
-    hash = "sha256-jpjqMIQ9fS4nkkKWZ80Mx5vULm5bvnNHy52ZQcR0y8c=";
+    hash = "sha256-ltSYZYsXWiq5ASvRmR7ETgK9e8bj4f9bhZAZEIceLkw=";
   };
 
   # elixir-ls is an umbrella app
@@ -49,6 +49,10 @@ mixRelease  {
     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
+
+    substitute release/debugger.sh $out/bin/elixir-debugger \
+      --replace 'exec "''${dir}/launch.sh"' "exec $out/lib/launch.sh"
+    chmod +x $out/bin/elixir-debugger
     # prepare the launcher
     substituteInPlace $out/lib/launch.sh \
       --replace "ERL_LIBS=\"\$SCRIPTPATH:\$ERL_LIBS\"" \
diff --git a/pkgs/development/beam-modules/mix-release.nix b/pkgs/development/beam-modules/mix-release.nix
index d48dc38a4b8..e5b44bc5dcd 100644
--- a/pkgs/development/beam-modules/mix-release.nix
+++ b/pkgs/development/beam-modules/mix-release.nix
@@ -1,4 +1,19 @@
-{ stdenv, lib, elixir, erlang, findutils, hex, rebar, rebar3, fetchMixDeps, makeWrapper, git, ripgrep }@inputs:
+{ stdenv
+, lib
+, elixir
+, erlang
+, hex
+, git
+, rebar
+, rebar3
+, fetchMixDeps
+, findutils
+, makeWrapper
+, coreutils
+, gnused
+, gnugrep
+, gawk
+}@inputs:
 
 { pname
 , version
@@ -10,80 +25,104 @@
 , mixEnv ? "prod"
 , compileFlags ? [ ]
 
-  # mix fixed output derivation dependencies
+  # Mix dependencies provided as a fixed output derivation
 , 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
+  # 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 finds dependencies.
 , mixNixDeps ? { }
 
 , elixir ? inputs.elixir
 , hex ? inputs.hex.override { inherit elixir; }
 
-# This reduces closure size, but can lead to some hard to understand runtime
-# errors, so use with caution. See e.g.
-# https://github.com/whitfin/cachex/issues/205
-# https://framagit.org/framasoft/mobilizon/-/issues/1169
+  # Remove releases/COOKIE
+  #
+  # People have different views on the nature of cookies. Some believe that they are
+  # secrets, while others believe they are just ids for clustering nodes instead of
+  # secrets.
+  #
+  # If you think cookie is secret, you can set this attr to true, then it will be
+  # removed from nix store. If not, you can set it to false.
+  #
+  # For backward compatibility, it is set to true by default.
+  #
+  # You can always specify a custom cookie by using RELEASE_COOKIE environment
+  # variable, regardless of the value of this attr.
+, removeCookie ? true
+
+  # This reduces closure size, but can lead to some hard to understand runtime
+  # errors, so use with caution. See e.g.
+  # https://github.com/whitfin/cachex/issues/205
+  # https://framagit.org/framasoft/mobilizon/-/issues/1169
 , stripDebug ? false
 
 , ...
 }@attrs:
 let
-  # remove non standard attributes that cannot be coerced to strings
+  # Remove non standard attributes that cannot be coerced to strings
   overridable = builtins.removeAttrs attrs [ "compileFlags" "mixNixDeps" ];
 in
 assert mixNixDeps != { } -> mixFodDeps == null;
 assert stripDebug -> !enableDebugInfo;
 
 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 = buildInputs ++ builtins.attrValues mixNixDeps;
+  nativeBuildInputs = nativeBuildInputs ++
+    # Erlang/Elixir deps
+    [ erlang elixir hex git ] ++
+    # Mix deps
+    (builtins.attrValues mixNixDeps) ++
+    # other compile-time deps
+    [ findutils makeWrapper ];
+
+  buildInputs = buildInputs;
 
   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
+  # 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";
+
   LC_ALL = "C.UTF-8";
 
   postUnpack = ''
-    export HEX_HOME="$TEMPDIR/hex"
+    # Mix and Hex
     export MIX_HOME="$TEMPDIR/mix"
+    export HEX_HOME="$TEMPDIR/hex"
 
     # 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
+      # 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
 
     ${./mix-configure-hook.sh}
-    # this is needed for projects that have a specific compile step
+
+    # 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
+    # to be available.
+    #
+    # Phoenix projects for example will need compile.phoenix.
     mix deps.compile --no-deps-check --skip-umbrella-children
 
     # Symlink dependency sources. This is needed for projects that require
     # access to the source of their dependencies. For example, Phoenix
-    # applications need javascript assets to build asset bundles.
+    # projects need javascript assets to build asset bundles.
     ${lib.optionalString (mixNixDeps != { }) ''
       mkdir -p deps
 
@@ -113,7 +152,6 @@ stdenv.mkDerivation (overridable // {
     runHook postBuild
   '';
 
-
   installPhase = attrs.installPhase or ''
     runHook preInstall
 
@@ -122,42 +160,50 @@ stdenv.mkDerivation (overridable // {
     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
+    # Remove files for Microsoft Windows
+    rm -f "$out"/bin/*.bat
+
+    # Wrap programs in $out/bin with their runtime deps
+    for f in $(find $out/bin/ -type f -executable); do
+      wrapProgram "$f" \
+        --prefix PATH : ${lib.makeBinPath [
+          coreutils
+          gnused
+          gnugrep
+          gawk
+        ]}
+    done
+  '' + lib.optionalString removeCookie ''
+    if [ -e $out/releases/COOKIE ]; then
       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
-      # TODO:
-      # sometimes there are links in dependencies like bcrypt compiled binaries
-      # at the moment those are not removed since substituteInPlace will
-      # error on binaries
-      for file in $(rg "${erlang}/lib/erlang" "$out" --files-with-matches); do
-        echo "removing reference to erlang in $file"
-        substituteInPlace "$file" --replace "${erlang}/lib/erlang" "$out"
-      done
-    fi
   '' + lib.optionalString stripDebug ''
-    # strip debug symbols to avoid hardreferences to "foreign" closures actually
+    # Strip debug symbols to avoid hardreferences to "foreign" closures actually
     # not needed at runtime, while at the same time reduce size of BEAM files.
     erl -noinput -eval 'lists:foreach(fun(F) -> io:format("Stripping ~p.~n", [F]), beam_lib:strip(F) end, filelib:wildcard("'"$out"'/**/*.beam"))' -s init stop
   '';
 
-  # TODO investigate why the resulting closure still has
-  # a reference to erlang.
-  # uncommenting the following will fail the build
-  # disallowedReferences = [ erlang ];
+  # TODO: remove erlang references in resulting derivation
+  #
+  # # Step 1 - investigate why the resulting derivation still has references to erlang.
+  #
+  # The reason is that the generated binaries contains erlang reference. Here's a repo to
+  # demonstrate the problem - <https://github.com/plastic-gun/nix-mix-release-unwanted-references>.
+  #
+  #
+  # # Step 2 - remove erlang references from the binaries
+  #
+  # As said in above repo, it's hard to remove erlang references from `.beam` binaries.
+  #
+  # We need more experienced developers to resolve this issue.
+  #
+  #
+  # # Tips
+  #
+  # When resolving this issue, it is convenient to fail the build when erlang is referenced,
+  # which can be achieved by using:
+  #
+  #   disallowedReferences = [ erlang ];
+  #
 })
diff --git a/pkgs/development/beam-modules/rebar3-release.nix b/pkgs/development/beam-modules/rebar3-release.nix
index b884809505f..621887d6cd1 100644
--- a/pkgs/development/beam-modules/rebar3-release.nix
+++ b/pkgs/development/beam-modules/rebar3-release.nix
@@ -84,7 +84,8 @@ let
         runHook postInstall
       '';
 
-      postInstall = ''
+      # Release will generate a binary which will cause a read null byte failure, see #261354
+      postInstall = lib.optionalString (releaseType == "escript") ''
         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