Subject: [PATCH 18/20] gnu: elixir: Add src output, metas correction, lint warnings fix.

From: Igor Goryachev <[email-masked]>
Date: Thu, 13 Jun 2024 09:17:55 +0300

* gnu/packages/elixir.scm (elixir): Add src output, metas correction, lint warnings fix.

Change-Id: I93ae35239168de9a8d8d99ca83950edfce735bc2
---
 gnu/packages/elixir.scm | 201 +++++++++++++++++++++++-----------------
 1 file changed, 114 insertions(+), 87 deletions(-)

diff --git a/gnu/packages/elixir.scm b/gnu/packages/elixir.scm
index 7675b38ffb..aa4a24fcda 100644
--- a/gnu/packages/elixir.scm
+++ b/gnu/packages/elixir.scm
@@ -34,83 +34,108 @@ (define-module (gnu packages elixir)
   #:use-module (guix git-download)
   #:use-module (guix packages)
   #:use-module (gnu packages)
+  #:use-module (gnu packages bash)
   #:use-module (gnu packages erlang)
   #:use-module (gnu packages version-control))
 
 (define-public elixir
-  (package
-    (name "elixir")
-    (version "1.16.3")
-    (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 "0db1f6p8409ld81lfd9ln9ir4v55h48lzsbd91jz0hns7ninlh2r"))
-       (patches (search-patches "elixir-path-length.patch"))))
-    (build-system gnu-build-system)
-    (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
-      #~(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")))))
-          (add-before 'build '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* (#:key inputs #:allow-other-keys)
-              ;; 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.start\\(\\)")
-                   (format #f "\
+  (let* ((compiler-path "lib/elixir/src/elixir_erl_compiler.erl")
+         (compiler-path-orig (string-append compiler-path ".orig")))
+    (package
+      (name "elixir")
+      (version "1.16.3")
+      (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 "0db1f6p8409ld81lfd9ln9ir4v55h48lzsbd91jz0hns7ninlh2r"))
+         (patches (search-patches "elixir-path-length.patch"))))
+      (build-system gnu-build-system)
+      (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
+        #~(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")))))
+            (add-after 'replace-paths 'pre-install-source
+              (lambda* (#:key outputs #:allow-other-keys)
+                (copy-recursively "lib" (string-append (assoc-ref outputs "src")
+                                                       "/source/lib"))))
+            ;; Temporarily patch the compiler to place correct source locations
+            ;; into module info instead of build directory.
+            (add-after 'pre-install-source 'patch-elixir-compiler
+              (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 '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 "." ".*"))))
+            ;; Unpatch the compiler and recompile it.
+            (add-after 'build 'restore-and-recompile
+              (lambda _
+                (copy-recursively #$compiler-path-orig #$compiler-path)
+                (delete-file #$compiler-path-orig)
+                (invoke "make")))
+            (add-before 'check 'set-home
+              (lambda* (#:key inputs #:allow-other-keys)
+                ;; 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.start\\(\\)")
+                     (format #f "\
 ~~w[GUIX_ELIXIR_LIBS ERL_LIBS]
 |> Enum.map(&System.get_env/1)
 |> Enum.reject(&is_nil/1)
@@ -118,23 +143,25 @@ (define-public elixir
 |> 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.start()"
-                           (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 (list erlang rebar3 git))
-    (native-search-paths
-     (list (search-path-specification
-            (variable "GUIX_ELIXIR_LIBS")
-            (files (list (string-append "lib/elixir/" (version-major+minor version)))))))
-    (home-page "https://elixir-lang.org/")
-    (synopsis "Elixir programming language")
-    (description "Elixir is a dynamic, functional language used to build
+                             (search-input-file inputs "/bin/rebar3"))))
+                  (for-each (lambda (program)
+                              (wrap-program (string-append out "/bin/" program)
+                                '("ERL_LIBS" prefix ("${GUIX_ELIXIR_LIBS}"))))
+                            programs)))))))
+      (outputs '("out" "src"))
+      (inputs (list bash-minimal erlang rebar3 git))
+      (native-search-paths
+       (list (search-path-specification
+              (variable "GUIX_ELIXIR_LIBS")
+              (files (list (string-append "lib/elixir/" (version-major+minor
+                                                         version)))))))
+      (home-page "https://elixir-lang.org/")
+      (synopsis "Functional meta-programming aware language")
+      (description "Elixir is a dynamic, functional language used to build
 scalable and maintainable applications.  Elixir leverages the Erlang VM, known
 for running low-latency, distributed and fault-tolerant systems, while also
 being successfully used in web development and the embedded software domain.")
-    (license license:asl2.0)))
+      (license license:asl2.0))))
 
 (define-public elixir-hex
   (package
-- 
2.45.1