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
This commit is contained in:
		
							parent
							
								
									01361d46b8
								
							
						
					
					
						commit
						3178b1a442
					
				
					 2 changed files with 131 additions and 4 deletions
				
			
		| 
						 | 
					@ -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
 | 
					@code{#:phases}.  The @code{#:phases} keyword in particular lets you
 | 
				
			||||||
modify the set of build phases for your package (@pxref{Build Phases}).
 | 
					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
 | 
					@quotation Compatibility Note
 | 
				
			||||||
Until version 1.3.0, the @code{arguments} field would typically use
 | 
					Until version 1.3.0, the @code{arguments} field would typically use
 | 
				
			||||||
@code{quote} (@code{'}) or @code{quasiquote} (@code{`}) and no
 | 
					@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.
 | 
					applied to implicit inputs as well.
 | 
				
			||||||
@end deffn
 | 
					@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
 | 
					@node Writing Manifests
 | 
				
			||||||
@section 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
 | 
					the helpers used by this phase, and for more examples of
 | 
				
			||||||
@code{modify-phases}.
 | 
					@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 code staging
 | 
				
			||||||
@cindex staging, of code
 | 
					@cindex staging, of code
 | 
				
			||||||
Keep in mind that build phases are code evaluated at the time the
 | 
					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")
 | 
					$5 = ("." ".." "egrep" "fgrep" "grep")
 | 
				
			||||||
@end example
 | 
					@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
 | 
					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
 | 
					object and ``lowers'' it into a derivation (@pxref{Derivations}) or a
 | 
				
			||||||
store file:
 | 
					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.
 | 
					shows build events only, and higher levels print build logs.
 | 
				
			||||||
@end deffn
 | 
					@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}
 | 
					@deffn {REPL command} run-in-store @var{exp}
 | 
				
			||||||
Run @var{exp}, a monadic expression, through the store monad.
 | 
					Run @var{exp}, a monadic expression, through the store monad.
 | 
				
			||||||
@xref{The Store Monad}, for more information.
 | 
					@xref{The Store Monad}, for more information.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
;;; GNU Guix --- Functional package management for GNU
 | 
					;;; 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.
 | 
					;;; This file is part of GNU Guix.
 | 
				
			||||||
;;;
 | 
					;;;
 | 
				
			||||||
| 
						 | 
					@ -21,13 +21,15 @@
 | 
				
			||||||
  #:use-module (guix monads)
 | 
					  #:use-module (guix monads)
 | 
				
			||||||
  #:use-module (guix utils)
 | 
					  #:use-module (guix utils)
 | 
				
			||||||
  #:use-module (guix packages)
 | 
					  #:use-module (guix packages)
 | 
				
			||||||
 | 
					  #:autoload   (guix build-system) (bag)
 | 
				
			||||||
  #:use-module (guix status)
 | 
					  #: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)
 | 
					  #:use-module ((guix derivations)
 | 
				
			||||||
                #:select (derivation?
 | 
					                #:select (derivation?
 | 
				
			||||||
                          derivation->output-paths built-derivations))
 | 
					                          derivation->output-paths built-derivations))
 | 
				
			||||||
 | 
					  #:autoload   (guix read-print) (pretty-print-with-comments)
 | 
				
			||||||
  #:use-module (ice-9 match)
 | 
					  #: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 repl)
 | 
				
			||||||
  #:use-module (system repl common)
 | 
					  #:use-module (system repl common)
 | 
				
			||||||
  #:use-module (system repl command)
 | 
					  #:use-module (system repl command)
 | 
				
			||||||
| 
						 | 
					@ -138,4 +140,68 @@ Enter a REPL for values in the store monad."
 | 
				
			||||||
      (repl-option-set! new 'interp #t)
 | 
					      (repl-option-set! new 'interp #t)
 | 
				
			||||||
      (run-repl new))))
 | 
					      (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 #~'()))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue