127 lines
3.2 KiB
Nix
127 lines
3.2 KiB
Nix
{
|
|
stdenv,
|
|
erlang,
|
|
rebar3WithPlugins,
|
|
openssl,
|
|
lib,
|
|
}:
|
|
|
|
{
|
|
pname,
|
|
version,
|
|
src,
|
|
beamDeps ? [ ],
|
|
buildPlugins ? [ ],
|
|
checkouts ? null,
|
|
releaseType,
|
|
buildInputs ? [ ],
|
|
setupHook ? null,
|
|
profile ? "default",
|
|
installPhase ? null,
|
|
buildPhase ? null,
|
|
configurePhase ? null,
|
|
meta ? { },
|
|
...
|
|
}@attrs:
|
|
|
|
let
|
|
shell =
|
|
drv:
|
|
stdenv.mkDerivation {
|
|
name = "interactive-shell-${drv.pname}";
|
|
buildInputs = [ drv ];
|
|
};
|
|
|
|
customPhases = lib.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 = "${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
|
|
'';
|
|
|
|
# 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
|
|
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
|
|
lib.fix pkg
|