guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

17/17: monad-repl: Add REPL commands to inspect package arguments.


From: guix-commits
Subject: 17/17: monad-repl: Add REPL commands to inspect package arguments.
Date: Mon, 4 Dec 2023 16:50:35 -0500 (EST)

civodul pushed a commit to branch master
in repository guix.

commit 3178b1a442c2f2eeeec1ff73bb852d2837b8aa3d
Author: Ludovic Courtès <ludovic.courtes@inria.fr>
AuthorDate: Mon Nov 27 18:09:23 2023 +0100

    monad-repl: Add REPL commands to inspect package arguments.
    
    * guix/monad-repl.scm (keyword-argument-value, package-argument-command):
    New procedures.
    (phases, configure-flags, make-flags): New REPL commands.
    * doc/guix.texi (package Reference): Link to “Using Guix Interactively”.
    (Defining Package Variants): Add “Tips” quotation.
    (Build Phases): Add “Tip” quotation.
    (Using Guix Interactively): Document the new REPL commands.
    
    Change-Id: I7049c1d8aa9241e07d7c921aa396e578a1b4ef16
---
 doc/guix.texi       | 61 +++++++++++++++++++++++++++++++++++++++++++
 guix/monad-repl.scm | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 131 insertions(+), 4 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index 1fd2e21608..7dde9b727b 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -7975,6 +7975,10 @@ The exact set of supported keywords depends on the build 
