about summary refs log tree commit diff
path: root/pkgs/development/beam-modules
diff options
context:
space:
mode:
authorLuke Granger-Brown <git@lukegb.com>2021-04-12 18:26:33 +0000
committerLuke Granger-Brown <git@lukegb.com>2021-04-12 18:49:01 +0000
commit08b22e605bc7d7560ef6ce567caa43f57178715f (patch)
treeeed46af25264ec81b18ba7a216beec55a84f6683 /pkgs/development/beam-modules
parent82ca81cd62c785b81bf530837c05babcb9cde8a5 (diff)
parent60daed57149403acbb622e48a003422eacea4c16 (diff)
Merge remote-tracking branch 'upstream/staging-next' into down-integrate-staging
Diffstat (limited to 'pkgs/development/beam-modules')
-rw-r--r--pkgs/development/beam-modules/build-mix.nix100
-rw-r--r--pkgs/development/beam-modules/default.nix134
-rw-r--r--pkgs/development/beam-modules/fetch-mix-deps.nix41
-rwxr-xr-xpkgs/development/beam-modules/mix-bootstrap108
-rw-r--r--pkgs/development/beam-modules/mix-release.nix106
5 files changed, 201 insertions, 288 deletions
diff --git a/pkgs/development/beam-modules/build-mix.nix b/pkgs/development/beam-modules/build-mix.nix
deleted file mode 100644
index 45f5e36744211..0000000000000
--- a/pkgs/development/beam-modules/build-mix.nix
+++ /dev/null
@@ -1,100 +0,0 @@
-{ stdenv, writeText, elixir, erlang, hex, lib }:
-
-{ name
-, version
-, src
-, setupHook ? null
-, buildInputs ? []
-, beamDeps ? []
-, postPatch ? ""
-, compilePorts ? false
-, installPhase ? null
-, buildPhase ? null
-, configurePhase ? null
-, meta ? {}
-, enableDebugInfo ? false
-, ... }@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;
-
-  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
-        fi
-
-        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
-    ''
-    else installPhase;
-
-    passthru = {
-      packageName = name;
-      env = shell self;
-      inherit beamDeps;
-    };
-});
-in fix pkg
diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix
index 02877a954117a..6e6da4fab0376 100644
--- a/pkgs/development/beam-modules/default.nix
+++ b/pkgs/development/beam-modules/default.nix
@@ -3,7 +3,7 @@
 let
   inherit (lib) makeExtensible;
 
-  lib' = pkgs.callPackage ./lib.nix {};
+  lib' = pkgs.callPackage ./lib.nix { };
 
   # FIXME: add support for overrideScope
   callPackageWithScope = scope: drv: args: lib.callPackageWith scope drv args;
@@ -14,70 +14,70 @@ 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 {};
-        fetchMixDeps = callPackage ./fetch-mix-deps.nix { };
-        buildMix = callPackage ./build-mix.nix {};
-
-        # BEAM-based languages.
-        elixir = elixir_1_11;
-
-        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 {
-          inherit erlang;
-          debugInfo = true;
-        };
-
-        elixir_1_7 = lib'.callElixir ../interpreters/elixir/1.7.nix {
-          inherit 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;
+
+      rebar = callPackage ../tools/build-managers/rebar { };
+      rebar3 = callPackage ../tools/build-managers/rebar3 { };
+
+      # rebar3 port compiler plugin is required by buildRebar3
+      pc = callPackage ./pc { };
+
+      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 { };
+      fetchMixDeps = callPackage ./fetch-mix-deps.nix { };
+      mixRelease = callPackage ./mix-release.nix { };
+
+      # BEAM-based languages.
+      elixir = elixir_1_11;
+
+      elixir_1_11 = lib'.callElixir ../interpreters/elixir/1.11.nix {
+        inherit erlang;
+        debugInfo = true;
       };
