From 8bdef3ae032ed12b5bbec548e3a65cf020adf457 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Mon, 15 Dec 2025 09:09:25 -0500 Subject: [PATCH 1/4] beamPackages.buildMix: update to use fixed point --- pkgs/development/beam-modules/build-mix.nix | 228 ++++++++---------- pkgs/development/beam-modules/default.nix | 8 + .../beam-modules/hooks/default.nix | 8 + .../beam-modules/hooks/mix-configure-hook.sh | 34 +++ .../beam-modules/mix-configure-hook.sh | 18 -- 5 files changed, 149 insertions(+), 147 deletions(-) create mode 100644 pkgs/development/beam-modules/hooks/default.nix create mode 100755 pkgs/development/beam-modules/hooks/mix-configure-hook.sh delete mode 100755 pkgs/development/beam-modules/mix-configure-hook.sh diff --git a/pkgs/development/beam-modules/build-mix.nix b/pkgs/development/beam-modules/build-mix.nix index d9ff7d120588..d867648abdfb 100644 --- a/pkgs/development/beam-modules/build-mix.nix +++ b/pkgs/development/beam-modules/build-mix.nix @@ -1,64 +1,46 @@ { - stdenv, - writeText, elixir, erlang, hex, lib, + mixConfigureHook, + stdenv, + writeText, }: -{ - name, - version, - src, - buildInputs ? [ ], - nativeBuildInputs ? [ ], - 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, - beamDeps ? [ ], - propagatedBuildInputs ? [ ], - postPatch ? "", - compilePorts ? false, - meta ? { }, - enableDebugInfo ? false, - mixEnv ? "prod", - mixTarget ? "host", - removeConfig ? true, - # A config directory that is considered for all the dependencies of an app, typically in $src/config/ - # This was initially added, as some of Mobilizon's dependencies need to access the config at build time. - appConfigPath ? null, - ... -}@attrs: - -assert appConfigPath != null -> removeConfig; - -let - shell = - drv: - stdenv.mkDerivation { - name = "interactive-shell-${drv.name}"; - buildInputs = [ drv ]; - }; - - pkg = - self: - stdenv.mkDerivation ( - attrs - // { - name = "${name}-${version}"; - inherit version src; +lib.extendMkDerivation { + constructDrv = stdenv.mkDerivation; + excludeDrvArgNames = [ + "mixEnv" + ]; + extendDrvArgs = + finalAttrs: + { + nativeBuildInputs ? [ ], + propagatedBuildInputs ? [ ], + passthru ? { }, + mixEnv ? "prod", + mixTarget ? "host", + enableDebugInfo ? false, + # A handful of libraries require compile time configuration + appConfigPath ? null, + 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, + beamDeps ? [ ], + ... + }@args: + { + name = "erlang-${erlang.version}-${args.name}-${finalAttrs.version}"; + env = { MIX_ENV = mixEnv; MIX_TARGET = mixTarget; MIX_BUILD_PREFIX = (if mixTarget == "host" then "" else "${mixTarget}_") + "${mixEnv}"; MIX_DEBUG = if enableDebugInfo then 1 else 0; HEX_OFFLINE = 1; - - __darwinAllowLocalNetworking = true; - ERL_COMPILER_OPTIONS = let options = erlangCompilerOptions ++ lib.optionals erlangDeterministicBuilds [ "deterministic" ]; @@ -67,93 +49,81 @@ let LANG = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "C"; LC_CTYPE = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "UTF-8"; + __darwinAllowLocalNetworking = true; + }; - # add to ERL_LIBS so other modules can find at runtime. - # http://erlang.org/doc/man/code.html#code-path - # Mix also searches the code path when compiling with the --no-deps-check flag - setupHook = attrs.setupHook or writeText "setupHook.sh" '' - addToSearchPath ERL_LIBS "$1/lib/erlang/lib" + # add to ERL_LIBS so other modules can find at runtime. + # http://erlang.org/doc/man/code.html#code-path + # Mix also searches the code path when compiling with the --no-deps-check flag + # This is used by package builders such as mixRelease + setupHook = writeText "setupHook.sh" '' + addToSearchPath ERL_LIBS "$1/lib/erlang/lib" + ''; + + nativeBuildInputs = nativeBuildInputs ++ [ + elixir + hex + mixConfigureHook + ]; + propagatedBuildInputs = propagatedBuildInputs ++ beamDeps; + + # We don't want to include whatever config a dependency brings; per + # https://hexdocs.pm/elixir/main/Config.html, config is application specific. + patchPhase = + args.patchPhase or ( + '' + runHook prePatch + + rm -rf config + '' + + lib.optionalString (!isNull appConfigPath) '' + cp -r ${appConfigPath} config + '' + + '' + runHook postPatch + '' + ); + + buildPhase = + args.buildPhase or '' + runHook preBuild + + export HEX_HOME="$TEMPDIR/hex" + export MIX_HOME="$TEMPDIR/mix" + mix compile --no-deps-check + + runHook postBuild ''; - buildInputs = buildInputs ++ [ ]; - nativeBuildInputs = nativeBuildInputs ++ [ - elixir - hex - ]; - propagatedBuildInputs = propagatedBuildInputs ++ beamDeps; + installPhase = + args.installPhase or '' + runHook preInstall - configurePhase = - attrs.configurePhase or '' - runHook preConfigure + # This uses the install path convention established by nixpkgs maintainers + # for all beam packages. Changing this will break compatibility with other + # builder functions like buildRebar3 and buildErlangMk. + mkdir -p "$out/lib/erlang/lib/${finalAttrs.name}-${finalAttrs.version}-${args.version}" - ${./mix-configure-hook.sh} - ${lib.optionalString (removeConfig && isNull appConfigPath) - # By default, we don't want to include whatever config a dependency brings; per - # https://hexdocs.pm/elixir/main/Config.html, config is application specific. - '' - rm -rf config - mkdir config - '' - } - ${lib.optionalString (!isNull appConfigPath) - # Some more tightly-coupled dependencies do depend on the config of the application - # they're being built for. - '' - rm -rf config - cp -r ${appConfigPath} config - '' - } + # Some packages like db_connection will use _build/shared instead of + # honoring the $MIX_ENV variable. + for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${finalAttrs.name}-${finalAttrs.version}/{src,ebin,priv,include} ; do + if test -d $reldir ; then + # Some builds produce symlinks (eg: phoenix priv dircetory). They must + # be followed with -H flag. + cp -Hrt "$out/lib/erlang/lib/${finalAttrs.name}-${finalAttrs.version}" "$reldir" + fi + done - runHook postConfigure - ''; + runHook postInstall + ''; - buildPhase = - attrs.buildPhase or '' - runHook preBuild - export HEX_HOME="$TEMPDIR/hex" - export MIX_HOME="$TEMPDIR/mix" - mix compile --no-deps-check - runHook postBuild - ''; + # stripping does not have any effect on beam files + # it is however needed for dependencies with NIFs like bcrypt for example + dontStrip = args.dontStrip or false; - installPhase = - attrs.installPhase or '' - runHook preInstall - - # This uses the install path convention established by nixpkgs maintainers - # for all beam packages. Changing this will break compatibility with other - # builder functions like buildRebar3 and buildErlangMk. - mkdir -p "$out/lib/erlang/lib/${name}-${version}" - - # Some packages like db_connection will use _build/shared instead of - # honoring the $MIX_ENV variable. - for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${name}/{src,ebin,priv,include} ; do - if test -d $reldir ; then - # Some builds produce symlinks (eg: phoenix priv dircetory). They must - # be followed with -H flag. - cp -Hrt "$out/lib/erlang/lib/${name}-${version}" "$reldir" - fi - done - - # Copy the source so it can be used by dependent packages. For example, - # phoenix applications need the source of phoenix and phoenix_html to - # build javascript and css assets. - mkdir -p $out/src - cp -r "$src/." "$out/src" - - runHook postInstall - ''; - - # stripping does not have any effect on beam files - # it is however needed for dependencies with NIFs like bcrypt for example - dontStrip = false; - - passthru = { - packageName = name; - env = shell self; - inherit beamDeps; - }; + passthru = { + inherit beamDeps; } - ); -in -lib.fix pkg + // passthru; + }; +} diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix index 0bcee85e7fcc..4102f0a60031 100644 --- a/pkgs/development/beam-modules/default.nix +++ b/pkgs/development/beam-modules/default.nix @@ -11,6 +11,9 @@ let callPackageWithScope = scope: drv: args: lib.callPackageWith scope drv args; + callPackagesWithScope = + scope: drv: args: + lib.callPackagesWith scope drv args; mkScope = scope: pkgs // scope; packages = @@ -18,6 +21,7 @@ let let defaultScope = mkScope self; callPackage = drv: args: callPackageWithScope defaultScope drv args; + callPackages = drv: args: callPackagesWithScope defaultScope drv args; in rec { inherit callPackage erlang; @@ -95,6 +99,10 @@ let # without helper functions buildRebar3 and buildMix. hex = callPackage ./hex { }; webdriver = callPackage ./webdriver { }; + + inherit (callPackages ./hooks { }) + mixConfigureHook + ; }; in makeExtensible packages diff --git a/pkgs/development/beam-modules/hooks/default.nix b/pkgs/development/beam-modules/hooks/default.nix new file mode 100644 index 000000000000..9bf74f5dbbb3 --- /dev/null +++ b/pkgs/development/beam-modules/hooks/default.nix @@ -0,0 +1,8 @@ +{ + makeSetupHook, +}: +{ + mixConfigureHook = makeSetupHook { + name = "mix-configure-hook.sh"; + } ./mix-configure-hook.sh; +} diff --git a/pkgs/development/beam-modules/hooks/mix-configure-hook.sh b/pkgs/development/beam-modules/hooks/mix-configure-hook.sh new file mode 100755 index 000000000000..56851bc9fb9d --- /dev/null +++ b/pkgs/development/beam-modules/hooks/mix-configure-hook.sh @@ -0,0 +1,34 @@ +# shellcheck shell=bash +mixConfigureHook() { + echo "Executing mixConfigureHook" + + runHook 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" + + # Symlink all dependencies found in ERL_LIBS since Elixir does not honor ERL_LIBS + mkdir -p _build/"$MIX_BUILD_PREFIX"/lib + while read -r -d ':' lib; do + for dir in "$lib"/*; do + # 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) + build_dir="_build/$MIX_BUILD_PREFIX/lib/$dest" + ((MIX_DEBUG == 1)) && echo "Linking $dir to $build_dir" + # Symlink libs to _build so that mix can find them when compiling. + # This is what allows mix to compile the package without searching + # for dependencies over the network. + ln -s "$dir" "$build_dir" + done + done <<<"$ERL_LIBS:" + + runHook postConfigure +} + +if [ -z "${dontCargoConfigure-}" ] && [ -z "${configurePhase-}" ]; then + configurePhase=mixConfigureHook +fi diff --git a/pkgs/development/beam-modules/mix-configure-hook.sh b/pkgs/development/beam-modules/mix-configure-hook.sh deleted file mode 100755 index 8c0ee23d5a1c..000000000000 --- a/pkgs/development/beam-modules/mix-configure-hook.sh +++ /dev/null @@ -1,18 +0,0 @@ -# shellcheck shell=bash -# this hook will symlink all dependencies found in ERL_LIBS -# since Elixir 1.12.2 elixir does not look into ERL_LIBS for -# elixir depencencies anymore, so those have to be symlinked to the _build directory -mkdir -p _build/"$MIX_BUILD_PREFIX"/lib -while read -r -d ':' lib; do - for dir in "$lib"/*; do - # 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) - build_dir="_build/$MIX_BUILD_PREFIX/lib/$dest" - ((MIX_DEBUG == 1)) && echo "Linking $dir to $build_dir" - # Symlink libs to _build so that mix can find them when compiling. - # This is what allows mix to compile the package without searching - # for dependencies over the network. - ln -s "$dir" "$build_dir" - done -done <<< "$ERL_LIBS:" From d1972278b5292faefe31e2f81ef57cd06598b387 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Mon, 29 Dec 2025 13:21:40 -0500 Subject: [PATCH 2/4] beamPackages.buildMix: move phases to hooks --- pkgs/development/beam-modules/build-mix.nix | 106 ++++++------------ pkgs/development/beam-modules/default.nix | 6 +- .../hooks/beam-copy-source-hook.sh | 16 +++ .../hooks/beam-module-install-hook.sh | 25 +++++ .../beam-modules/hooks/default.nix | 24 +++- .../hooks/mix-app-config-patch-hook.sh | 19 ++++ .../beam-modules/hooks/mix-build-dir-hook.sh | 26 +++++ .../beam-modules/hooks/mix-compile-hook.sh | 20 ++++ .../beam-modules/hooks/mix-configure-hook.sh | 34 ------ .../beam-modules/mix-configure-hook.sh | 5 + pkgs/development/beam-modules/mix-release.nix | 2 - pkgs/servers/mobilizon/default.nix | 1 + 12 files changed, 169 insertions(+), 115 deletions(-) create mode 100755 pkgs/development/beam-modules/hooks/beam-copy-source-hook.sh create mode 100644 pkgs/development/beam-modules/hooks/beam-module-install-hook.sh create mode 100644 pkgs/development/beam-modules/hooks/mix-app-config-patch-hook.sh create mode 100755 pkgs/development/beam-modules/hooks/mix-build-dir-hook.sh create mode 100755 pkgs/development/beam-modules/hooks/mix-compile-hook.sh delete mode 100755 pkgs/development/beam-modules/hooks/mix-configure-hook.sh create mode 100755 pkgs/development/beam-modules/mix-configure-hook.sh diff --git a/pkgs/development/beam-modules/build-mix.nix b/pkgs/development/beam-modules/build-mix.nix index d867648abdfb..52c0ce1ad1f8 100644 --- a/pkgs/development/beam-modules/build-mix.nix +++ b/pkgs/development/beam-modules/build-mix.nix @@ -2,8 +2,13 @@ elixir, erlang, hex, + beamCopySourceHook, + beamModuleInstallHook, + mixBuildDirHook, + mixCompileHook, + mixAppConfigPatchHook, + lib, - mixConfigureHook, stdenv, writeText, }: @@ -16,42 +21,46 @@ lib.extendMkDerivation { extendDrvArgs = finalAttrs: { - nativeBuildInputs ? [ ], - propagatedBuildInputs ? [ ], - passthru ? { }, + beamDeps ? [ ], mixEnv ? "prod", mixTarget ? "host", - enableDebugInfo ? false, - # A handful of libraries require compile time configuration + + # Allow passing compile time config instead of an empty config appConfigPath ? null, + + 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, - beamDeps ? [ ], ... }@args: { - name = "erlang-${erlang.version}-${args.name}-${finalAttrs.version}"; + name = "erlang${erlang.version}-${args.name}-${finalAttrs.version}"; env = { - MIX_ENV = mixEnv; - MIX_TARGET = mixTarget; - MIX_BUILD_PREFIX = (if mixTarget == "host" then "" else "${mixTarget}_") + "${mixEnv}"; - MIX_DEBUG = if enableDebugInfo then 1 else 0; - HEX_OFFLINE = 1; ERL_COMPILER_OPTIONS = let options = erlangCompilerOptions ++ lib.optionals erlangDeterministicBuilds [ "deterministic" ]; in "[${lib.concatStringsSep "," options}]"; + MIX_ENV = mixEnv; + MIX_TARGET = mixTarget; + MIX_BUILD_PREFIX = (if mixTarget == "host" then "" else "${mixTarget}_") + "${mixEnv}"; + MIX_DEBUG = if enableDebugInfo then 1 else 0; + HEX_OFFLINE = 1; + LANG = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "C"; LC_CTYPE = if stdenv.hostPlatform.isLinux then "C.UTF-8" else "UTF-8"; - __darwinAllowLocalNetworking = true; + + # some hooks need name-version, but we've overridden name above for the nix package + beamModuleName = args.name; }; + __darwinAllowLocalNetworking = true; + # add to ERL_LIBS so other modules can find at runtime. # http://erlang.org/doc/man/code.html#code-path # Mix also searches the code path when compiling with the --no-deps-check flag @@ -60,70 +69,21 @@ lib.extendMkDerivation { addToSearchPath ERL_LIBS "$1/lib/erlang/lib" ''; - nativeBuildInputs = nativeBuildInputs ++ [ + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ elixir hex - mixConfigureHook + + beamCopySourceHook + beamModuleInstallHook + mixBuildDirHook + mixCompileHook + mixAppConfigPatchHook ]; - propagatedBuildInputs = propagatedBuildInputs ++ beamDeps; - # We don't want to include whatever config a dependency brings; per - # https://hexdocs.pm/elixir/main/Config.html, config is application specific. - patchPhase = - args.patchPhase or ( - '' - runHook prePatch + propagatedBuildInputs = (args.propagatedBuildInputs or [ ]) ++ beamDeps; - rm -rf config - '' - + lib.optionalString (!isNull appConfigPath) '' - cp -r ${appConfigPath} config - '' - + '' - runHook postPatch - '' - ); - - buildPhase = - args.buildPhase or '' - runHook preBuild - - export HEX_HOME="$TEMPDIR/hex" - export MIX_HOME="$TEMPDIR/mix" - mix compile --no-deps-check - - runHook postBuild - ''; - - installPhase = - args.installPhase or '' - runHook preInstall - - # This uses the install path convention established by nixpkgs maintainers - # for all beam packages. Changing this will break compatibility with other - # builder functions like buildRebar3 and buildErlangMk. - mkdir -p "$out/lib/erlang/lib/${finalAttrs.name}-${finalAttrs.version}-${args.version}" - - # Some packages like db_connection will use _build/shared instead of - # honoring the $MIX_ENV variable. - for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${finalAttrs.name}-${finalAttrs.version}/{src,ebin,priv,include} ; do - if test -d $reldir ; then - # Some builds produce symlinks (eg: phoenix priv dircetory). They must - # be followed with -H flag. - cp -Hrt "$out/lib/erlang/lib/${finalAttrs.name}-${finalAttrs.version}" "$reldir" - fi - done - - runHook postInstall - ''; - - # stripping does not have any effect on beam files - # it is however needed for dependencies with NIFs like bcrypt for example - dontStrip = args.dontStrip or false; - - passthru = { + passthru = (args.passthru or { }) // { inherit beamDeps; - } - // passthru; + }; }; } diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix index 4102f0a60031..0fec22df3458 100644 --- a/pkgs/development/beam-modules/default.nix +++ b/pkgs/development/beam-modules/default.nix @@ -101,7 +101,11 @@ let webdriver = callPackage ./webdriver { }; inherit (callPackages ./hooks { }) - mixConfigureHook + beamCopySourceHook + beamModuleInstallHook + mixBuildDirHook + mixCompileHook + mixAppConfigPatchHook ; }; in diff --git a/pkgs/development/beam-modules/hooks/beam-copy-source-hook.sh b/pkgs/development/beam-modules/hooks/beam-copy-source-hook.sh new file mode 100755 index 000000000000..a4ffa9fd1413 --- /dev/null +++ b/pkgs/development/beam-modules/hooks/beam-copy-source-hook.sh @@ -0,0 +1,16 @@ +# shellcheck shell=bash +# +# Copy the source so it can be used by mix projects to assemble `deps` +# do this before building to avoid build artifacts but after patching +# to include any user modifications to the source + +beamCopySourceHook() { + echo "Executing beamCopySourceHook" + + mkdir -p "$out/src" + cp -r "." "$out/src" + + echo "Finished beamCopySourceHook" +} + +postPatchHooks+=(beamCopySourceHook) diff --git a/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh b/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh new file mode 100644 index 000000000000..6591f4bb70f7 --- /dev/null +++ b/pkgs/development/beam-modules/hooks/beam-module-install-hook.sh @@ -0,0 +1,25 @@ +# shellcheck shell=bash +# +# This uses the install path convention established by nixpkgs maintainers +# for all beam packages. Changing this will break compatibility with other +# builder functions like buildRebar3 and buildErlangMk. + +beamModuleInstallHook() { + echo "Executing beamModuleInstallHook" + + mkdir -p "$out/lib/erlang/lib/${beamModuleName}-${version}" + + for reldir in _build/{$MIX_BUILD_PREFIX,shared}/lib/${beamModuleName}/{src,ebin,priv,include}; do + if test -d "$reldir"; then + # Some builds produce symlinks (eg: phoenix priv directory). They must + # be followed with -H flag. + cp -vHrt "$out/lib/erlang/lib/${beamModuleName}-${version}" "$reldir" + fi + done + + echo "Finished beamModuleInstallHook" +} + +if [ -z "${dontBeamModuleInstall-}" ] && [ -z "${installPhase-}" ]; then + installPhase=beamModuleInstallHook +fi diff --git a/pkgs/development/beam-modules/hooks/default.nix b/pkgs/development/beam-modules/hooks/default.nix index 9bf74f5dbbb3..000363c9d150 100644 --- a/pkgs/development/beam-modules/hooks/default.nix +++ b/pkgs/development/beam-modules/hooks/default.nix @@ -1,8 +1,22 @@ +{ makeSetupHook }: { - makeSetupHook, -}: -{ - mixConfigureHook = makeSetupHook { + beamCopySourceHook = makeSetupHook { + name = "beam-copy-source-hook.sh"; + } ./beam-copy-source-hook.sh; + + beamModuleInstallHook = makeSetupHook { + name = "beam-module-install-hook.sh"; + } ./beam-module-install-hook.sh; + + mixBuildDirHook = makeSetupHook { name = "mix-configure-hook.sh"; - } ./mix-configure-hook.sh; + } ./mix-build-dir-hook.sh; + + mixCompileHook = makeSetupHook { + name = "mix-compile-hook.sh"; + } ./mix-compile-hook.sh; + + mixAppConfigPatchHook = makeSetupHook { + name = "mix-config-patch-hook.sh"; + } ./mix-app-config-patch-hook.sh; } diff --git a/pkgs/development/beam-modules/hooks/mix-app-config-patch-hook.sh b/pkgs/development/beam-modules/hooks/mix-app-config-patch-hook.sh new file mode 100644 index 000000000000..e2153db58b4c --- /dev/null +++ b/pkgs/development/beam-modules/hooks/mix-app-config-patch-hook.sh @@ -0,0 +1,19 @@ +# shellcheck shell=bash +# +# We don't want to include whatever config a dependency brings; per +# https://hexdocs.pm/elixir/main/Config.html, config is application specific. + +mixAppConfigPatchHook() { + echo "Executing mixAppConfigPatchHook" + + rm -rvf config + + # But we still need a way to provide config for deps that need compile time config + if [ ! -z "${appConfigPath}" ]; then + ln -sf "${appConfigPath}" config + fi + + echo "Finished mixAppConfigPatchHook" +} + +prePatchHooks+=(mixAppConfigPatchHook) diff --git a/pkgs/development/beam-modules/hooks/mix-build-dir-hook.sh b/pkgs/development/beam-modules/hooks/mix-build-dir-hook.sh new file mode 100755 index 000000000000..c353aaeabc4d --- /dev/null +++ b/pkgs/development/beam-modules/hooks/mix-build-dir-hook.sh @@ -0,0 +1,26 @@ +# shellcheck shell=bash +# +# Symlink all dependencies found in ERL_LIBS since Elixir does not honor ERL_LIBS + +mixBuildDirHook() { + echo "Executing mixBuildDirHook" + + mkdir -p _build/"$MIX_BUILD_PREFIX"/lib + while read -r -d ':' lib; do + for dir in "$lib"/*; do + # 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) + build_dir="_build/$MIX_BUILD_PREFIX/lib/$dest" + + # Symlink libs to _build so that mix can find them when compiling. + # This is what allows mix to compile the package without searching + # for dependencies over the network. + ln -sv "$dir" "$build_dir" + done + done <<<"$ERL_LIBS:" + + echo "Finished mixBuildDirHook" +} + +preConfigureHooks+=(mixBuildDirHook) diff --git a/pkgs/development/beam-modules/hooks/mix-compile-hook.sh b/pkgs/development/beam-modules/hooks/mix-compile-hook.sh new file mode 100755 index 000000000000..19b27c8a94f8 --- /dev/null +++ b/pkgs/development/beam-modules/hooks/mix-compile-hook.sh @@ -0,0 +1,20 @@ +# shellcheck shell=bash + +mixCompileHook() { + echo "Executing mixCompileHook" + + runHook preBuild + + local flagsArray=() + concatTo flagsArray mixCompileFlags + + mix compile --no-deps-check "${flagsArray[@]}" + + runHook postBuild + + echo "Finished mixCompileHook" +} + +if [ -z "${dontMixCompile-}" ] && [ -z "${buildPhase-}" ]; then + buildPhase=mixCompileHook +fi diff --git a/pkgs/development/beam-modules/hooks/mix-configure-hook.sh b/pkgs/development/beam-modules/hooks/mix-configure-hook.sh deleted file mode 100755 index 56851bc9fb9d..000000000000 --- a/pkgs/development/beam-modules/hooks/mix-configure-hook.sh +++ /dev/null @@ -1,34 +0,0 @@ -# shellcheck shell=bash -mixConfigureHook() { - echo "Executing mixConfigureHook" - - runHook 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" - - # Symlink all dependencies found in ERL_LIBS since Elixir does not honor ERL_LIBS - mkdir -p _build/"$MIX_BUILD_PREFIX"/lib - while read -r -d ':' lib; do - for dir in "$lib"/*; do - # 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) - build_dir="_build/$MIX_BUILD_PREFIX/lib/$dest" - ((MIX_DEBUG == 1)) && echo "Linking $dir to $build_dir" - # Symlink libs to _build so that mix can find them when compiling. - # This is what allows mix to compile the package without searching - # for dependencies over the network. - ln -s "$dir" "$build_dir" - done - done <<<"$ERL_LIBS:" - - runHook postConfigure -} - -if [ -z "${dontCargoConfigure-}" ] && [ -z "${configurePhase-}" ]; then - configurePhase=mixConfigureHook -fi diff --git a/pkgs/development/beam-modules/mix-configure-hook.sh b/pkgs/development/beam-modules/mix-configure-hook.sh new file mode 100755 index 000000000000..80a395b8a6a0 --- /dev/null +++ b/pkgs/development/beam-modules/mix-configure-hook.sh @@ -0,0 +1,5 @@ +# Added 2026-02-12 for external users +echo "mix-configure-hook.sh has been removed and is now a setup hook. + Add 'beamPackages.mixBuildDirHook' to 'nativeBuildInputs' instead. +" >&2 +exit 1 diff --git a/pkgs/development/beam-modules/mix-release.nix b/pkgs/development/beam-modules/mix-release.nix index 27a318085710..7204c03bf567 100644 --- a/pkgs/development/beam-modules/mix-release.nix +++ b/pkgs/development/beam-modules/mix-release.nix @@ -171,8 +171,6 @@ stdenv.mkDerivation ( attrs.configurePhase or '' runHook preConfigure - ${./mix-configure-hook.sh} - # 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. diff --git a/pkgs/servers/mobilizon/default.nix b/pkgs/servers/mobilizon/default.nix index c6fe27b0bbfc..3785f84246df 100644 --- a/pkgs/servers/mobilizon/default.nix +++ b/pkgs/servers/mobilizon/default.nix @@ -146,6 +146,7 @@ mixRelease rec { ${lib.getExe nixfmt} pkgs/servers/mobilizon/mix.nix ''; elixirPackage = beamPackages.elixir; + inherit mixNixDeps; }; meta = { From 6a187b67638f85cec51ee0a2024e367ae3c27ef2 Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Wed, 11 Feb 2026 20:13:10 -0500 Subject: [PATCH 3/4] beamPackages.mixRelease: fix mixNixDeps building --- pkgs/development/beam-modules/mix-release.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/development/beam-modules/mix-release.nix b/pkgs/development/beam-modules/mix-release.nix index 7204c03bf567..bbbca0625b44 100644 --- a/pkgs/development/beam-modules/mix-release.nix +++ b/pkgs/development/beam-modules/mix-release.nix @@ -16,6 +16,7 @@ gnused, gnugrep, gawk, + mixBuildDirHook, }@inputs: { @@ -108,6 +109,7 @@ stdenv.mkDerivation ( elixir hex git + mixBuildDirHook ] ++ # Mix deps @@ -184,13 +186,12 @@ stdenv.mkDerivation ( ${lib.optionalString (mixNixDeps != { }) '' mkdir -p deps - ${lib.concatMapStringsSep "\n" (dep: '' - dep_name=$(basename ${dep} | cut -d '-' -f2) - dep_path="deps/$dep_name" + ${lib.concatMapAttrsStringSep "\n" (name: dep: '' + dep_path="deps/${name}" if [ -d "${dep}/src" ]; then - ln -s ${dep}/src $dep_path + ln -sv ${dep}/src $dep_path fi - '') (builtins.attrValues mixNixDeps)} + '') mixNixDeps} ''} # Symlink deps to build root. Similar to above, but allows for mixFodDeps From 9cbc309fb9fdc60e3773c0417c43600a363ec05e Mon Sep 17 00:00:00 2001 From: "Adam C. Stephens" Date: Fri, 13 Feb 2026 08:35:34 -0500 Subject: [PATCH 4/4] mobilizon: fix fast_html dependency building --- pkgs/servers/mobilizon/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/servers/mobilizon/default.nix b/pkgs/servers/mobilizon/default.nix index 3785f84246df..ecc7b6bcd336 100644 --- a/pkgs/servers/mobilizon/default.nix +++ b/pkgs/servers/mobilizon/default.nix @@ -40,6 +40,7 @@ mixRelease rec { // { fast_html = prev.fast_html.override { nativeBuildInputs = [ cmake ]; + dontUseCmakeConfigure = true; }; ex_cldr = prev.ex_cldr.overrideAttrs (old: { # We have to use the GitHub sources, as it otherwise tries to download