guix-devel
[Top][All Lists]
Advanced

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

How to write Guix extension?


From: zimoun
Subject: How to write Guix extension?
Date: Wed, 07 Sep 2022 13:20:24 +0200

Hi,

Extension is a mechanism which allows to have more CLI subcommands.  For
example, see guix-modules or gwl; they extend Guix by providing the
subcommands “guix module” or “guix workflow”.  Note that:

 - guix-modules uses guile-build-system and is one file.
 - gwl uses gnu-build-system and is multi-files

I would like to have multi-files but without the “complexity” of gwl
(transform .scm.in to .scm at build time, etc.).

Let take an example.  The structure is fixed and it looks like:

--8<---------------cut here---------------start------------->8---
$ tree /tmp/example/
/tmp/example/
├── guix
│   └── extensions
│       └── hello.scm
└── my
    ├── module
    │   └── sub.scm
    └── top.scm

4 directories, 3 files
--8<---------------cut here---------------end--------------->8---

Then setting GUIX_EXTENSIONS_PATH just works.

--8<---------------cut here---------------start------------->8---
$ GUIX_EXTENSIONS_PATH=/tmp/example/guix/extensions guix help
Usage: guix OPTION | COMMAND ARGS...

[...]

  plumbing commands

[...]

    hello      hello world

Report bugs to: bug-guix@gnu.org.
GNU Guix home page: <https://guix.gnu.org>
General help using Guix and GNU software: <https://guix.gnu.org/en/help/>
--8<---------------cut here---------------end--------------->8---

So far, so good!


What is my issue? :-) Well, my issue is to correctly set the load path
so that I can use the module defined under the folder my/.

For instance, this ’hello’ extension reads:

--8<---------------cut here---------------start------------->8---
$ GUIX_EXTENSIONS_PATH=/tmp/example/guix/extensions guix hello
hello
path: "/tmp/example/my"
load-path: 
  "/tmp/example/my"
  
"/gnu/store/qdhi0a69908b0521gqzxdsf9a9bniqxi-guix-module-union/share/guile/site/3.0"
  "/gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/share/guile/3.0"
  "/gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/share/guile/3.0"
  "/gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/share/guile/site/3.0"
  "/gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/share/guile/site"
  "/gnu/store/1jgcbdzx2ss6xv59w55g3kr3x4935dfb-guile-3.0.8/share/guile"
  "/home/simon/.guix-profile/share/guile/site/3.0"
  "/home/simon/.config/guix/profiles/emacs/emacs/share/guile/site/3.0"
  "/home/simon/.guix-profile/share/guile/site/3.0"
  "/home/simon/.config/guix/profiles/emacs/emacs/share/guile/site/3.0"
"top": "/tmp/example/my/top.scm"
"sub": #f
"module/sub": "/tmp/example/my/module/sub.scm"
--8<---------------cut here---------------end--------------->8---

which means that %load-path contains ’my’ module and ’%search-load-path’
finds the relevant files.  See plain script below.


However, how do I use the exported procedure in these files my/top.scm
and my/module/sub.scm?  For instance, my/top.scm reads:

--8<---------------cut here---------------start------------->8---
(define-module (my top)
  #:export (from-top))

(define (from-top)
  (let ((here (current-filename)))
    (format #t "top: ~s~%"
            (string-append (dirname here) here))))
--8<---------------cut here---------------end--------------->8---

but then I miss how to use ’from-top’ inside
’guix/extensions/hello.scm’.  Obviously ’#:use-module (my top)’ cannot
work because the load path is extended by the script itself.

I have tried

    (apply (@ (my top) from-top))
or    
    (apply (@@ (my top) from-top))

without success.  Well, I get:

    ERROR: In procedure %resolve-variable:


How can I write a multi-files extension?


Cheers,
simon

guix/extensions/hello.scm:

(define-module (guix extensions hello)
  #:use-module ((guix scripts))      ;define-command, category, synopsis, etc.

  ;;#:use-module (my module world)

  #:export (guix-hello))

(define (my-path)
  (canonicalize-path
   (string-append (dirname (current-filename)) "/../../my")))


(define-command (guix-hello . args)
  (category plumbing)
  (synopsis "hello world")

  (begin
    (format #t "hello~%")
    (format #t "path: ~s~%" (my-path))
    (add-to-load-path (my-path))
    (format #t "load-path: ~%")
    (for-each (lambda (path)
                (format #t "  ~s~%" path))
              %load-path)
    (for-each (lambda (what)
                (format #t "~s: ~s~%" what (%search-load-path what)))
              (list "top" "sub" "module/sub"))))

my/top.scm:

(define-module (my top)
  #:export (from-top))

(define (from-top)
  (let ((here (current-filename)))
    (format #t "top: ~s~%"
            (string-append (dirname here) here))))

reply via email to

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