mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-09-29 19:30:11 +00:00
beamPackages.mixRelease: refactor phases into hooks (#563431)
This commit is contained in:
@@ -28,7 +28,6 @@ beamPackages.mixRelease rec {
|
||||
|
||||
nativeBuildInputs = [
|
||||
git
|
||||
cmake
|
||||
];
|
||||
|
||||
mixNixDeps = import ./mix.nix {
|
||||
|
||||
@@ -82,9 +82,14 @@ makeScopeWithSplicing' {
|
||||
inherit (pkgs.callPackages ./hooks { })
|
||||
beamCopySourceHook
|
||||
beamModuleInstallHook
|
||||
mixAppConfigPatchHook
|
||||
mixBuildDirHook
|
||||
mixCompileHook
|
||||
mixAppConfigPatchHook
|
||||
mixDepsCompileHook
|
||||
mixEscriptSetupHook
|
||||
mixFodDepsSetupHook
|
||||
mixNixDepsSetupHook
|
||||
mixReleaseSetupHook
|
||||
rebar3CompileHook
|
||||
rebarDevendorPatchHook
|
||||
;
|
||||
|
||||
@@ -13,4 +13,6 @@ beamCopySourceHook() {
|
||||
echo "Finished beamCopySourceHook"
|
||||
}
|
||||
|
||||
postPatchHooks+=(beamCopySourceHook)
|
||||
if [ -z "${dontBeamCopySource-}" ]; then
|
||||
postPatchHooks+=(beamCopySourceHook)
|
||||
fi
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./beam-module-install-hook.sh;
|
||||
|
||||
mixAppConfigPatchHook = makeSetupHook {
|
||||
name = "mix-config-patch-hook.sh";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-app-config-patch-hook.sh;
|
||||
|
||||
mixBuildDirHook = makeSetupHook {
|
||||
name = "mix-configure-hook.sh";
|
||||
meta.license = lib.licenses.mit;
|
||||
@@ -23,10 +28,30 @@
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-compile-hook.sh;
|
||||
|
||||
mixAppConfigPatchHook = makeSetupHook {
|
||||
name = "mix-config-patch-hook.sh";
|
||||
mixDepsCompileHook = makeSetupHook {
|
||||
name = "mix-deps-compile-hook.sh";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-app-config-patch-hook.sh;
|
||||
} ./mix-deps-compile-hook.sh;
|
||||
|
||||
mixEscriptSetupHook = makeSetupHook {
|
||||
name = "mix-escript-setup-hook.sh";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-escript-setup-hook.sh;
|
||||
|
||||
mixFodDepsSetupHook = makeSetupHook {
|
||||
name = "mix-fod-deps-setup-hook";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-fod-deps-setup-hook.sh;
|
||||
|
||||
mixNixDepsSetupHook = makeSetupHook {
|
||||
name = "mix-nix-deps-setup-hook";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-nix-deps-setup-hook.sh;
|
||||
|
||||
mixReleaseSetupHook = makeSetupHook {
|
||||
name = "mix-release-setup-hook.sh";
|
||||
meta.license = lib.licenses.mit;
|
||||
} ./mix-release-setup-hook.sh;
|
||||
|
||||
rebar3CompileHook = makeSetupHook {
|
||||
name = "rebar3-compile-hook.sh";
|
||||
|
||||
@@ -16,4 +16,6 @@ mixAppConfigPatchHook() {
|
||||
echo "Finished mixAppConfigPatchHook"
|
||||
}
|
||||
|
||||
prePatchHooks+=(mixAppConfigPatchHook)
|
||||
if [ -z "${dontMixAppConfigPatch-}" ]; then
|
||||
prePatchHooks+=(mixAppConfigPatchHook)
|
||||
fi
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
mixBuildDirHook() {
|
||||
echo "Executing mixBuildDirHook"
|
||||
|
||||
local lib dir dest build_dir
|
||||
|
||||
mkdir -p _build/"$MIX_BUILD_PREFIX"/lib
|
||||
while read -r -d ':' lib; do
|
||||
while IFS= read -r -d ':' lib; do
|
||||
[ -n "$lib" ] || continue
|
||||
for dir in "$lib"/*; do
|
||||
[ -d "$dir" ] || continue
|
||||
# Strip version number for directory name if it exists, so naming of
|
||||
# all libs matches what mix's expectation.
|
||||
dest=$(basename "$dir" | cut -d '-' -f1)
|
||||
|
||||
19
pkgs/development/beam-modules/hooks/mix-deps-compile-hook.sh
Executable file
19
pkgs/development/beam-modules/hooks/mix-deps-compile-hook.sh
Executable file
@@ -0,0 +1,19 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# 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.
|
||||
|
||||
mixDepsCompileHook() {
|
||||
echo "Executing mixDepsCompileHook"
|
||||
|
||||
mix deps.compile --no-deps-check --skip-umbrella-children
|
||||
|
||||
echo "Finished mixDepsCompileHook"
|
||||
}
|
||||
|
||||
if [ -z "${dontMixDepsCompile-}" ]; then
|
||||
postConfigureHooks+=(mixDepsCompileHook)
|
||||
fi
|
||||
@@ -0,0 +1,30 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
mixEscriptBuild() {
|
||||
echo "Executing mixEscriptBuild"
|
||||
|
||||
mix escript.build --no-deps-check
|
||||
|
||||
echo "Finished mixEscriptBuild"
|
||||
}
|
||||
|
||||
mixEscriptInstall() {
|
||||
echo "Executing mixEscriptInstall"
|
||||
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p "$out/bin"
|
||||
cp "$escriptBinName" "$out/bin"
|
||||
|
||||
runHook postInstall
|
||||
|
||||
echo "Finished mixEscriptInstall"
|
||||
}
|
||||
|
||||
if [ -z "${dontMixEscriptBuild-}" ]; then
|
||||
postBuildHooks+=(mixEscriptBuild)
|
||||
fi
|
||||
|
||||
if [ -z "${dontMixEscriptInstall-}" ] && [ -z "${installPhase-}" ]; then
|
||||
installPhase=mixEscriptInstall
|
||||
fi
|
||||
29
pkgs/development/beam-modules/hooks/mix-fod-deps-setup-hook.sh
Executable file
29
pkgs/development/beam-modules/hooks/mix-fod-deps-setup-hook.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
mixFodDepsPostUnpack() {
|
||||
echo "Executing mixFodDepsPostUnpack"
|
||||
|
||||
if [ -n "${mixFodDeps-}" ]; then
|
||||
# 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"
|
||||
cp --no-preserve=mode -R "${mixFodDeps}" "$MIX_DEPS_PATH"
|
||||
fi
|
||||
|
||||
echo "Finished mixFodDepsPostUnpack"
|
||||
}
|
||||
|
||||
mixFodDepsPostConfigure() {
|
||||
echo "Executing mixFodDepsPostConfigure"
|
||||
|
||||
if [ -n "${mixFodDeps-}" ]; then
|
||||
# Symlink deps to build root. Allows for mixFodDeps Phoenix projects to
|
||||
# find javascript assets.
|
||||
ln -s "$MIX_DEPS_PATH" ./deps
|
||||
fi
|
||||
|
||||
echo "Finished mixFodDepsPostConfigure"
|
||||
}
|
||||
|
||||
postUnpackHooks+=(mixFodDepsPostUnpack)
|
||||
postConfigureHooks+=(mixFodDepsPostConfigure)
|
||||
21
pkgs/development/beam-modules/hooks/mix-nix-deps-setup-hook.sh
Executable file
21
pkgs/development/beam-modules/hooks/mix-nix-deps-setup-hook.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# Symlink dependency sources. This is needed for projects that require
|
||||
# access to the source of their dependencies. For example, Phoenix
|
||||
# projects need javascript assets to build asset bundles.
|
||||
|
||||
mixNixDepsPostConfigure() {
|
||||
echo "Executing mixNixDepsPostConfigure"
|
||||
|
||||
local name
|
||||
for name in "${!mixNixDeps[@]}"; do
|
||||
if [ -d "${mixNixDeps[$name]}/src" ]; then
|
||||
mkdir -p deps
|
||||
ln -sv "${mixNixDeps[$name]}/src" "deps/$name"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Finished mixNixDepsPostConfigure"
|
||||
}
|
||||
|
||||
postConfigureHooks+=(mixNixDepsPostConfigure)
|
||||
@@ -0,0 +1,91 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
mixReleaseInstallHook() {
|
||||
echo "Executing mixReleaseInstallHook"
|
||||
|
||||
runHook preInstall
|
||||
|
||||
mix release ${mixReleaseName:+"$mixReleaseName"} --no-deps-check --path "$out"
|
||||
|
||||
runHook postInstall
|
||||
|
||||
echo "Finished mixReleaseInstallHook"
|
||||
}
|
||||
|
||||
mixReleaseFixupHook() {
|
||||
echo "Executing mixReleaseFixupHook"
|
||||
|
||||
echo "Removing files for Microsoft Windows"
|
||||
rm -f "$out"/bin/*.bat
|
||||
|
||||
echo "Wrapping programs in $out/bin with their runtime deps"
|
||||
find "$out/bin/" -type f -executable | while read f; do
|
||||
wrapProgram "$f" --prefix PATH : "$mixReleaseRuntimePath"
|
||||
done
|
||||
|
||||
# shellcheck disable=SC2144 # this will only work for a single erts
|
||||
if [ -e "$out"/erts-* ]; then
|
||||
mixReleaseRemoveErlangReferences
|
||||
fi
|
||||
|
||||
echo "Finished mixReleaseFixupHook"
|
||||
}
|
||||
|
||||
mixReleaseRemoveErlangReferences() {
|
||||
# ERTS is included in the release, then erlang is not required as a runtime dependency.
|
||||
# But, erlang is still referenced in some places. To removed references to erlang,
|
||||
# following steps are required.
|
||||
|
||||
echo "Removing references to erlang"
|
||||
|
||||
# 1. remove references to erlang from plain text files
|
||||
for file in $(rg "${erlang}/lib/erlang" "$out" --files-with-matches); do
|
||||
substituteInPlace "$file" --replace "${erlang}/lib/erlang" "$out"
|
||||
done
|
||||
|
||||
# 2. remove references to erlang from .beam files
|
||||
#
|
||||
# No need to do anything, because it has been handled by "deterministic" option specified
|
||||
# by ERL_COMPILER_OPTIONS.
|
||||
|
||||
# 3. remove references to erlang from normal binary files
|
||||
for file in $(rg "${erlang}/lib/erlang" "$out" --files-with-matches --binary --iglob '!*.beam'); do
|
||||
echo "removing references to erlang in $file"
|
||||
# use bbe to substitute strings in binary files, because using substituteInPlace
|
||||
# on binaries will raise errors
|
||||
bbe -e "s|${erlang}/lib/erlang|$out|" -o "$file".tmp "$file"
|
||||
rm -f "$file"
|
||||
mv "$file".tmp "$file"
|
||||
done
|
||||
|
||||
# References to erlang should be removed from output after above processing.
|
||||
}
|
||||
|
||||
mixReleaseRemoveCookieHook() {
|
||||
if [ -e "$out/releases/COOKIE" ]; then
|
||||
echo "Removing $out/releases/COOKIE"
|
||||
rm "$out/releases/COOKIE"
|
||||
fi
|
||||
}
|
||||
|
||||
mixReleaseStripDebugHook() {
|
||||
# Strip debug symbols to avoid hardreferences to "foreign" closures actually
|
||||
# not needed at runtime, while at the same time reduce size of BEAM files.
|
||||
erl -noinput -eval 'lists:foreach(fun(F) -> io:format("Stripping ~p.~n", [F]), beam_lib:strip(F) end, filelib:wildcard("'"$out"'/**/*.beam"))' -s init stop
|
||||
}
|
||||
|
||||
if [ -z "${dontMixReleaseFixup-}" ]; then
|
||||
preFixupHooks+=(mixReleaseFixupHook)
|
||||
fi
|
||||
|
||||
if [ -n "${removeCookie-1}" ]; then
|
||||
preFixupHooks+=(mixReleaseRemoveCookieHook)
|
||||
fi
|
||||
|
||||
if [ -n "${stripDebug-}" ]; then
|
||||
postFixupHooks+=(mixReleaseStripDebugHook)
|
||||
fi
|
||||
|
||||
if [ -z "${dontMixReleaseInstall-}" ] && [ -z "${installPhase-}" ]; then
|
||||
installPhase=mixReleaseInstallHook
|
||||
fi
|
||||
@@ -10,4 +10,6 @@ rebarDevendorPatchHook() {
|
||||
echo "Finished rebarDevendorPatchHook"
|
||||
}
|
||||
|
||||
prePatchHooks+=(rebarDevendorPatchHook)
|
||||
if [ -z "${dontRebarDevendorPatch-}" ]; then
|
||||
prePatchHooks+=(rebarDevendorPatchHook)
|
||||
fi
|
||||
|
||||
@@ -12,11 +12,18 @@
|
||||
ripgrep,
|
||||
bbe,
|
||||
makeWrapper,
|
||||
writableTmpDirAsHomeHook,
|
||||
coreutils,
|
||||
gnused,
|
||||
gnugrep,
|
||||
gawk,
|
||||
mixBuildDirHook,
|
||||
mixCompileHook,
|
||||
mixDepsCompileHook,
|
||||
mixEscriptSetupHook,
|
||||
mixFodDepsSetupHook,
|
||||
mixNixDepsSetupHook,
|
||||
mixReleaseSetupHook,
|
||||
}@inputs:
|
||||
|
||||
lib.extendMkDerivation {
|
||||
@@ -25,7 +32,6 @@ lib.extendMkDerivation {
|
||||
excludeDrvArgNames = [
|
||||
"compileFlags"
|
||||
"erlangCompilerOptions"
|
||||
"mixNixDeps"
|
||||
];
|
||||
|
||||
extendDrvArgs =
|
||||
@@ -41,6 +47,7 @@ lib.extendMkDerivation {
|
||||
mixEnv ? "prod",
|
||||
mixTarget ? "host",
|
||||
compileFlags ? [ ],
|
||||
mixCompileFlags ? compileFlags,
|
||||
# Build a particular named release.
|
||||
# see https://hexdocs.pm/mix/1.12/Mix.Tasks.Release.html#content
|
||||
mixReleaseName ? "",
|
||||
@@ -106,20 +113,22 @@ lib.extendMkDerivation {
|
||||
erlang
|
||||
elixir
|
||||
hex
|
||||
git
|
||||
mixBuildDirHook
|
||||
]
|
||||
++
|
||||
# Mix deps
|
||||
(builtins.attrValues mixNixDeps)
|
||||
++
|
||||
# other compile-time deps
|
||||
[
|
||||
findutils
|
||||
ripgrep
|
||||
|
||||
bbe
|
||||
findutils
|
||||
git
|
||||
makeWrapper
|
||||
];
|
||||
ripgrep
|
||||
writableTmpDirAsHomeHook
|
||||
|
||||
mixBuildDirHook
|
||||
mixCompileHook
|
||||
mixDepsCompileHook
|
||||
]
|
||||
++ lib.optionals (escriptBinName != null) [ mixEscriptSetupHook ]
|
||||
++ lib.optionals (escriptBinName == null) [ mixReleaseSetupHook ]
|
||||
++ lib.optionals (mixFodDeps != null) [ mixFodDepsSetupHook ]
|
||||
++ lib.optionals (mixNixDeps != { }) ([ mixNixDepsSetupHook ] ++ (builtins.attrValues mixNixDeps));
|
||||
|
||||
buildInputs = [
|
||||
bashNonInteractive
|
||||
@@ -158,147 +167,13 @@ lib.extendMkDerivation {
|
||||
}
|
||||
// (attrs.env or { });
|
||||
|
||||
postUnpack = ''
|
||||
# Mix and Hex
|
||||
export MIX_HOME="$TEMPDIR/mix"
|
||||
export HEX_HOME="$TEMPDIR/hex"
|
||||
inherit erlang;
|
||||
|
||||
# Rebar
|
||||
export REBAR_GLOBAL_CONFIG_DIR="$TEMPDIR/rebar3"
|
||||
export REBAR_CACHE_DIR="$TEMPDIR/rebar3.cache"
|
||||
|
||||
${lib.optionalString (mixFodDeps != null) ''
|
||||
# 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"
|
||||
cp --no-preserve=mode -R "${mixFodDeps}" "$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
|
||||
|
||||
# Symlink dependency sources. This is needed for projects that require
|
||||
# access to the source of their dependencies. For example, Phoenix
|
||||
# projects need javascript assets to build asset bundles.
|
||||
${lib.optionalString (mixNixDeps != { }) ''
|
||||
mkdir -p deps
|
||||
|
||||
${lib.concatMapAttrsStringSep "\n" (name: dep: ''
|
||||
dep_path="deps/${name}"
|
||||
if [ -d "${dep}/src" ]; then
|
||||
ln -sv ${dep}/src $dep_path
|
||||
fi
|
||||
'') mixNixDeps}
|
||||
''}
|
||||
|
||||
# Symlink deps to build root. Similar to above, but allows for mixFodDeps
|
||||
# Phoenix projects to find javascript assets.
|
||||
${lib.optionalString (mixFodDeps != null) ''
|
||||
ln -s "$MIX_DEPS_PATH" ./deps
|
||||
''}
|
||||
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase =
|
||||
attrs.buildPhase or ''
|
||||
runHook preBuild
|
||||
|
||||
mix compile --no-deps-check ${lib.concatStringsSep " " compileFlags}
|
||||
|
||||
${lib.optionalString (escriptBinName != null) ''
|
||||
mix escript.build --no-deps-check
|
||||
''}
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase =
|
||||
attrs.installPhase or ''
|
||||
runHook preInstall
|
||||
|
||||
${
|
||||
if (escriptBinName != null) then
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${escriptBinName} $out/bin
|
||||
''
|
||||
else
|
||||
''
|
||||
mix release ${mixReleaseName} --no-deps-check --path "$out"
|
||||
''
|
||||
}
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
postFixup = ''
|
||||
echo "removing files for Microsoft Windows"
|
||||
rm -f "$out"/bin/*.bat
|
||||
|
||||
echo "wrapping programs in $out/bin with their runtime deps"
|
||||
for f in $(find $out/bin/ -type f -executable); do
|
||||
wrapProgram "$f" \
|
||||
--prefix PATH : ${
|
||||
lib.makeBinPath [
|
||||
coreutils
|
||||
gnused
|
||||
gnugrep
|
||||
gawk
|
||||
]
|
||||
}
|
||||
done
|
||||
''
|
||||
+ lib.optionalString removeCookie ''
|
||||
if [ -e $out/releases/COOKIE ]; then
|
||||
echo "removing $out/releases/COOKIE"
|
||||
rm $out/releases/COOKIE
|
||||
fi
|
||||
''
|
||||
+ ''
|
||||
if [ -e $out/erts-* ]; then
|
||||
# ERTS is included in the release, then erlang is not required as a runtime dependency.
|
||||
# But, erlang is still referenced in some places. To removed references to erlang,
|
||||
# following steps are required.
|
||||
|
||||
# 1. remove references to erlang from plain text files
|
||||
for file in $(rg "${erlang}/lib/erlang" "$out" --files-with-matches); do
|
||||
echo "removing references to erlang in $file"
|
||||
substituteInPlace "$file" --replace "${erlang}/lib/erlang" "$out"
|
||||
done
|
||||
|
||||
# 2. remove references to erlang from .beam files
|
||||
#
|
||||
# No need to do anything, because it has been handled by "deterministic" option specified
|
||||
# by ERL_COMPILER_OPTIONS.
|
||||
|
||||
# 3. remove references to erlang from normal binary files
|
||||
for file in $(rg "${erlang}/lib/erlang" "$out" --files-with-matches --binary --iglob '!*.beam'); do
|
||||
echo "removing references to erlang in $file"
|
||||
# use bbe to substitute strings in binary files, because using substituteInPlace
|
||||
# on binaries will raise errors
|
||||
bbe -e "s|${erlang}/lib/erlang|$out|" -o "$file".tmp "$file"
|
||||
rm -f "$file"
|
||||
mv "$file".tmp "$file"
|
||||
done
|
||||
|
||||
# References to erlang should be removed from output after above processing.
|
||||
fi
|
||||
''
|
||||
+ lib.optionalString stripDebug ''
|
||||
# Strip debug symbols to avoid hardreferences to "foreign" closures actually
|
||||
# not needed at runtime, while at the same time reduce size of BEAM files.
|
||||
erl -noinput -eval 'lists:foreach(fun(F) -> io:format("Stripping ~p.~n", [F]), beam_lib:strip(F) end, filelib:wildcard("'"$out"'/**/*.beam"))' -s init stop
|
||||
'';
|
||||
mixReleaseRuntimePath = lib.makeBinPath [
|
||||
coreutils
|
||||
gnused
|
||||
gnugrep
|
||||
gawk
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user