diff --git a/pkgs/development/beam-modules/build-rebar3.nix b/pkgs/development/beam-modules/build-rebar3.nix index a4c9ca4eb8df..11b1c8b44e52 100644 --- a/pkgs/development/beam-modules/build-rebar3.nix +++ b/pkgs/development/beam-modules/build-rebar3.nix @@ -1,132 +1,85 @@ { + erlang, + beamCopySourceHook, + beamModuleInstallHook, + rebar3CompileHook, + rebar3WithPlugins, + rebarDevendorPatchHook, + + libyaml, + openssl, + + lib, stdenv, writeText, - erlang, - rebar3WithPlugins, - openssl, - libyaml, - lib, }: -{ - name, - version, - src, - setupHook ? null, - buildInputs ? [ ], - beamDeps ? [ ], - buildPlugins ? [ ], - postPatch ? "", - installPhase ? null, - buildPhase ? null, - configurePhase ? null, - meta ? { }, - erlangCompilerOptions ? [ ], - # Deterministic Erlang builds remove full system paths from debug information - # among other things to keep builds more reproducible. See their docs for more: - # https://www.erlang.org/doc/man/compile - erlangDeterministicBuilds ? true, - ... -}@attrs: +lib.extendMkDerivation { + constructDrv = stdenv.mkDerivation; + excludeDrvArgNames = [ + "beamDeps" + "buildPlugins" + ]; + extendDrvArgs = + finalAttrs: + { + beamDeps ? [ ], + buildPlugins ? [ ], -let - rebar3 = rebar3WithPlugins { - plugins = buildPlugins; - }; + enableDebugInfo ? false, + erlangCompilerOptions ? [ ], + # Deterministic Erlang builds remove full system paths from debug information + # among other things to keep builds more reproducible. See their docs for more: + # https://www.erlang.org/doc/man/compile + erlangDeterministicBuilds ? true, + ... + }@args: + let + rebar3Custom = rebar3WithPlugins { + plugins = buildPlugins; + }; + in + { + pname = args.name; + name = "erlang${erlang.version}-${args.name}-${finalAttrs.version}"; - shell = - drv: - stdenv.mkDerivation { - name = "interactive-shell-${drv.name}"; - buildInputs = [ drv ]; - }; + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ + rebarDevendorPatchHook + beamCopySourceHook + beamModuleInstallHook + rebar3CompileHook + ]; - customPhases = lib.filterAttrs (_: v: v != null) { - inherit - setupHook - configurePhase - buildPhase - installPhase - ; - }; + buildInputs = (args.buildInputs or [ ]) ++ [ + erlang + rebar3Custom + openssl + libyaml + ]; - pkg = - self: - stdenv.mkDerivation ( - attrs - // { - - pname = name; - name = "${name}-${version}"; - inherit version; - - buildInputs = buildInputs ++ [ - erlang - rebar3 - openssl - libyaml - ]; - propagatedBuildInputs = lib.unique beamDeps; - - inherit src; + propagatedBuildInputs = lib.unique beamDeps; + env = { ERL_COMPILER_OPTIONS = let options = erlangCompilerOptions ++ lib.optionals erlangDeterministicBuilds [ "deterministic" ]; in "[${lib.concatStringsSep "," options}]"; - # stripping does not have any effect on beam files - # it is however needed for dependencies with NIFs - # false is the default but we keep this for readability - dontStrip = false; + beamModuleName = args.name; + }; - setupHook = writeText "setupHook.sh" '' - addToSearchPath ERL_LIBS "$1/lib/erlang/lib/" - ''; + setupHook = writeText "setupHook.sh" '' + addToSearchPath ERL_LIBS "$1/lib/erlang/lib/" + ''; - postPatch = '' - rm -f rebar rebar3 - '' - + postPatch; - - preConfigure = '' - # Copy the source so it can be used by mix projects - # do this before building to avoid build artifacts but after patching - # to include any modifications - mkdir -p $out/src - cp -r "." "$out/src" - ''; - - buildPhase = '' - runHook preBuild - HOME=. rebar3 bare compile --paths "." - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - mkdir -p "$out/lib/erlang/lib/${name}-${version}" - for reldir in src ebin priv include; do - [ -d "$reldir" ] || continue - # $out/lib/erlang/lib is a convention used in nixpkgs for compiled BEAM packages - cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir" - done - runHook postInstall - ''; - - meta = { - inherit (erlang.meta) platforms; - } - // meta; - - passthru = { - packageName = name; - env = shell self; - inherit beamDeps; - }; + meta = { + inherit (erlang.meta) platforms; } - // customPhases - ); -in -lib.fix pkg + // (args.meta or { }); + + passthru = { + inherit beamDeps; + }; + }; +} diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix index 3982e43a1486..c2ed9fe6931d 100644 --- a/pkgs/development/beam-modules/default.nix +++ b/pkgs/development/beam-modules/default.nix @@ -105,6 +105,8 @@ let mixBuildDirHook mixCompileHook mixAppConfigPatchHook + rebar3CompileHook + rebarDevendorPatchHook ; }; in diff --git a/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh b/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh index 6591f4bb70f7..ba66032751bc 100644 --- a/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh +++ b/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh @@ -9,7 +9,15 @@ beamModuleInstallHook() { mkdir -p "$out/lib/erlang/lib/${beamModuleName}-${version}" - for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${beamModuleName}/{src,ebin,priv,include}; do + # default to rebar3 + local fromDir=(./{ebin,priv,include}) + + # replace if mix project + if [ -n "$MIX_BUILD_PREFIX" ]; then + fromDir=(_build/{$MIX_BUILD_PREFIX,shared}/lib/"${beamModuleName}"/{src,ebin,priv,include}) + fi + + for reldir in "${fromDir[@]}"; do if test -d "$reldir"; then # Some builds produce symlinks (eg: phoenix priv directory). They must # be followed with -H flag. diff --git a/pkgs/development/beam-modules/hooks/default.nix b/pkgs/development/beam-modules/hooks/default.nix index 000363c9d150..1be544b2f2c7 100644 --- a/pkgs/development/beam-modules/hooks/default.nix +++ b/pkgs/development/beam-modules/hooks/default.nix @@ -19,4 +19,12 @@ mixAppConfigPatchHook = makeSetupHook { name = "mix-config-patch-hook.sh"; } ./mix-app-config-patch-hook.sh; + + rebar3CompileHook = makeSetupHook { + name = "rebar3-compile-hook.sh"; + } ./rebar3-compile-hook.sh; + + rebarDevendorPatchHook = makeSetupHook { + name = "rebar-devendor-patch-hook.sh"; + } ./rebar-devendor-patch-hook.sh; } diff --git a/pkgs/development/beam-modules/hooks/rebar-devendor-patch-hook.sh b/pkgs/development/beam-modules/hooks/rebar-devendor-patch-hook.sh new file mode 100644 index 000000000000..032bf9b986fe --- /dev/null +++ b/pkgs/development/beam-modules/hooks/rebar-devendor-patch-hook.sh @@ -0,0 +1,13 @@ +# shellcheck shell=bash +# +# It's common to vendor a copy of rebar/rebar3 in repos, but we want to remove those + +rebarDevendorPatchHook() { + echo "Executing rebarDevendorPatchHook" + + rm -f rebar rebar + + echo "Finished rebarDevendorPatchHook" +} + +prePatchHooks+=(rebarDevendorPatchHook) diff --git a/pkgs/development/beam-modules/hooks/rebar3-compile-hook.sh b/pkgs/development/beam-modules/hooks/rebar3-compile-hook.sh new file mode 100755 index 000000000000..2ef0c864ece2 --- /dev/null +++ b/pkgs/development/beam-modules/hooks/rebar3-compile-hook.sh @@ -0,0 +1,17 @@ +# shellcheck shell=bash + +rebar3CompileHook() { + echo "Executing rebar3CompileHook" + + runHook preBuild + + HOME=. rebar3 bare compile --paths "." + + runHook postBuild + + echo "Finished rebar3CompileHook" +} + +if [ -z "${dontRebar3Compile-}" ] && [ -z "${buildPhase-}" ]; then + buildPhase=rebar3CompileHook +fi