with-imported-modules யும் பிறவும்

with-imported-modules யும் பிறவும்

Published by Arun Isaac on

In other languages: English

Tags: guix, மென்பொருள், scheme, lisp

G-கோவைகளில் எங்கும் இருக்கும் with-imported-modules என்னது? use-modules இருக்கும் போது அது எதற்குத் தேவை?

G-கோவைகளில் எங்கும் இருக்கும் with-imported-modules என்னது? use-modules இருக்கும் போது அது எதற்குத் தேவை?

இரு எளிய Hello World G-கோவை program-file உரைநிரல்களைக் கீழ் காணலாம்.

முதல் உரைநிரலில் with-imported-modules இல்லை. அதைக் கட்டமைத்து தூய சூழலில் இயக்கினால், no code for module (guix build utils) செய்தியுடன் தோல்வியடைகிறது.

;; foo.scm
(use-modules ((gnu packages base) #:select (coreutils))
             (guix gexp))

(define foo-gexp
  #~(begin
      (use-modules (guix build utils))

      (invoke #$(file-append coreutils "/bin/echo")
              "foo")))

(program-file "foo" foo-gexp)
$ env -i $(guix build -f foo.scm)
Backtrace:
           9 (primitive-load "/gnu/store/1r5mxrxqw43y75njxg89ichill6?")
In ice-9/eval.scm:
   721:20  8 (primitive-eval (begin (use-modules (guix build #)) (?)))
In ice-9/psyntax.scm:
  1229:36  7 (expand-top-sequence (#<syntax:1r5mxrxqw43y75njxg89ic?>) ?)
  1089:25  6 (parse _ (("placeholder" placeholder)) ((top) #(# # ?)) ?)
  1221:19  5 (parse _ (("placeholder" placeholder)) ((top) #(# # ?)) ?)
   259:10  4 (parse _ (("placeholder" placeholder)) (()) _ c&e (eval) ?)
In ice-9/boot-9.scm:
  3935:20  3 (process-use-modules _)
   222:17  2 (map1 (((guix build utils))))
  3936:31  1 (_ ((guix build utils)))
   3330:6  0 (resolve-interface (guix build utils) #:select _ #:hide ?)

ice-9/boot-9.scm:3330:6: In procedure resolve-interface:
no code for module (guix build utils)

இரண்டாம் உரைநிரல் with-imported-modules உடையது. அது வெற்றிகரமாக இயங்குகிறது.

;; foo.scm
(use-modules ((gnu packages base) #:select (coreutils))
             (guix gexp))

(define foo-gexp
  (with-imported-modules '((guix build utils))
    #~(begin
        (use-modules (guix build utils))

        (invoke #$(file-append coreutils "/bin/echo")
                "foo"))))

(program-file "foo" foo-gexp)
$ env -i $(guix build -f foo.scm)
foo

இவ்வேறுபாடு எதனால்? use-modules ஏன் போதவில்லை? இதை அறிய, இரண்டிலும் %load-path யைக் காணலாம். முதலில், with-imported-modules இல்லாமல்.

;; foo.scm
(use-modules (guix gexp))

(define foo-gexp
  #~(begin
      (for-each (lambda (path)
                  (display path)
                  (newline))
                %load-path)))

(program-file "foo" foo-gexp)
$ env -i $(guix build -f foo.scm)
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/3.0
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/site/3.0
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/site
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile

பின், with-imported-modules உடன்.

;; foo.scm
(use-modules (guix gexp))

(define foo-gexp
  (with-imported-modules '((guix build utils))
    #~(begin
        (for-each (lambda (path)
                    (display path)
                    (newline))
                  %load-path))))

(program-file "foo" foo-gexp)
$ env -i $(guix build -f foo.scm)
/gnu/store/jsxgc979x79h81kzqz9n6cpf5pk4z262-module-import
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/3.0
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/site/3.0
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile/site
/gnu/store/9jcmmhrmp66wa3zl4rfi9fl72v4jhhxz-guile-3.0.9/share/guile

இரண்டாம் முறை கூடுதல் இருக்கும் module-import காண்க. அதற்குள் (guix build utils) நிரல்கூறு (module) இருப்பதைக் காணலாம். with-imported-modules தேவையான நிரல்கூறுகளுடைய கிடங்குருப்படி (store item) அமைத்து நம் program-file உரைநிரல் அதை எட்ட %load-path1 மாறியை நிறுவுகிறது!

$ tree /gnu/store/jsxgc979x79h81kzqz9n6cpf5pk4z262-module-import
/gnu/store/jsxgc979x79h81kzqz9n6cpf5pk4z262-module-import
└── guix
    └── build
        └── utils.scm

3 directories, 1 file

உருவாக்கப்பட்ட கிடங்குருப்படியினுள் நோக்கினால் %load-path மாறியை நிறுவும் கூற்றைக் காணலாம்.

(set! %load-path
      (prepend
       (cons
        "/gnu/store/jsxgc979x79h81kzqz9n6cpf5pk4z262-module-import"
        (map
         (lambda (extension)
           (string-append extension "/share/guile/site/"
                          (effective-version)))
         extensions))
       %load-path))

source-module-closure

(guix build utils) guile நிரல்கூறுகளைத் தவிர வேறு எந்த நிரல்கூறுகளையும் சார்ந்திருப்பதில்லை. ஆனால், பிற நிரல்கூறுகள், எடுத்துக்காட்டுக்கு (guix search-paths), வேறு நிரல்கூறுகளைச் சார்ந்திருக்கலாம். அன்னிரல்கூறுகள் இன்னும் வேறு நிரல்கூறுகளையும் சார்ந்திருக்கலாம். இவை அத்தனையும் நாமே கையால் பட்டியலிடுவது கடுப்பு. அதற்கே source-module-closure உள்ளது! அது நமக்காக இன்னிரல்கூறுகளைக் கண்டறிவது. சிறு எடுத்துக்காட்டு கீழே.

(use-modules (guix modules)
             (guix gexp))

(define foo-gexp
  (with-imported-modules (source-module-closure '((guix search-paths)))
    #~(begin
        (use-modules (guix search-paths))

        […])))

(program-file "foo" foo-gexp)

with-extensions

Guix நிரல்கூறுகளைப் பயன்படுத்த with-imported-modules போதும். ஆனால், வேறு நிரல்தொகுதியிலிருந்து (package) நிரல்கூறுகள் தேவைப்பட்டால் என் செய்வது? Guix உடனடியே அன்னிரல்கூறுகளை வைத்திராது. நிரல்தொகுதிகளை கட்டமைக்கவோ மாற்றிடவோ (substitute) வேண்டியிருக்கலாம். தேவையான குப்பைத் திரட்டி சுட்டுகளையும் (garbage collector references) அமைக்க வேண்டியிருக்கும். இதற்குத் தான் with-extensions உள்ளது. guile-json பயன்படுத்தும் சிறு எடுத்துக்காட்டை கீழ் காண்க. இதை with-imported-modules உடன் ஆற்ற இயலாதென்பதைப் புரிய முயல்க.

(use-modules ((gnu packages guile) #:select (guile-json-4))
             (guix gexp))

(define foo-gexp
  (with-extensions (list guile-json-4)
    #~(begin
        (use-modules (json)))))

(program-file "foo" foo-gexp)

அவ்வளவு தான், இப்போது சற்று தெளிவு கிட்டியிருக்கமென நம்புகிறேன்!

Footnotes:

1

with-imported-modules %load-compiled-path மாறியையும் நிறுவுகிறது. ஆனால் சுருக்கம் கருதி, இந்த நுணுக்கத்தை இப்போது காண வேண்டாம்.