summary refs log tree commit diff
path: root/pkgs/development/beam-modules/rebar3-release.nix
blob: 16344f2f194cc0a16ea0609046ed9b0fe01b3650 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{ stdenv, erlang, rebar3WithPlugins, openssl,
  lib }:

{ name, version
, src
, beamDeps ? []
, buildPlugins ? []
, checkouts ? null
, releaseType
, buildInputs ? []
, setupHook ? null
, profile ? "default"
, installPhase ? null
, buildPhase ? null
, configurePhase ? null
, meta ? {}
, ... }@attrs:

with lib;

let
  shell = drv: stdenv.mkDerivation {
          name = "interactive-shell-${drv.name}";
          buildInputs = [ drv ];
    };

  customPhases = filterAttrs
    (_: v: v != null)
    { inherit setupHook configurePhase buildPhase installPhase; };

  # 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 = "${name}-${version}";
    inherit version;

    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 = name;
      env = shell self;
    } // (if attrs ? passthru then attrs.passthru else {}));
  } // customPhases);
in
  fix pkg