Package: guix-patches;
Reported by: Fulbert <fulbert <at> bluewin.ch>
Date: Wed, 12 Oct 2022 06:37:01 UTC
Severity: normal
Tags: moreinfo, patch
View this message in rfc822 format
From: Simon Tournier <zimon.toutoune <at> gmail.com> To: Fulbert <fulbert <at> bluewin.ch>, 58463 <at> debbugs.gnu.org Cc: 45mg <45mg.writes <at> gmail.com>, Nicolas Graves <ngraves <at> ngraves.fr> Subject: [bug#58463] [PATCH] * doc: guix-cookbook: Add a "Guix API usage examples" Date: Fri, 21 Feb 2025 18:31:01 +0100
Hi, Well this patch documents GUIX_EXTENSIONS_PATH. It had fallen into the cracks, my bad! Somehow, I had been unhappy with the implementation of GUIX_EXTENSIONS_PATH. I think this patch should be included in the Cookbook. I remember a revamp of this patch but I’m not able to find it back. Cough Cough… WDYT? Does this patch would help about introducing more Guix extensions instead of adding subcommands. I think that a Guix extension is the perfect way in order to test new ideas and CLI before introducing upstream and thus claim strong backward compatibility and clear API design. https://fulbert.neocities.org/guix/10-years-of-guix/simon-tournier-guix-repl/guix-cookbook/API-usage-examples#API-usage-examples On Wed, 12 Oct 2022 at 08:39, Fulbert <fulbert <at> bluewin.ch> wrote: > From c1af5a6ea0e56d0764969e118f0c55942db90e7b Mon Sep 17 00:00:00 2001 > From: Fulbert <fulbert <at> bluewin.ch> > Date: Wed, 12 Oct 2022 07:57:47 +0200 > Subject: [PATCH] * doc: guix-cookbook: Add a "Guix API usage examples" > chapter. > > * doc/guix-cookbook.texi ("Guix API usage examples"): New chapter. > Transcript of examples given in "Guix REPL - to infinity and beyond" > by Simon Tournier at the "10 years of Guix" event. > --- > doc/guix-cookbook.texi | 426 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 426 insertions(+) > > diff --git a/doc/guix-cookbook.texi b/doc/guix-cookbook.texi > index b61adc06da..8c6954b049 100644 > --- a/doc/guix-cookbook.texi > +++ b/doc/guix-cookbook.texi > @@ -73,6 +73,7 @@ Weblate} (@pxref{Translating Guix,,, guix, GNU Guix reference manual}). > * System Configuration:: Customizing the GNU System > * Advanced package management:: Power to the users! > * Environment management:: Control environment > +* API usage examples:: Using the API via REPL, scripts and extensions. > > * Acknowledgments:: Thanks! > * GNU Free Documentation License:: The license of this document. > @@ -94,6 +95,11 @@ System Configuration > * Auto-Login to a Specific TTY:: Automatically Login a User to a Specific TTY > * Customizing the Kernel:: Creating and using a custom Linux kernel on Guix System. > > +API usage examples > + > +* API usage examples:: Using Guix through its API via REPL, script and extensions. > + Transcript of Simon Tournier presentation : Guix REPL - to infinity and beyond > + > @end detailmenu > @end menu > > @@ -2977,6 +2983,426 @@ will have predefined environment variables and procedures. > > Run @command{direnv allow} to setup the environment for the first time. > > +@c ********************************************************************* > +@node API usage examples > +@chapter API usage examples > + > +This chapter is a transcript of the examples given by Simon Tournier in > +his presentation > +@uref{https://10years.guix.gnu.org/video/guix-repl-to-infinity-and-beyond/,Guix > +REPL - to infinity and beyond} (16 minutes video) at the > +@uref{https://10years.guix.gnu.org/,10 years of Guix} event. > + > +Interactions with Guix as a library through its API via REPL, script > +and ``guix extension'' (API subject to changes, > +script/extension might break at any update <at> dots{}). > + > +Throuthout this chapter : > + > +@itemize > +@item > +shell prompt shortened to : @code{'$ '} > +@item > +guix REPL prompt shortened to : @code{'> '} > +@end itemize > + > +@menu > +* Guix REPL:: > +* Guix script:: > +* Guix extension:: > +@end menu > + > +@node Guix REPL > +@section Guix REPL > +@anchor{#guix-repl} > + > +@menu > +* 101:: > +* select count packages on criteria:: > +* table count/group on criteria:: > +@end menu > + > +@node 101 > +@subsection 101 > +@anchor{#101} > +@quotation Note > +the REPL command @code{,use (module path name)} (shortened > +@code{,u}) can be used as an equivalent for > +@code{(use-modules (module path name))}. @code{,use} alone will list > +currently imported modules. > +@end quotation > + > +Simple Guix REPL session > +@example sh > +$ guix repl > +GNU Guile 3.0.8 > +;; [skipped licence preamble] > +> (use-modules (gnu packages base)) > +> findutils > +$1 = #<package findutils@@4.8.0 gnu/packages/base.scm:294 7fc88588ddc0> > +> ,use(guix) > +> (package-name findutils) > +$2 = "findutils" > +> (package-version findutils) > +$3 = "4.8.0" > +> (package? findutils) > +$4 = #t > +@end example > + > +@quotation Note > +the REPL command @code{,describe} (can be shortened @code{,d}) : > +Usage: describe OBJ@* > +Show description/documentation. (#f if unavailable) > +@example sh > +> ,d package->derivation > +Return the <derivation> object of PACKAGE for SYSTEM. > +> ,describe package-name > +#f > +@end example > +@end quotation > + > +@quotation Note > +when a module is imported, its exported objects are listed in > +TAB-@dots{} completions. > + > +@example sh > +> package-in<TAB> > +package-input-error? package-input-rewriting/spec > +package-input-rewriting package-inputs > +@end example > +@end quotation > + > +@node select count packages on criteria > +@subsection select count packages on criteria > +@anchor{#select-count-packages-on-criteria} > +(→ 4 min 20 s into Simon Tournier presentation) > + > +In the following REPL session > + > +@itemize > +@item > +count of haskell packages and ; > + > +@item > +count of haskell pacakges using the @code{#:cabal-revision} argument > +@emph{(present in the package ghc-crypthohash-sha1, as shown below, for > +instance)} > + > +@lisp > +(define-public ghc-cryptohash-sha1 > + (package > + ;; skipped for clarity > + (build-system haskell-build-system) > + (arguments > + `(#:cabal-revision > + ("6" "10rpxrmqgwihmplczglwxf5q3l13z9j3kvi065z884y4dymmnkgc") > + ;; … > +@end lisp > + > +@end itemize > + > +REPL session : > + > +@example sh > +$ guix repl > +GNU Guile 3.0.8 > +;; [skipped licence preamble] > +> (use-modules > + (guix) > + (guix build-system haskell) > + (gnu) > + (ice-9 match)) > +> > +> (define haskell-packages > + (fold-packages > + (lambda (package result) > + (if (eq? (package-build-system package) haskell-build-system) > + (cons package result) > + result)) > + '())) > +> (define (cabal-revision? package) > + (apply (lambda* (#:key cabal-revision #:allow-other-keys) > + (match cabal-revision > + ((revision hash) #t) > + (_ #f))) > + (package-arguments package))) > +> (define cabal-revision-packages > + (filter cabal-revision? haskell-packages)) > +> (length haskell-packages) > +$1 = 721 > +> (length cabal-revision-packages) > +$2 = 108 > +@end example > + > +@node table count/group on criteria > +@subsection table count/group on criteria > +@anchor{#table-countgroup-on-criteria} > +(→ 5 min 20 s into Simon Tournier presentation) > + > +The @code{arguments-vs-import.scm} file shown below demonstrate some > +more sophisticated selection and grouping of packages, and can be passed > +to @code{guix repl} like so : > +@example sh > +$ guix repl -- arguments-vs-import.scm > +@end example > +Its interpretation will output a table similar to the one show below the > +script-file content, giving the number of packages which ``tweak'' their > +arguments to the build and the number of packages which don't, all > +grouped by build-system types. > + > +@code{arguments-vs-import.scm} file content : > + > +@lisp > +(use-modules (guix) > + (gnu) > + (ice-9 match)) > + > +(define table (make-hash-table)) > + > +(fold-packages (lambda (package result) > + (let ((bs (build-system-name > + (package-build-system package))) > + (arg (package-arguments package))) > + (match (hash-ref result bs) > + ((tot wo wi) > + (if (null? arg) > + (hash-set! result bs (list > + (1+ tot) > + (1+ wo) > + wi)) > + (hash-set! result bs (list > + (1+ tot) > + wo > + (1+ wi))))) > + (#f (if (null? arg) > + (hash-set! result bs (list 1 1 0)) > + (hash-set! result bs (list 1 0 1)))) > + (_ (format #t "Error: ~s~%" (package-name package)))) > + result)) > + table) > + > +(define fmt "~13s: ~4s = ~4s = ~4s + ~4s~%") > +(format #t fmt > + 'key 'tot 'tot 'no-arguments 'arguments) > +(hash-for-each-handle (lambda (kv) > + (match kv > + ((key . value) > + (match value > + ((tot wo wi) > + (format #t fmt > + key > + (+ wo wi) > + tot wo wi)))))) > + table) > +@end lisp > + > +call from shell and output : > + > +@example sh > +$ cd ~/tmp/10-years-of-guix > +$ guix repl -- guix-repl-and-beyond.scm > +key : tot = tot = no-arguments + arguments > +ocaml : 57 = 57 = 0 + 57 > +haskell : 721 = 721 = 504 + 217 > +clojure : 11 = 11 = 0 + 11 > +[skipping for clarity] > +meson : 442 = 442 = 89 + 353 > +texlive : 143 = 143 = 0 + 143 > +python : 2619 = 2619 = 797 + 1822 > +binary : 14 = 14 = 0 + 14 > +@end example > + > +@node Guix script > +@section Guix script > +@anchor{#guix-script} > +Simon Tournier does not say much about using guix through scripts <at> dots{} > +probably because there is not much to say and the following links should > +answer most questions. > + > +@itemize > +@item > +@uref{https://www.gnu.org/software/guile/manual/html_node/Running-Guile-Scripts.html#Running-Guile-Scripts,Running > +Guile Scripts (Guile Reference Manual)} > +@item > +@uref{https://www.gnu.org/software/guile/manual/html_node/Guile-Scripting.html#Guile-Scripting,Guile > +Scripting (Guile Reference Manual)} > +@item > +@uref{https://www.gnu.org/software/coreutils/manual/html_node/env-invocation.html#env-invocation,env > +invocation (GNU Coreutils 9.1)} > +@end itemize > + > +Nevertheless, the script ``@code{explore}'', from Ludovic Courtès, used > +in the next section to demonstrate a ``script-to-extension conversion'', > +is probably an interesting example of using the guix API. See the links > +below for more : > + > +@itemize > +@item > +@uref{https://10years.guix.gnu.org/video/explore-your-system/,Ten Years > +of Guix --- Explore your system --- Ludovic Courtès} > +@item > +@uref{https://notabug.org/civodul/guix-explorer,civodul/guix-explorer: > +Exploring Guix System. - NotABug.org: Free code hosting} > +@end itemize > + > +@node Guix extension > +@section Guix extension > +@anchor{#guix-extension} > +(→ 7 min 05 s into Simon Tournier presentation) > + > +@menu > +* minimal example:: > +* Ludovic Courtès's explore.scm program:: > +@end menu > + > +@node minimal example > +@subsection minimal example > +@anchor{#minimal-example} > +As a minimal example of a guix extension, the following file, > +@code{~/tmp/10-years-of-guix/guix/extensions/hello.scm}, is used : > + > +@lisp > +(define-module (guix extensions hello) > + #:export (guix-hello)) > + > +(define-command (guix-hello . cmd-line) > + (category plumbing) > + (synopsis "hello world") > + (display (G_ "hello folks!"))) > +@end lisp > + > +The environment variable @code{GUIX_EXTENSIONS_PATH} has to include the > +path to the scrip file. > + > +With this in place, we can see the @code{hello} extension integrated in > +the @code{guix} CLI, as the following capture shows, with the new > +command ``hello'' added to the ``plumbing'' category : > + > +@example sh > +$ export GUIX_EXTENSIONS_PATH="$HOME/tmp/10-years-of-guix/guix/extensions" > +$ guix help > +Usage: guix OPTION | COMMAND ARGS... > +Run COMMAND with ARGS, if given. > +# [skipping for clarity …] > + plumbing commands > + archive manipulate, export, and import normalized archives (nars) > + copy copy store items remotely over SSH > + git operate on Git repositories > + offload set up and operate build offloading > + processes list currently running sessions > + repl read-eval-print loop (REPL) for interactive programming > + hello hello world > + > +Report bugs to: bug-guix@@gnu.org. > +# … > +@end example > + > +@node Ludovic Courtès's explore.scm program > +@subsection Ludovic Courtès's explore.scm program > +@anchor{#ludovic-courtèss-explore.scm-program} > +The @code{explore.scm} script can then be modified as follows to have it work > +as a Guix extension rather than a script. > + > +(→ 9 min 13 s into Simon Tournier presentation) > + > +@itemize > +@item > +removing the shebang call to guile > + > +@example > +@verbatim > +-#!/bin/sh > +-exec "${GUILE:-guile}" -e "(@ (explore) guix-explore)" -s "$0" "$@" > +-!# > +@end verbatim > +@end example > + > +@item > +replacing the module declaration with appropriate path/name > +@example > +@verbatim > +-(define-module (explore) > ++(define-module (guix extensions explore) > +@end verbatim > +@end example > + > +@item > +adding the module guix scripts to the use-module list > +@example > +@dots{} > +@verbatim > + #:use-module (guix ui) > ++ #:use-module (guix scripts) > + #:use-module (guix store) > +@end verbatim > +@dots{} > +@end example > + > +@item > +modifying the guix-explore definition > +@example > +@verbatim > +-(define (guix-explore args) > ++(define-command (guix-explore . args) > ++ (category extension) > ++ (synopsis ``explore your service'') > +(define %user-module @dots{} > +@end verbatim > +@dots{} > +@end example > +@end itemize > + > +@quotation Note on the path to the script > + > +[It seems that] to be used as a guix extension, Guix requires a script > +to live under a > +``[/@dots{}]/guix/extensions[/@dots{}]/<module-name>.scm'' tree > +structure with the corresponding module declaration > +@code{(define-module (guix extensions [@dots{}] <module-name>) @dots{}}. > + > +This will work : > + > +@example sh > +$ pwd > +~/tmp/10-years-of-guix/guix/extensions/test > +$ head -1 hello.scm > +(define-module (guix extensions test hello) > +@end example > + > +@dots{} while this won't work : > + > +@example sh > +$ pwd > +~/tmp/10-years-of-guix/guix/test > +$ head -1 hello.scm > +(define-module (guix test hello) > +@end example > + > +@dots{} nor this : > + > +@example sh > +$ pwd > +~/tmp/10-years-of-guix/nono/ > +$ head -1 hello.scm > +(define-module (nono hello) > +@end example > +@end quotation > + > +lauching > + > +@quotation Note > +@code{explore} produces a visual and interactive representation of > +the services used in a OS declaration. The user has to provide a path to > +the OS configuration file to explore. > +@end quotation > + > +All set, explore can now be used as a Guix extension like so : > + > +@example sh > +$ export GUIX_EXTENSIONS_PATH=/path/to/guix/extensions > +$ guix explore -- /path/to/configure.scm > +@end example > + > @c ********************************************************************* > @node Acknowledgments > @chapter Acknowledgments > -- > 2.38.0 Cheers, simon
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.