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-g...@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))))