system
 @code{#:phases}.  The @code{#:phases} keyword in particular lets you
 modify the set of build phases for your package (@pxref{Build Phases}).
 
+The REPL has dedicated commands to interactively inspect values of some
+of these arguments, as a convenient debugging aid (@pxref{Using Guix
+Interactively}).
+
 @quotation Compatibility Note
 Until version 1.3.0, the @code{arguments} field would typically use
 @code{quote} (@code{'}) or @code{quasiquote} (@code{`}) and no
@@ -8774,6 +8778,23 @@ when @var{cut?} returns true for a given package.  When 
@var{deep?} is true, @va
 applied to implicit inputs as well.
 @end deffn
 
+@quotation Tips
+Understanding what a variant really looks like can be difficult as one
+starts combining the tools shown above.  There are several ways to
+inspect a package before attempting to build it that can prove handy:
+
+@itemize
+@item
+You can inspect the package interactively at the REPL, for instance to
+view its inputs, the code of its build phases, or its configure flags
+(@pxref{Using Guix Interactively}).
+
+@item
+When rewriting dependencies, @command{guix graph} can often help
+visualize the changes that are made (@pxref{Invoking guix graph}).
+@end itemize
+@end quotation
+
 @node Writing Manifests
 @section Writing Manifests
 
@@ -10585,6 +10606,11 @@ we have seen before.  @xref{Build Utilities}, for more 
about
 the helpers used by this phase, and for more examples of
 @code{modify-phases}.
 
+@quotation Tip
+You can inspect the code associated with a package's @code{#:phases}
+argument interactively, at the REPL (@pxref{Using Guix Interactively}).
+@end quotation
+
 @cindex code staging
 @cindex staging, of code
 Keep in mind that build phases are code evaluated at the time the
@@ -12763,6 +12789,30 @@ scheme@@(guix-user)> (scandir (string-append $3 
"/bin"))
 $5 = ("." ".." "egrep" "fgrep" "grep")
 @end example
 
+As a packager, you may be willing to inspect the build phases or flags
+of a given package; this is particularly useful when relying a lot on
+inheritance to define package variants (@pxref{Defining Package
+Variants}) or when package arguments are a result of some computation,
+both of which can make it harder to foresee what ends up in the package
+arguments.  Additional commands let you inspect those package arguments:
+
+@example
+scheme@@(guix-user)> ,phases grep
+$1 = (modify-phases %standard-phases
+       (add-after 'install 'fix-egrep-and-fgrep
+         (lambda* (#:key outputs #:allow-other-keys)
+           (let* ((out (assoc-ref outputs "out"))
+                  (bin (string-append out "/bin")))
+             (substitute* (list (string-append bin "/egrep")
+                                (string-append bin "/fgrep"))
+               (("^exec grep")
+                (string-append "exec " bin "/grep")))))))
+scheme@@(guix-user)> ,configure-flags findutils
+$2 = (list "--localstatedir=/var")
+scheme@@(guix-user)> ,make-flags binutils
+$3 = '("MAKEINFO=true")
+@end example
+
 At a lower-level, a useful command is @code{lower}: it takes a file-like
 object and ``lowers'' it into a derivation (@pxref{Derivations}) or a
 store file:
@@ -12794,6 +12844,17 @@ This is similar to the @option{--verbosity} 
command-line option
 shows build events only, and higher levels print build logs.
 @end deffn
 
+@deffn {REPL command} phases @var{package}
+@deffnx {REPL command} configure-flags @var{package}
+@deffnx {REPL command} make-flags @var{package}
+These REPL commands return the value of one element of the
+@code{arguments} field of @var{package} (@pxref{package Reference}): the
+first one show the staged code associated with @code{#:phases}
+(@pxref{Build Phases}), the second shows the code for
+@code{#:configure-flags}, and @code{,make-flags} returns the code for
+@code{#:make-flags}.
+@end deffn
+
 @deffn {REPL command} run-in-store @var{exp}
 Run @var{exp}, a monadic expression, through the store monad.
 @xref{The Store Monad}, for more information.
diff --git a/guix/monad-repl.scm b/guix/monad-repl.scm
index 8a6053edd5..d6b39112b7 100644
--- a/guix/monad-repl.scm
+++ b/guix/monad-repl.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2014, 2015, 2016, 2022 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2014-2016, 2022-2023 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -21,13 +21,15 @@
   #:use-module (guix monads)
   #:use-module (guix utils)
   #:use-module (guix packages)
+  #:autoload   (guix build-system) (bag)
   #:use-module (guix status)
-  #:autoload   (guix gexp) (lower-object)
+  #:autoload   (guix gexp) (gexp gexp? lower-gexp lowered-gexp-sexp 
lower-object)
   #:use-module ((guix derivations)
                 #:select (derivation?
                           derivation->output-paths built-derivations))
+  #:autoload   (guix read-print) (pretty-print-with-comments)
   #:use-module (ice-9 match)
-  #:use-module (ice-9 pretty-print)
+  #:autoload   (ice-9 pretty-print) (pretty-print)
   #:use-module (system repl repl)
   #:use-module (system repl common)
   #:use-module (system repl command)
@@ -138,4 +140,68 @@ Enter a REPL for values in the store monad."
       (repl-option-set! new 'interp #t)
       (run-repl new))))
 
-;;; monad-repl.scm ends here
+
+;;;
+;;; Viewing package arguments.
+;;;
+
+(define (keyword-argument-value args keyword default)
+  "Return the value associated with KEYWORD in ARGS, a keyword/value sequence,
+or DEFAULT if KEYWORD is missing from ARGS."
+  (let loop ((args args))
+    (match args
+      (()
+       default)
+      ((kw value rest ...)
+       (if (eq? kw keyword)
+           value
+           (loop rest))))))
+
+(define (package-argument-command repl form keyword default)
+  "Implement a command that display KEYWORD, a keyword such as #:phases, in
+the arguments of the package FORM evaluates to.  Return DEFAULT is KEYWORD is
+missing from those arguments."
+  (match (repl-eval repl form)
+    ((? package? package)
+     (let* ((bag* (bag
+                    (inherit (package->bag package))
+                    (build (lambda* (name inputs #:rest args)
+                             (with-monad %store-monad
+                               (return (keyword-argument-value args keyword
+                                                               default))))))))
+       (define phases
+         (parameterize ((%graft? #f))
+           (with-store store
+             (set-build-options store
+                                #:print-build-trace #t
+                                #:print-extended-build-trace? #t
+                                #:multiplexed-build-output? #t)
+             (run-with-store store
+               (mlet %store-monad ((exp (bag->derivation bag*)))
+                 (if (gexp? exp)
+                     (mlet %store-monad ((gexp (lower-gexp exp)))
+                       (return (lowered-gexp-sexp gexp)))
+                     (return exp)))))))
+
+       (run-hook before-print-hook phases)
+       (let ((column (port-column (current-output-port))))
+         (pretty-print-with-comments (current-output-port) phases
+                                     #:indent column)
+         (newline (current-output-port)))))
+    (_
+     (format #t ";; ERROR: This command only accepts package records.~%"))))
+
+(define-meta-command ((phases guix) repl (form))
+  "phases
+Return the build phases of the package defined by FORM."
+  (package-argument-command repl form #:phases #~%standard-phases))
+
+(define-meta-command ((configure-flags guix) repl (form))
+  "configure-flags
+Return the configure flags of the package defined by FORM."
+  (package-argument-command repl form #:configure-flags #~'()))
+
+(define-meta-command ((make-flags guix) repl (form))
+  "make-flags
+Return the make flags of the package defined by FORM."
+  (package-argument-command repl form #:make-flags #~'()))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]