1{
2 stdenv,
3 erlang,
4 rebar3WithPlugins,
5 openssl,
6 lib,
7}:
8
9{
10 pname,
11 version,
12 src,
13 beamDeps ? [ ],
14 buildPlugins ? [ ],
15 checkouts ? null,
16 releaseType,
17 buildInputs ? [ ],
18 setupHook ? null,
19 profile ? "default",
20 installPhase ? null,
21 buildPhase ? null,
22 configurePhase ? null,
23 meta ? { },
24 ...
25}@attrs:
26
27let
28 shell =
29 drv:
30 stdenv.mkDerivation {
31 name = "interactive-shell-${drv.pname}";
32 buildInputs = [ drv ];
33 };
34
35 customPhases = lib.filterAttrs (_: v: v != null) {
36 inherit
37 setupHook
38 configurePhase
39 buildPhase
40 installPhase
41 ;
42 };
43
44 # When using the `beamDeps` argument, it is important that we use
45 # `rebar3WithPlugins` here even when there are no plugins. The vanilla
46 # `rebar3` package is an escript archive with bundled dependencies which can
47 # interfere with those in the app we are trying to build. `rebar3WithPlugins`
48 # doesn't have this issue since it puts its own deps last on the code path.
49 rebar3 = rebar3WithPlugins {
50 plugins = buildPlugins;
51 };
52
53 pkg =
54 assert beamDeps != [ ] -> checkouts == null;
55 self:
56 stdenv.mkDerivation (
57 attrs
58 // {
59
60 name = "${pname}-${version}";
61 inherit version pname;
62
63 buildInputs =
64 buildInputs
65 ++ [
66 erlang
67 rebar3
68 openssl
69 ]
70 ++ beamDeps;
71
72 # ensure we strip any native binaries (eg. NIFs, ports)
73 stripDebugList = lib.optional (releaseType == "release") "rel";
74
75 inherit src;
76
77 REBAR_IGNORE_DEPS = beamDeps != [ ];
78
79 configurePhase = ''
80 runHook preConfigure
81 ${lib.optionalString (checkouts != null) "cp --no-preserve=all -R ${checkouts}/_checkouts ."}
82 runHook postConfigure
83 '';
84
85 buildPhase = ''
86 runHook preBuild
87 HOME=. DEBUG=1 rebar3 as ${profile} ${if releaseType == "escript" then "escriptize" else "release"}
88 runHook postBuild
89 '';
90
91 installPhase = ''
92 runHook preInstall
93 dir=${if releaseType == "escript" then "bin" else "rel"}
94 mkdir -p "$out/$dir" "$out/bin"
95 cp -R --preserve=mode "_build/${profile}/$dir" "$out"
96 ${lib.optionalString (
97 releaseType == "release"
98 ) "find $out/rel/*/bin -type f -executable -exec ln -s -t $out/bin {} \\;"}
99 runHook postInstall
100 '';
101
102 # Release will generate a binary which will cause a read null byte failure, see #261354
103 postInstall = lib.optionalString (releaseType == "escript") ''
104 for dir in $out/rel/*/erts-*; do
105 echo "ERTS found in $dir - removing references to erlang to reduce closure size"
106 for f in $dir/bin/{erl,start}; do
107 substituteInPlace "$f" --replace "${erlang}/lib/erlang" "''${dir/\/erts-*/}"
108 done
109 done
110 '';
111
112 meta = {
113 inherit (erlang.meta) platforms;
114 }
115 // meta;
116
117 passthru = (
118 {
119 packageName = pname;
120 env = shell self;
121 }
122 // (if attrs ? passthru then attrs.passthru else { })
123 );
124 }
125 // customPhases
126 );
127in
128lib.fix pkg