-in makeExtensible packages
+
+      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 {
+        inherit erlang;
+        debugInfo = true;
+      };
+
+      elixir_1_7 = lib'.callElixir ../interpreters/elixir/1.7.nix {
+        inherit 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 { };
+    };
+in
+makeExtensible packages
diff --git a/pkgs/development/beam-modules/fetch-mix-deps.nix b/pkgs/development/beam-modules/fetch-mix-deps.nix
index 020a82ad70b74..73365bd1a93e1 100644
--- a/pkgs/development/beam-modules/fetch-mix-deps.nix
+++ b/pkgs/development/beam-modules/fetch-mix-deps.nix
@@ -1,34 +1,49 @@
 { stdenvNoCC, lib, elixir, hex, rebar, rebar3, cacert, git }:
 
-{ name, version, sha256, src, mixEnv ? "prod", debug ? false, meta ? { } }:
-
-stdenvNoCC.mkDerivation ({
-  name = "mix-deps-${name}-${version}";
-
+{ pname
+, version
+, sha256
+, src
+, mixEnv ? "prod"
+, debug ? false
+, meta ? { }
+, ...
+}@attrs:
+
+stdenvNoCC.mkDerivation (attrs // {
   nativeBuildInputs = [ elixir hex cacert git ];
 
-  inherit src;
-
   MIX_ENV = mixEnv;
   MIX_DEBUG = if debug then 1 else 0;
   DEBUG = if debug then 1 else 0; # for rebar3
-
-  configurePhase = ''
+  # 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="$out";
+    export MIX_DEPS_PATH="$TEMPDIR/deps";
 
     # Rebar
-    mix local.rebar rebar "${rebar}/bin/rebar"
-    mix local.rebar rebar3 "${rebar3}/bin/rebar3"
     export REBAR_GLOBAL_CONFIG_DIR="$TMPDIR/rebar3"
     export REBAR_CACHE_DIR="$TMPDIR/rebar3.cache"
+    runHook postConfigure
   '';
 
   dontBuild = true;
 
-  installPhase = ''
+  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";
diff --git a/pkgs/development/beam-modules/mix-bootstrap b/pkgs/development/beam-modules/mix-bootstrap
deleted file mode 100755
index 7e31def71fa82..0000000000000
--- 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 0000000000000..320fcaa9c9b7c
--- /dev/null
+++ b/pkgs/development/beam-modules/mix-release.nix
@@ -0,0 +1,106 @@
+{ stdenv, lib, elixir, erlang, findutils, hex, rebar, rebar3, fetchMixDeps, makeWrapper, git }:
+
+{ pname
+, version
+, src
+, nativeBuildInputs ? [ ]
+, meta ? { }
+, enableDebugInfo ? false
+, mixEnv ? "prod"
+, compileFlags ? [ ]
+, mixDeps ? null
+, ...
+}@attrs:
+let
+  overridable = builtins.removeAttrs attrs [ "compileFlags" ];
+
+in
+stdenv.mkDerivation (overridable // {
+  nativeBuildInputs = nativeBuildInputs ++ [ erlang hex elixir makeWrapper git ];
+
+  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
+  MIX_REBAR = "${rebar}/bin/rebar";
+  MIX_REBAR3 = "${rebar3}/bin/rebar3";
+
+  postUnpack = ''
+    export HEX_HOME="$TEMPDIR/hex"
+    export MIX_HOME="$TEMPDIR/mix"
+    # 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"
+
+    # Rebar
+    export REBAR_GLOBAL_CONFIG_DIR="$TEMPDIR/rebar3"
+    export REBAR_CACHE_DIR="$TEMPDIR/rebar3.cache"
+
+    ${lib.optionalString (mixDeps != null) ''
+      cp --no-preserve=mode -R "${mixDeps}" "$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
+  '';
+
+  fixupPhase = ''
+    runHook preFixup
+    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
+    # TODO remove the uneeded reference too erlang
+    # one possible way would be
+    # for f in $(${findutils}/bin/find $out -name start); do
+    #   substituteInPlace $f \
+    #     --replace 'ROOTDIR=${erlang}/lib/erlang' 'ROOTDIR=""'
+    # done
+    # What is left to do is to check that erlang is not required on
+    # the host
+
+    patchShebangs $out
+    runHook postFixup
+  '';
+  # TODO figure out how to do a Fixed Output Derivation and add the output hash
+  # This doesn't play well at the moment with Phoenix projects
+  # for example that have frontend dependencies
+
+  # disallowedReferences = [ erlang ];
+})