2022-10-08 07:55:50
Note: this file was written in pandoc.markdown and it source is available here by just replacing the URL suffix from .html
to .md.txt
. The pandoc configuration used in the conversion to html is also available whith the same URL replacing .html
with .yaml.txt
.
Guix repl usage exemples from : Simon Tournier presentation, given at the 10 years of Guix event.
Interactions with Guix as a library through its API via repl, script and “(undocumented) guix extension” (API subject to changes, script/extension might break at any update… [or maybe this warning was meant specifically for the “extensions”(?) part]).
Throuthout this doc :
'$ '
'> '
Note: the repl command ,use (module path name)
(shortened ,u
) can be used as an equivalent for (use-modules (module path name))
. ,use
alone will list currently imported modules.
$ guix repl
3.0.8
GNU Guile ;; [skipped licence preamble]
> (use-modules (gnu packages base))
> findutils
= #<package findutils@4.8.0 gnu/packages/base.scm:294 7fc88588ddc0>
$1 > ,use(guix)
> (package-name findutils)
$2 = "findutils"
> (package-version findutils)
$3 = "4.8.0"
> (package? findutils)
$4 = #t
Note: the repl command ,describe
(can be shortened ,d
) :
> ,d package->derivation
Return the <derivation> object of PACKAGE for SYSTEM.> ,describe package-name
#f
Note: when a module is imported, its exported objects are listed in TAB-… completions.
> package-in<TAB>
package-input-error? package-input-rewriting/spec package-input-rewriting package-inputs
(→ 4 min 20 s into Simon Tournier presentation)
In the following repl session
count of haskell packages and ;
count of haskell pacakges using the #:cabal-revision
argument (present in the package ghc-crypthohash-sha1, as shown below, for instance)
define-public ghc-cryptohash-sha1
(
(package;; skipped content
(build-system haskell-build-system)
(arguments
`(#:cabal-revision"6" "10rpxrmqgwihmplczglwxf5q3l13z9j3kvi065z884y4dymmnkgc")
(;; …
repl session :
$ guix repl
3.0.8
GNU Guile ;; [skipped licence preamble]
> (use-modules
(guix)
(guix build-system haskell)
(gnu)
(ice-9 match))>
> (define haskell-packages
(fold-packageslambda (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#t)
((revision hash) _ #f)))
(
(package-arguments package)))> (define cabal-revision-packages
filter cabal-revision? haskell-packages))
(> (length haskell-packages)
= 721
$1 > (length cabal-revision-packages)
= 108 $2
(→ 5 min 20 s into Simon Tournier presentation)
The arguments-vs-import.scm
file shown below demonstrate some more sophisticated selection and grouping of packages, and can be passed to guix repl
like so : guix repl -- arguments-vs-import.scm
. 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.
arguments-vs-import.scm
file content :
(use-modules (guix)
(gnu)
(ice-9 match))
define table (make-hash-table))
(
lambda (package result)
(fold-packages (let ((bs (build-system-name
(
(package-build-system package)))
(arg (package-arguments package)))
(match (hash-ref result bs)
((tot wo wi)if (null? arg)
(list
(hash-set! result bs (1+ tot)
(1+ wo)
(
wi))list
(hash-set! result bs (1+ tot)
(
wo1+ wi)))))
(#f (if (null? arg)
(list 1 1 0))
(hash-set! result bs (list 1 0 1))))
(hash-set! result bs (_ (format #t "Error: ~s~%" (package-name package))))
(
result))
table)
define fmt "~13s: ~4s = ~4s = ~4s + ~4s~%")
(#t fmt
(format
'key 'tot 'tot 'no-arguments 'arguments)lambda (kv)
(hash-for-each-handle (
(match kv. value)
((key
(match value
((tot wo wi)#t fmt
(format
key+ wo wi)
(
tot wo wi)))))) table)
call from shell and output :
$ 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 some for clarity]
meson : 442 = 442 = 89 + 353
texlive : 143 = 143 = 0 + 143
python : 2619 = 2619 = 797 + 1822
binary : 14 = 14 = 0 + 14
Simon Tournier does not say much about using guix through scripts… probably because there is not much to say and the following links should answer most questions.
Nevertheless, the script “explore
”, from Ludovic Courtès, used in the next section to demonstrate a “script-to-extension conversion”, is probably an interesting exemple of using the guix API. See the links below for more :
(→ 7 min 05 s into Simon Tournier presentation)
As a minimal exemple of a guix extension, the following file, ~/tmp/10-years-of-guix/guix/extensions/hello.scm
, is used :
define-module (guix extensions hello)
(
#:export (guix-hello))
. cmd-line)
(define-command (guix-hello
(category plumbing)"hello world")
(synopsis display (G_ "hello folks!"))) (
The environment variable GUIX_EXTENSIONS_PATH
has to include the path to the scrip file.
With this in place, we can see the hello
extension integrated in the guix
CLI, as the following capture shows, with the new command “hello” added to the “plumbing” category :
$ export GUIX_EXTENSIONS_PATH="$HOME/tmp/10-years-of-guix/guix/extensions"
$ guix help
Utilisation : guix OPTION | COMMANDE ARGS...
Lance la COMMANDE avec les arguments ARGS, le cas échéant.
# [skipping 40 lines for clarity …]
commandes de plomberie
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
Signalez toute anomalie à : bug-guix@gnu.org.
# [skipping for clarity]
explore.scm
programThe explore.scm
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)
[It seems that] to be used as a guix extension, Guix requires a script to live under a “[/…]/guix/extensions[/…]/<module-name>.scm” tree structure with the corresponding module declaration (define-module (guix extensions […] <module-name>) …
.
This will work :
$ pwd
~/tmp/10-years-of-guix/guix/extensions/test
$ head -1 hello.scm
(define-module (guix extensions test hello)
… while this won’t work :
$ pwd
~/tmp/10-years-of-guix/guix/test
$ head -1 hello.scm
(define-module (guix test hello)
… nor this :
$ pwd
~/tmp/10-years-of-guix/nono/
$ head -1 hello.scm
(define-module (nono hello)
Note: 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.
All set, explore can now be used as a Guix extension like so :
$ export GUIX_EXTENSIONS_PATH=/path/to/guix/extensions
$ guix explore -- /path/to/configure.scm