--- /dev/null
+(define-module (infiniteadaptability packages elixir)
+ #:use-module (guix gexp)
+ #:use-module (guix git-download)
+ #:use-module (guix packages)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages elixir)
+ #:use-module (infiniteadaptability packages erlang))
+
+(define-public elixir-1.19.2
+ (package
+ (inherit elixir)
+ (name "elixir")
+ (version "1.19.2")
+ (source
+ (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/elixir-lang/elixir")
+ (commit (string-append "v" version))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32 "0556xjkh5229afl22av2g8gkq5ak0gfipm90ybgnq2d2brd714xh"))))
+ (arguments
+ (list
+ #:test-target "test"
+ #:parallel-tests? #f ;see <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=32171#23>
+ #:make-flags #~(list (string-append "PREFIX=" #$output))
+ #:phases
+ #~(let* ((compiler-path "lib/elixir/src/elixir_erl_compiler.erl")
+ (compiler-path-orig (string-append compiler-path ".orig")))
+ (modify-phases %standard-phases
+ (add-after 'unpack 'make-git-checkout-writable
+ (lambda _
+ (for-each make-file-writable (find-files "."))))
+ (add-after 'make-git-checkout-writable 'replace-paths
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; Note: references end up obfuscated in binary BEAM files
+ ;; where they may be invisible to the GC and graft code:
+ ;; <https://issues.guix.gnu.org/54304#11>.
+ (substitute* '("lib/mix/lib/mix/release.ex"
+ "lib/mix/lib/mix/tasks/release.init.ex")
+ (("#!/bin/sh")
+ (string-append "#!" (search-input-file inputs "/bin/sh"))))
+ (substitute* "bin/elixir"
+ (("ERTS_BIN=\n")
+ (string-append
+ "ERTS_BIN="
+ ;; Elixir Releases will prepend to ERTS_BIN the path of
+ ;; a copy of erl. We detect if a release is being
+ ;; generated by checking the initial ERTS_BIN value: if
+ ;; it's empty, we are not in release mode and can point
+ ;; to the actual erl binary in Guix store.
+ "\nif [ -z \"$ERTS_BIN\" ]; then ERTS_BIN="
+ (string-drop-right
+ (search-input-file inputs "/bin/erl") 3)
+ "; fi\n")))
+ (substitute* "bin/mix"
+ (("#!/usr/bin/env elixir")
+ (string-append "#!" #$output "/bin/elixir")))
+ ;; We should not brake the formatting, so we need patch the
+ ;; following more accurately.
+ (substitute* "lib/mix/test/mix/tasks/cmd_test.exs"
+ (("File\\.mkdir_p!\\(\"priv\"\\)" all)
+ (string-append all "\n sh = \""
+ (search-input-file inputs "/bin/sh") "\""))
+ (("#!/bin/sh") "#!#{sh}"))))
+ (add-after 'replace-paths 'pre-install-source
+ (lambda* (#:key outputs #:allow-other-keys)
+ (copy-recursively
+ "lib"
+ (string-append (assoc-ref outputs "src") "/source/lib"))))
+ (add-after 'pre-install-source 'patch-elixir-compiler
+ ;; Temporarily patch the compiler to place correct source
+ ;; locations into module info instead of build directory.
+ (lambda* (#:key outputs #:allow-other-keys)
+ (copy-recursively compiler-path compiler-path-orig)
+ (let ((source (string-append "/tmp/guix-build-" #$name "-"
+ #$version ".drv-0"))
+ (destination (assoc-ref outputs "src")))
+ (substitute* compiler-path
+ (("source, Source")
+ (string-append "source, string:replace(Source, \""
+ source "\", \"" destination "\")"))))))
+ (add-before 'build 'set-deterministic
+ (lambda _
+ ;; Set deterministic compiler option.
+ (setenv "ERL_COMPILER_OPTIONS" "deterministic")))
+ (add-after 'build 'restore-and-recompile
+ ;; Unpatch the compiler and recompile it.
+ (lambda _
+ (copy-recursively compiler-path-orig compiler-path)
+ (delete-file compiler-path-orig)
+ (invoke "erlc" "-I" "lib/elixir/include"
+ "-o" "lib/elixir/ebin" compiler-path)))
+ (add-after 'restore-and-recompile 'make-current
+ ;; The Elixir compiler checks whether or not to compile files
+ ;; by inspecting their timestamps. When the timestamp is
+ ;; equal to the epoch no compilation will be performed. Some
+ ;; tests fail when files are older than Jan 1, 2000.
+ (lambda _
+ (for-each (lambda (file)
+ (let ((recent 1400000000))
+ (utime file recent recent 0 0)))
+ (find-files "." ".*"))))
+ (add-before 'check 'set-home
+ (lambda _
+ ;; Some tests require access to a home directory.
+ (setenv "HOME" "/tmp")))
+ (delete 'configure)
+ (add-after 'install 'wrap-programs
+ (lambda* (#:key inputs outputs #:allow-other-keys)
+ (let* ((out (assoc-ref outputs "out"))
+ (programs '("elixir" "elixirc" "iex")))
+ ;; mix can be sourced as an elixir script by other elixir
+ ;; program, for example `iex -S mix`, so we should not wrap
+ ;; mix into shell script.
+ (substitute* (string-append out "/bin/mix")
+ (("Mix.CLI.main\\(\\)")
+ (format #f "\
+~~w[GUIX_ELIXIR_LIBS ERL_LIBS]
+|> Enum.map(&System.get_env/1)
+|> Enum.reject(&is_nil/1)
+|> Enum.join(\":\")
+|> case do \"\" -> :ok; erl_libs -> System.put_env(\"ERL_LIBS\", erl_libs) end
+System.put_env(\"MIX_REBAR3\", System.get_env(\"MIX_REBAR3\", \"~a\"))
+Mix.CLI.main()"
+ (search-input-file inputs "/bin/rebar3"))))
+ (for-each
+ (lambda (program)
+ (wrap-program (string-append out "/bin/" program)
+ '("ERL_LIBS" prefix ("${GUIX_ELIXIR_LIBS}"))))
+ programs))))))))
+ (inputs (modify-inputs (package-inputs elixir)
+ (replace "erlang" erlang-28.1.1)
+ (replace "rebar3" rebar)))))
+
+elixir-1.19.2