Subject: Re: [bug#33598] Optimizations for emacs-clang-format and emacs-clang-rename

From: Tim Gesthuizen <[email-masked]>
Date: Fri, 4 Jan 2019 23:00:52 +0100

On 19.12.2018 18:50, Pierre Neidhardt wrote:
> Hi Tim,
> 
> Yeah, that makes sense.  Please send a new patch updated with the aforementioned
> recommendations and I'll merge.
> Thanks for the good work!
> 

Hi,
I had some problems packaging the changes because I had some really
weird issues with the guile modules (please validate that the patches
compile as expected).
They implement the discussed function for generating package definitions
for packages that contain only a single elisp file from another packages
source.
If the attached patches compile, they can be merged and work as
expected. If they cause weird errors to happen Pierre tries to find some
time to investigate into this.

Tim Gesthuizen.
From beec284f12caec18995be40c7a1cb9e254f83ec7 Mon Sep 17 00:00:00 2001
From: Tim Gesthuizen <[email-masked]>
Date: Fri, 30 Nov 2018 14:49:51 +0100
Subject: [PATCH 1/5] gnu: Shrink source for emacs-clang-format.

To build emacs-clang-format only the `clang-format.el` file is needed. In
order to save disk space and make clear that this is the only file needed
modify the downloaded source to only contain `clang-format.el`.

* gnu/packages/emacs.scm (emacs-clang-format): Add source snippet.
* gnu/packages/emacs.scm (emacs-clang-format): Modify phases.
---
 gnu/packages/llvm.scm | 58 ++++++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 20 deletions(-)

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index 7eb785c36..cf7c44600 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -480,28 +480,46 @@ code analysis tools.")
     (license license:bsd-3)))
 
 (define-public emacs-clang-format
-  (package
-    (inherit clang)
-    (name "emacs-clang-format")
-    (build-system emacs-build-system)
-    (inputs
-     `(("clang" ,clang)))
-    (arguments
-     `(#:phases
-       (modify-phases %standard-phases
-         (add-after 'unpack 'configure
-           (lambda* (#:key inputs #:allow-other-keys)
-             (let ((clang (assoc-ref inputs "clang")))
-               (copy-file "tools/clang-format/clang-format.el" "clang-format.el")
-               (emacs-substitute-variables "clang-format.el"
-                 ("clang-format-executable"
-                  (string-append clang "/bin/clang-format"))))
-             #t)))))
-    (synopsis "Format code using clang-format")
-    (description "This package allows to filter code through @code{clang-format}
+  (let ((target-file "clang-format.el"))
+    (package
+      (inherit clang)
+      (name "emacs-clang-format")
+      (source (let ((orig (package-source clang)))
+                (origin
+                  (method (origin-method orig))
+                  (uri (origin-uri orig))
+                  (sha256 (origin-sha256 orig))
+                  (modules '((guix build utils)
+                             (srfi srfi-1)
+                             (ice-9 ftw)))
+                  (snippet
+                   `(begin
+                      ;; Copy target file to source root and delete all other files
+                      (copy-file (string-append "tools/clang-format/" ,target-file)
+                                 ,target-file)
+                      (map delete-file-recursively
+                           (fold delete
+                                 (scandir ".")
+                                 '("." ".." ,target-file)))
+                      #t)))))
+      (build-system emacs-build-system)
+      (inputs
+       `(("clang" ,clang)))
+      (arguments
+       `(#:phases
+         (modify-phases %standard-phases
+           (add-after 'unpack 'configure
+             (lambda* (#:key inputs #:allow-other-keys)
+               (let ((clang (assoc-ref inputs "clang")))
+                 (emacs-substitute-variables ,target-file
+                   ("clang-format-executable"
+                    (string-append clang "/bin/clang-format"))))
+               #t)))))
+      (synopsis "Format code using clang-format")
+      (description "This package allows to filter code through @code{clang-format}
 to fix its formatting.  @code{clang-format} is a tool that formats
 C/C++/Obj-C code according to a set of style options, see
-@url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}.")))
+@url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}."))))
 
 (define-public emacs-clang-rename
   (package
-- 
2.20.1

From 93a8266610510e67103d06a852b97feba3d3c4e9 Mon Sep 17 00:00:00 2001
From: Tim Gesthuizen <[email-masked]>
Date: Fri, 30 Nov 2018 15:01:10 +0100
Subject: [PATCH 2/5] gnu: Shrink source for emacs-clang-rename.

To build emacs-clang-rename only the `clang-rename.el` file is needed. In
order to save disk space and make clear that this is the only file needed
modify the downloaded source to only contain `clang-rename.el`.

* gnu/packages/emacs.scm (emacs-clang-rename): Add source snippet.
* gnu/packages/emacs.scm (emacs-clang-rename): Modify phases.
---
 gnu/packages/llvm.scm | 59 ++++++++++++++++++++++++++++---------------
 1 file changed, 39 insertions(+), 20 deletions(-)

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index cf7c44600..530d6599b 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -522,23 +522,42 @@ C/C++/Obj-C code according to a set of style options, see
 @url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}."))))
 
 (define-public emacs-clang-rename
-  (package
-    (inherit clang)
-    (name "emacs-clang-rename")
-    (build-system emacs-build-system)
-    (inputs
-     `(("clang" ,clang)))
-    (arguments
-     `(#:phases
-       (modify-phases %standard-phases
-         (add-after 'unpack 'configure
-           (lambda* (#:key inputs #:allow-other-keys)
-             (let ((clang (assoc-ref inputs "clang")))
-               (copy-file "tools/clang-rename/clang-rename.el" "clang-rename.el")
-               (emacs-substitute-variables "clang-rename.el"
-                 ("clang-rename-binary"
-                  (string-append clang "/bin/clang-rename"))))
-             #t)))))
-    (synopsis "Rename every occurrence of a symbol using clang-rename")
-    (description "This package renames every occurrence of a symbol at point
-using @code{clang-rename}.")))
+  (let ((target-file "clang-rename.el"))
+   (package
+     (inherit clang)
+     (name "emacs-clang-rename")
+     (source (let ((orig (package-source clang)))
+               (origin
+                 (method (origin-method orig))
+                 (uri (origin-uri orig))
+                 (sha256 (origin-sha256 orig))
+                 (file-name (string-append name
+                                           (package-version clang)))
+                 (modules '((guix build utils)
+                            (srfi srfi-1)
+                            (ice-9 ftw)))
+                 (snippet
+                  `(begin
+                     (copy-file (string-append "tools/clang-rename/" ,target-file)
+                                ,target-file)
+                     (map delete-file-recursively
+                          (fold delete
+                                (scandir ".")
+                                '("." ".." ,target-file)))
+                     #t)))))
+     (build-system emacs-build-system)
+     (inputs
+      `(("clang" ,clang)))
+     (arguments
+      `(#:phases
+        (modify-phases %standard-phases
+          (add-after 'unpack 'configure
+            (lambda* (#:key inputs #:allow-other-keys)
+              (let ((clang (assoc-ref inputs "clang")))
+                (emacs-substitute-variables ,target-file
+                  ("clang-rename-binary"
+                   (string-append clang "/bin/clang-rename"))))
+              #t)))))
+     (synopsis "Rename every occurrence of a symbol using clang-rename")
+     (description "This package renames every occurrence of a symbol at point
+using @code{clang-rename}."))))
-- 
2.20.1

From c253da5cbb01eb0218f559559ecf16754bb824da Mon Sep 17 00:00:00 2001
From: Tim Gesthuizen <[email-masked]>
Date: Fri, 30 Nov 2018 15:13:51 +0100
Subject: [PATCH 3/5] gnu: Add package-from-clang-elisp-file

emacs-clang-format and emacs-clang-rename both are packages that are build by
extracting a single elisp file and building it as an emacs package.
This concept is encapsulated in the package-from-clang-elisp-file
function. This reduces repeating of concepts in the two package definitions.

* gnu/packages/llvm.scm (package-from-clang-elisp-file): New function
* gnu/packages/llvm.scm (emacs-clang-format): Use new function
* gnu/packages/llvm.scm (emacs-clang-rename): Use new function
---
 gnu/packages/llvm.scm | 138 +++++++++++++++++++-----------------------
 1 file changed, 61 insertions(+), 77 deletions(-)

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index 530d6599b..05147b665 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -479,85 +479,69 @@ code analysis tools.")
      "This package provides a Python binding to LLVM for use in Numba.")
     (license license:bsd-3)))
 
+;;; Returns a package definition that packages an emacs-lisp file from the
+;;; clang source. The package has the name PKGNAME and packages the file
+;;; SRC-FILE from the clang source in its root directory with the name
+;;; TARGET-FILE where SUBST substitutions will be performed on the elisp file
+;;; and SYN and DESC as the package synopsis an description.
+(define (package-from-clang-elisp-file pkgname src-file target-file subst syn desc)
+  (package
+    (inherit clang)
+    (name pkgname)
+    (source (let ((orig (package-source clang)))
+              (origin
+                (method (origin-method orig))
+                (uri (origin-uri orig))
+                (sha256 (origin-sha256 orig))
+                (file-name (string-append pkgname "-" (package-version clang)))
+                (modules '((guix build utils)
+                           (srfi srfi-1)
+                           (ice-9 ftw)))
+                (snippet
+                 `(begin
+                    ;; Copy target file to source root and delete all other files
+                    (copy-file (string-append ,src-file)
+                               ,target-file)
+                    (map delete-file-recursively
+                         (fold delete
+                               (scandir ".")
+                               '("." ".." ,target-file)))
+                    #t)))))
+    (build-system emacs-build-system)
+    (inputs
+     `(("clang" ,clang)))
+    (arguments
+     `(#:phases
+       (modify-phases %standard-phases
+         (add-after 'unpack 'configure
+           (lambda* (#:key inputs #:allow-other-keys)
+             (let ((clang (assoc-ref inputs "clang")))
+               (emacs-substitute-variables ,target-file
+                 ,subst))
+             #t)))))
+    (synopsis syn)
+    (description desc)))
+
 (define-public emacs-clang-format
-  (let ((target-file "clang-format.el"))
-    (package
-      (inherit clang)
-      (name "emacs-clang-format")
-      (source (let ((orig (package-source clang)))
-                (origin
-                  (method (origin-method orig))
-                  (uri (origin-uri orig))
-                  (sha256 (origin-sha256 orig))
-                  (modules '((guix build utils)
-                             (srfi srfi-1)
-                             (ice-9 ftw)))
-                  (snippet
-                   `(begin
-                      ;; Copy target file to source root and delete all other files
-                      (copy-file (string-append "tools/clang-format/" ,target-file)
-                                 ,target-file)
-                      (map delete-file-recursively
-                           (fold delete
-                                 (scandir ".")
-                                 '("." ".." ,target-file)))
-                      #t)))))
-      (build-system emacs-build-system)
-      (inputs
-       `(("clang" ,clang)))
-      (arguments
-       `(#:phases
-         (modify-phases %standard-phases
-           (add-after 'unpack 'configure
-             (lambda* (#:key inputs #:allow-other-keys)
-               (let ((clang (assoc-ref inputs "clang")))
-                 (emacs-substitute-variables ,target-file
-                   ("clang-format-executable"
-                    (string-append clang "/bin/clang-format"))))
-               #t)))))
-      (synopsis "Format code using clang-format")
-      (description "This package allows to filter code through @code{clang-format}
+  (package-from-clang-elisp-file
+   "emacs-clang-format"
+   "tools/clang-format/clang-format.el"
+   "clang-format.el"
+   '("clang-format-executable"
+                    (string-append clang "/bin/clang-format"))
+   "Format code using clang-format"
+   "This package allows to filter code through @code{clang-format}
 to fix its formatting.  @code{clang-format} is a tool that formats
 C/C++/Obj-C code according to a set of style options, see
-@url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}."))))
+@url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}."))
 
 (define-public emacs-clang-rename
-  (let ((target-file "clang-rename.el"))
-   (package
-     (inherit clang)
-     (name "emacs-clang-rename")
-     (source (let ((orig (package-source clang)))
-               (origin
-                 (method (origin-method orig))
-                 (uri (origin-uri orig))
-                 (sha256 (origin-sha256 orig))
-                 (file-name (string-append name
-                                           (package-version clang)))
-                 (modules '((guix build utils)
-                            (srfi srfi-1)
-                            (ice-9 ftw)))
-                 (snippet
-                  `(begin
-                     (copy-file (string-append "tools/clang-rename/" ,target-file)
-                                ,target-file)
-                     (map delete-file-recursively
-                          (fold delete
-                                (scandir ".")
-                                '("." ".." ,target-file)))
-                     #t)))))
-     (build-system emacs-build-system)
-     (inputs
-      `(("clang" ,clang)))
-     (arguments
-      `(#:phases
-        (modify-phases %standard-phases
-          (add-after 'unpack 'configure
-            (lambda* (#:key inputs #:allow-other-keys)
-              (let ((clang (assoc-ref inputs "clang")))
-                (emacs-substitute-variables ,target-file
-                  ("clang-rename-binary"
-                   (string-append clang "/bin/clang-rename"))))
-              #t)))))
-     (synopsis "Rename every occurrence of a symbol using clang-rename")
-     (description "This package renames every occurrence of a symbol at point
-using @code{clang-rename}."))))
+  (package-from-clang-elisp-file
+   "emacs-clang-rename"
+   "tools/clang-rename/clang-rename.el"
+   "clang-rename.el"
+   '("clang-rename-binary"
+                   (string-append clang "/bin/clang-rename"))
+   "Rename every occurrence of a symbol using clang-rename"
+   "This package renames every occurrence of a symbol at point
+using @code{clang-rename}."))
-- 
2.20.1

From 51a9a6ea6615eef9ce66985bb1ad0c3ddec5c8d8 Mon Sep 17 00:00:00 2001
From: Tim Gesthuizen <[email-masked]>
Date: Fri, 4 Jan 2019 22:34:36 +0100
Subject: [PATCH 4/5] gnu: Add package-elisp-from-package

Add a function to generate package definitions that packages single elisp
files from other packages.

* gnu/packages/emacs.scm (package-elisp-from-package): New function
---
 gnu/packages/emacs.scm | 64 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/emacs.scm b/gnu/packages/emacs.scm
index 52f4018c2..cdee59ce4 100644
--- a/gnu/packages/emacs.scm
+++ b/gnu/packages/emacs.scm
@@ -35,7 +35,7 @@
 ;;; Copyright © 2018 Sohom Bhattacharjee <[email-masked]>
 ;;; Copyright © 2018 Mathieu Lirzin <[email-masked]>
 ;;; Copyright © 2018 Pierre Neidhardt <[email-masked]>
-;;; Copyright © 2018 Tim Gesthuizen <[email-masked]>
+;;; Copyright © 2018, 2019 Tim Gesthuizen <[email-masked]>
 ;;; Copyright © 2018 Jack Hill <[email-masked]>
 ;;; Copyright © 2018 Pierre-Antoine Rouby <[email-masked]>
 ;;; Copyright © 2018 Alex Branham <[email-masked]>
@@ -333,6 +333,68 @@ editor (without an X toolkit)" )
              (lambda _
                (invoke "mkdir" "-p" "src/deps")))))))))
 
+;;; Returns a package definition that packages an emacs-lisp file from the
+;;; SRCPKG source. The package has the name PKGNAME and packages the file
+;;; SRC-FILE from the source in its root directory as TARGET-FILE or the
+;;; basename of SRC-FILE where INPUTS NATIVE-INPUTS and PROPAGATED-INPUTS are
+;;; added as package inputs and SUBSTITUTIONS substitutions will be performed
+;;; on the elisp file and SYNOPSIS and DESCRIPTION as the package synopsis and
+;;; description.
+(define* (package-elisp-from-package
+          srcpkg pkgname src-file
+          #:key (target-file #f)
+          (inputs '())
+          (native-inputs '())
+          (propagated-inputs '())
+          (substitutions '())
+          (synopsis #f)
+          (description #f))
+  (let ((real-target-file (if target-file
+                              target-file
+                              (basename src-file)))
+        (orig (package-source srcpkg)))
+    (package
+      (inherit srcpkg)
+      (name pkgname)
+      (source (origin
+                (method (origin-method orig))
+                (uri (origin-uri orig))
+                (sha256 (origin-sha256 orig))
+                (file-name (string-append pkgname "-" (package-version srcpkg)))
+                (modules '((guix build utils)
+                           (srfi srfi-1)
+                           (ice-9 ftw)))
+                (snippet
+                 `(begin
+                    ;; Copy target file to source root and delete all other files
+                    (copy-file ,src-file
+                               ,real-target-file)
+                    (map delete-file-recursively
+                         (fold delete
+                               (scandir ".")
+                               '("." ".." ,real-target-file)))
+                    #t))))
+      (build-system emacs-build-system)
+      (inputs inputs)
+      (native-inputs native-inputs)
+      (propagated-inputs propagated-inputs)
+      (arguments
+       `(#:phases
+         (modify-phases %standard-phases
+           (add-after 'unpack 'configure
+             (lambda* (#:key inputs #:allow-other-keys)
+               (emacs-substitute-variables ,real-target-file
+                 ,substitutions)
+               #t)))))
+      (synopsis (if synopsis
+                    synopsis
+                    (package-synopsis srcpkg)))
+      (description (if description
+                       description
+                       (package-description srcpkg))))))
+
+(export package-elisp-from-package)
+
 
 ;;;
 ;;; Emacs hacking.
-- 
2.20.1

From fda77fbd33933065a3d18f4db60fbf53f5908970 Mon Sep 17 00:00:00 2001
From: Tim Gesthuizen <[email-masked]>
Date: Fri, 4 Jan 2019 22:34:56 +0100
Subject: [PATCH 5/5] gnu: Use package-elisp-from-package for clangs emacs lisp
 files

Use package-elisp-from-package for emacs-clang-format and emacs-clang-rename.
Also remove package-from-clang-elisp-file as it is not needed anymore.

* gnu/packages/llvm.scm (emacs-clang-format): Use package-elisp-from-package
* gnu/packages/llvm.scm (emacs-clang-rename): Use package-elisp-from-package
* gnu/packages/llvm.scm (package-from-clang-elisp-file): Remove function
---
 gnu/packages/llvm.scm | 70 ++++++++++---------------------------------
 1 file changed, 15 insertions(+), 55 deletions(-)

diff --git a/gnu/packages/llvm.scm b/gnu/packages/llvm.scm
index 05147b665..c846e2758 100644
--- a/gnu/packages/llvm.scm
+++ b/gnu/packages/llvm.scm
@@ -39,6 +39,7 @@
   #:use-module (gnu packages gcc)
   #:use-module (gnu packages bootstrap)           ;glibc-dynamic-linker
   #:use-module (gnu packages compression)
+  #:use-module (gnu packages emacs)
   #:use-module (gnu packages libffi)
   #:use-module (gnu packages perl)
   #:use-module (gnu packages python)
@@ -479,69 +480,28 @@ code analysis tools.")
      "This package provides a Python binding to LLVM for use in Numba.")
     (license license:bsd-3)))
 
-;;; Returns a package definition that packages an emacs-lisp file from the
-;;; clang source. The package has the name PKGNAME and packages the file
-;;; SRC-FILE from the clang source in its root directory with the name
-;;; TARGET-FILE where SUBST substitutions will be performed on the elisp file
-;;; and SYN and DESC as the package synopsis an description.
-(define (package-from-clang-elisp-file pkgname src-file target-file subst syn desc)
-  (package
-    (inherit clang)
-    (name pkgname)
-    (source (let ((orig (package-source clang)))
-              (origin
-                (method (origin-method orig))
-                (uri (origin-uri orig))
-                (sha256 (origin-sha256 orig))
-                (file-name (string-append pkgname "-" (package-version clang)))
-                (modules '((guix build utils)
-                           (srfi srfi-1)
-                           (ice-9 ftw)))
-                (snippet
-                 `(begin
-                    ;; Copy target file to source root and delete all other files
-                    (copy-file (string-append ,src-file)
-                               ,target-file)
-                    (map delete-file-recursively
-                         (fold delete
-                               (scandir ".")
-                               '("." ".." ,target-file)))
-                    #t)))))
-    (build-system emacs-build-system)
-    (inputs
-     `(("clang" ,clang)))
-    (arguments
-     `(#:phases
-       (modify-phases %standard-phases
-         (add-after 'unpack 'configure
-           (lambda* (#:key inputs #:allow-other-keys)
-             (let ((clang (assoc-ref inputs "clang")))
-               (emacs-substitute-variables ,target-file
-                 ,subst))
-             #t)))))
-    (synopsis syn)
-    (description desc)))
-
 (define-public emacs-clang-format
-  (package-from-clang-elisp-file
+  (package-elisp-from-package
+   clang
    "emacs-clang-format"
    "tools/clang-format/clang-format.el"
-   "clang-format.el"
-   '("clang-format-executable"
-                    (string-append clang "/bin/clang-format"))
-   "Format code using clang-format"
-   "This package allows to filter code through @code{clang-format}
+   #:inputs `(("clang" ,clang))
+   #:substitutions '("clang-format-executable"
+                     (string-append (assoc-ref inputs "clang") "/bin/clang-format"))
+   #:synopsis "Format code using clang-format"
+   #:description "This package allows to filter code through @code{clang-format}
 to fix its formatting.  @code{clang-format} is a tool that formats
 C/C++/Obj-C code according to a set of style options, see
 @url{http://clang.llvm.org/docs/ClangFormatStyleOptions.html}."))
 
 (define-public emacs-clang-rename
-  (package-from-clang-elisp-file
+  (package-elisp-from-package
+   clang
    "emacs-clang-rename"
    "tools/clang-rename/clang-rename.el"
-   "clang-rename.el"
-   '("clang-rename-binary"
-                   (string-append clang "/bin/clang-rename"))
-   "Rename every occurrence of a symbol using clang-rename"
-   "This package renames every occurrence of a symbol at point
+   #:inputs `(("clang" ,clang))
+   #:substitutions '("clang-rename-binary"
+                     (string-append (assoc-ref inputs "clang") "/bin/clang-rename"))
+   #:synopsis "Rename every occurrence of a symbol using clang-rename"
+   #:description "This package renames every occurrence of a symbol at point
 using @code{clang-rename}."))
-- 
2.20.1