summary refs log tree commit diff
path: root/guix
diff options
context:
space:
mode:
authorNicolas Goaziou <mail@nicolasgoaziou.fr>2023-05-06 07:26:01 +0200
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2023-07-18 18:10:24 +0200
commit3f22dabc2a15154bb7fc03d9abf38a40854bf854 (patch)
tree37dad83d1b614bde480a3c16894b5e529c134fb5 /guix
parent4e11cac6be68a674c16965dc74e7da54cd3168df (diff)
downloadguix-3f22dabc2a15154bb7fc03d9abf38a40854bf854.tar.gz
guix: texlive-build-system: Improvements on non-trivial packages.
* guix/build/texlive-build-system.scm (build): Ignore temporary build files
when moving runfiles around.  Remove ".drv" source files prior to compiling
files.  Remove need for #:TEX-DIRECTORY keyword.  Handle ".ins" and ".dtx"
files in different directories.
(install): Install docfiles in "doc" output when available.
* guix/build-system/texlive.scm (texlive-build): Remove #:TEX-DIRECTORY.
* doc/guix.texi (Build Systems): Remove reference to #:TEX-DIRECTORY in
TEXLIVE-BUILD-SYSTEM documentation.  Also mention it now tries to compile
".dtx" files when there is no ".ins" file.
Diffstat (limited to 'guix')
-rw-r--r--guix/build-system/texlive.scm2
-rw-r--r--guix/build/texlive-build-system.scm115
2 files changed, 100 insertions, 17 deletions
diff --git a/guix/build-system/texlive.scm b/guix/build-system/texlive.scm
index aefd573d11..55e9cfee81 100644
--- a/guix/build-system/texlive.scm
+++ b/guix/build-system/texlive.scm
@@ -130,7 +130,6 @@ level package ID."
                         #:key
                         source
                         (tests? #f)
-                        tex-directory
                         (build-targets #f)
                         (tex-engine #f)
 
@@ -161,7 +160,6 @@ level package ID."
           #$(with-build-variables inputs outputs
               #~(texlive-build #:name #$name
                                #:source #+source
-                               #:tex-directory #$tex-directory
                                #:build-targets #$build-targets
                                #:tex-engine #$(if tex-engine
                                                   tex-engine
diff --git a/guix/build/texlive-build-system.scm b/guix/build/texlive-build-system.scm
index 353fb934a6..9bc0ce31c1 100644
--- a/guix/build/texlive-build-system.scm
+++ b/guix/build/texlive-build-system.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
 ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
 ;;; Copyright © 2021 Thiago Jung Bauermann <bauermann@kolabnow.com>
+;;; Copyright © 2023 Nicolas Goaziou <mail@nicolasgoaziou.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,8 +23,9 @@
   #:use-module ((guix build gnu-build-system) #:prefix gnu:)
   #:use-module (guix build utils)
   #:use-module (guix build union)
-  #:use-module (ice-9 match)
+  #:use-module (ice-9 format)
   #:use-module (ice-9 ftw)
+  #:use-module (ice-9 match)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-26)
   #:export (%standard-phases
@@ -35,33 +37,116 @@
 ;;
 ;; Code:
 
-(define (compile-with-latex engine format file)
+(define (runfiles-root-directories)
+  "Return list of root directories containing runfiles."
+  (scandir "."
+           (negate
+            (cut member <> '("." ".." "build" "doc" "source")))))
+
+(define* (delete-drv-files #:rest _)
+  "Delete pre-generated \".drv\" files in order to prevent build failures."
+  (when (file-exists? "source")
+    (for-each delete-file (find-files "source" "\\.drv$"))))
+
+(define (compile-with-latex engine format output file)
   (invoke engine
           "-interaction=nonstopmode"
-          "-output-directory=build"
+          (string-append "-output-directory=" output)
           (if format (string-append "&" format) "-ini")
           file))
 
 (define* (build #:key inputs build-targets tex-engine tex-format
                 #:allow-other-keys)
-  (mkdir "build")
-  (for-each (cut compile-with-latex tex-engine tex-format <>)
-            (if build-targets build-targets
-                (scandir "." (cut string-suffix? ".ins" <>)))))
+  (let ((targets
+         (cond
+          (build-targets
+           ;; Collect the relative file names of all the specified targets.
+           (append-map (lambda (target)
+                         (find-files "source"
+                                     (lambda (f _)
+                                       (string-suffix? (string-append "/" target)
+                                                       f))))
+                       build-targets))
+          ((directory-exists? "source")
+           ;; Prioritize ".ins" files over ".dtx" files.  There's no
+           ;; scientific reasoning here; it just seems to work better.
+           (match (find-files "source" "\\.ins$")
+             (() (find-files "source" "\\.dtx$"))
+             (files files)))
+          (else '()))))
+    (unless (null? targets)
+      (let ((output (string-append (getcwd) "/build")))
+        (mkdir-p output)
+        (for-each (lambda (target)
+                    (with-directory-excursion (dirname target)
+                      (compile-with-latex tex-engine
+                                          tex-format
+                                          output
+                                          (basename target))))
+                  targets))
+      ;; Now move generated files from the "build" directory into the rest of
+      ;; the source tree, effectively replacing downloaded files.
+
+      ;; Documentation may have been generated, but replace only runfiles,
+      ;; i.e., files that belong neither to "doc" nor "source" trees.
+      ;;
+      ;; In TeX Live, all packages are fully pre-generated.  As a consequence,
+      ;; a generated file from the "build" top directory absent from the rest
+      ;; of the tree is deemed unnecessary and can safely be ignored.
+      (let ((runfiles (append-map (cut find-files <>)
+                                  (runfiles-root-directories))))
+        (for-each (lambda (file)
+                    (match (filter
+                            (cut string-suffix?
+                                 (string-drop file (string-length "build"))
+                                 <>)
+                            runfiles)
+                      ;; Current file is not a runfile.  Ignore it.
+                      (() #f)
+                      ;; One candidate only.  Replace it with the one just
+                      ;; generated.
+                      ((destination)
+                       (let ((target (dirname destination)))
+                         (install-file file target)
+                         (format #t "re-generated file ~s in ~s~%"
+                                 (basename file)
+                                 target)))
+                      ;; Multiple candidates!  Not much can be done.
+                      ;; Hopefully, this should never happen.
+                      (_
+                       (format (current-error-port)
+                               "warning: ambiguous localization of file ~s; \
+ignoring it~%"
+                               (basename file)))))
+                  ;; Preserve the relative file name of the generated file in
+                  ;; order to be more accurate when looking for the
+                  ;; corresponding runfile in the tree.
+                  (find-files "build"))))))
 
-(define* (install #:key outputs tex-directory #:allow-other-keys)
-  (let* ((out (assoc-ref outputs "out"))
-         (target (string-append
-                  out "/share/texmf-dist/tex/" tex-directory)))
-    (mkdir-p target)
-    (for-each delete-file (find-files "." "\\.(log|aux)$"))
-    (for-each (cut install-file <> target)
-              (find-files "build" ".*"))))
+(define* (install #:key outputs #:allow-other-keys)
+  (let ((out (assoc-ref outputs "out"))
+        (doc (assoc-ref outputs "doc")))
+    ;; Take care of documentation.
+    (when (directory-exists? "doc")
+      (unless doc
+        (format (current-error-port)
+                "warning: missing 'doc' output for package documentation~%"))
+      (let ((doc-dir (string-append (or doc out) "/share/texmf-dist/doc")))
+        (mkdir-p doc-dir)
+        (copy-recursively "doc" doc-dir)))
+    ;; Handle runfiles.
+    (let ((texmf (string-append (assoc-ref outputs "out") "/share/texmf-dist")))
+      (for-each (lambda (root)
+                  (let ((destination (string-append texmf "/" root)))
+                    (mkdir-p destination)
+                    (copy-recursively root destination)))
+                (runfiles-root-directories)))))
 
 (define %standard-phases
   (modify-phases gnu:%standard-phases
     (delete 'bootstrap)
     (delete 'configure)
+    (add-before 'build 'delete-drv-files delete-drv-files)
     (replace 'build build)
     (delete 'check)
     (replace 'install install)))