Next: , Previous: , Up: Návod na zadávanie balíkov   [Contents][Index]


2.1.3 Zložitejší príklad

Vyššie uvedený príklad zadania balíka „Ahoj svet“ je taký jednoduchý ako sa len dá. Avšak, zadania balíkov môžu byť zložitejšie a Guix si poradí aj s omnoho náročnejšími balíkmi. Pozrime sa teda na iné, zložitejšie zadanie balíka (mierne upravené v porovnaní s pôvodným zadaním):

(define-module (gnu packages version-control)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix utils)
  #:use-module (guix packages)
  #:use-module (guix git-download)
  #:use-module (guix build-system cmake)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages python)
  #:use-module (gnu packages ssh)
  #:use-module (gnu packages tls)
  #:use-module (gnu packages web))

(define-public my-libgit2
  (let ((commit "e98d0a37c93574d2c6107bf7f31140b548c6a7bf")
        (revision "1"))
    (package
      (name "my-libgit2")
      (version (git-version "0.26.6" revision commit))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "https://github.com/libgit2/libgit2/")
                      (commit commit)))
                (file-name (git-file-name name version))
                (sha256
                 (base32
                  "17pjvprmdrx4h6bb1hhc98w9qi6ki7yl57f090n9kbhswxqfs7s3"))
                (patches (search-patches "libgit2-mtime-0.patch"))
                (modules '((guix build utils)))
                ;; Remove bundled software.
                (snippet '(delete-file-recursively "deps"))))
      (build-system cmake-build-system)
      (outputs '("out" "debug"))
      (arguments
       `(#:tests? #true                         ; Run the test suite (this is the default)
         #:configure-flags '("-DUSE_SHA1DC=ON") ; SHA-1 collision detection
         #:phases
         (modify-phases %standard-phases
           (add-after 'unpack 'fix-hardcoded-paths
             (lambda _
               (substitute* "tests/repo/init.c"
                 (("#!/bin/sh") (string-append "#!" (which "sh"))))
               (substitute* "tests/clar/fs.h"
                 (("/bin/cp") (which "cp"))
                 (("/bin/rm") (which "rm")))))
           ;; Run checks more verbosely.
           (replace 'check
             (lambda* (#:key tests? #:allow-other-keys)
               (when tests?
                 (invoke "./libgit2_clar" "-v" "-Q"))))
           (add-after 'unpack 'make-files-writable-for-tests
             (lambda _ (for-each make-file-writable (find-files ".")))))))
      (inputs
       (list libssh2 http-parser python-wrapper))
      (native-inputs
       (list pkg-config))
      (propagated-inputs
       ;; These two libraries are in 'Requires.private' in libgit2.pc.
       (list openssl zlib))
      (home-page "https://libgit2.github.com/")
      (synopsis "Library providing Git core methods")
      (description
       "Libgit2 is a portable, pure C implementation of the Git core methods
provided as a re-entrant linkable library with a solid API, allowing you to
write native speed custom Git applications in any language with bindings.")
      ;; GPLv2 with linking exception
      (license license:gpl2))))

(V prípade, že chcete zmeniť len pár polí v pôvodnom zadaní balíka by ste sa mali spoľahnúť na dedičnosť namiesto skopírovania celého zadania. Viď nižšie.)

Pozrime sa teraz na tieto polia zblízka.

2.1.3.1 spôsob git-fetch

Narozdiel od funkcie url-fetch, git-fetch vyžaduje git-reference, ktorú určuje Git repozitár a príslušná úprava. Úpravou sa rozumie akýkoľvek odkaz Git ako napríklad značka. Teda, ak je version označená, tak je možné použiť priamo číslo verzie. Niekedy majú značky verzií perdponu v. V tomto prípade môžete použiť (commit (string-append "v" version)).

Aby sme sa uistili, že sa zdrojový kód z Git repozitára uloží do priečinka s výstižným názvom, použijeme (file-name (git-file-name name version)).

Keď zadávate balík pre program s určitým číslom úpravy, môžete pre odvodenie správneho označenia verzie použiť funkciu git-version podľa pokynov v príručke prispievateľa do Guixu (see Version Numbers in GNU Guix Reference Manual).

Pýtate sa ako získať správny odtlačok sha256? Vyvolaním guix hash na miestnej kópii repozitára v požadovanej úprave, asi takto:

git clone https://github.com/libgit2/libgit2/
cd libgit2
git checkout v0.26.6
guix hash -rx .

guix hash -rx vypočíta odtlačok SHA256 celého priečinka nezahŕňajúc pod-priečinok .git (see Invoking guix hash in GNU Guix Reference Manual).

Do budúcna bude snáď guix download schopný vykonávať tieto kroky za vás, tak ako je tomu pri bežných sťahovaniach súborov.

2.1.3.2 Kusy kódu

Kusy kódu predstavujú malé časti Scheme kódu v úvodzovkách, t.j. bežne nevykonávané, ktoré sa používajú na plátanie zdrojových súborov. Je to taká Guixová náhrada za dobre známe .patch súbory. Vďaka úvodzovkám sa daný kód vykoná len vtedy, keď sa odošle démonovi Guixu na zostavenie. V praxi môžeme použiť toľko kusov kódu, koľko potrebujeme.

Kusy kódu môžu vyžadovať prídavné moduly Guilu, ktoré je možné načítať pomocou poľa modules.

2.1.3.3 Vstupy

Jestvujú tri rôzne druhy vstupov. V skratke:

native-inputs

Vyžadované pri zostavovaní ale nie pri spúšťaní. V prípade inštalácie balíka prostredníctvom náhrady sa tieto vstupy nebudú inštalovať.

vstupy

Inštalované do úložiska ale nie do profilu a prítomné pri zostavovaní.

propagated-inputs

Inštalované do úložiska aj do profilu a prítomné pri zostavovaní.

See package Reference in GNU Guix Reference Manual pre viac podrobností.

Správne rozlišovanie medzi jednotlivými druhmi vstupov je dôležité: ak je možné závislosť zaradiť ako input namiesto propagated input, tak by sa to tak malo urobiť. Inak bezdôvodne „znečistí“ používateľský profil.

Napríklad, ak inštalujete grafický program, ktorý závisí na nejakom nástroji spúšťanom v príkazovom riadku, tak vám pravdepodobne ide len o tú grafickú časť. Nie je teda potrebné siliť inštaláciu nástroja spúšťaného v príkazovom riadku do používateľského profilu. Závislosti sú spravované balíkmi a nie používateľmi. Vstupy umožňujú spravovať závislosti bez toho, aby to nejako zaťažovalo používateľov pridávaním neužitočných programov či knižníc do ich profilu.

Rovnako to platí aj pre native-inputs: po inštalácii programu môžu byť závislosti vyžadované pri zostavovaní bezpečne odstránené zberačom odpadkov. Okrem toho, ak je dostupná binárna náhrada, stiahnu sa len inputs a propagated inputs: native inputs nie sú pri inštalácii balíka prostredníctvom náhrady potrebné.

Poznámka: Tu a tam nájdete úryvky, v ktorých sú vstupy zapísané pomerne odlišne, teda asi takto:

;; „Pôvodný tvar“ zápisu vstupov
(inputs
 `(("libssh2" ,libssh2)
   ("http-parser" ,http-parser)
   ("python" ,python-wrapper)))

Toto je „pôvodný tvar“, v ktorom má každá položka zoznamu vstupov pridelenú menovku (reťazec). Tento tvar je stále podporovaný ale odporúčame vám používať už len vyššie uvedený tvar. Viď See package Reference in GNU Guix Reference Manual pre viac podrobností.

2.1.3.4 Výstupy

Tak ako môže mať balík viacero vstupov, môže mať aj viacero výstupov.

Každý výstup má osobitný priečinok v úložisku.

Používateľ si môže vybrať, ktorý výstup nainštaluje; pomáha to šetriť úložné miesto a predchádzať znečisteniu používateľského profilu nechcenými programami či knižnicami.

Oddeľovanie výstupov je voliteľné. Ak sa pole outputs vynechá, predvoleným a jediným výstupom (celý balík) bude "out".

Často vidíme oddelené výstupy s názvom debug alebo doc.

Oddelené výstupy by ste mali používať len vtedy, keď sa to oplatí: ak je výstup značne veľký (možno porovnať pomocou guix size), alebo ak je balík modulárny.

2.1.3.5 Argumenty zostavovacieho systému

Pole arguments obsahuje páry kľúč-hodnota používané pri nastavovaní postupu zostavenia.

Ten najjednoduchší argument #:tests? možno použiť na vynechanie testov po zostavení balíka. Je to užitočné najmä v prípade, keď balík neobsahuje žiadnu testovaciu súpravu. Je dôrazne odporúčané ponechať testovaciu súpravu povolenú, ak je nejaká dostupná.

Ďalším bežným argumentom je :make-flags určujúci zoznam dodatočných príznakov, ktoré sa majú použiť pri spúšťaní nástroja make ako keby ste pridali priamo do príkazového riadku. Napríklad, nasledovné príznaky

#:make-flags (list (string-append "prefix=" (assoc-ref %outputs "out"))
                   "CC=gcc")

sú chápané ako

$ make CC=gcc prefix=/gnu/store/...-<out>

Toto nastaví prekladač jazyka C na gcc a premennú prefix (cieľový priečinok inštalácie v prípade nástroja Make) na (assoc-ref %outputs "out"), čo predstavuje globálnu premennú prítomnú pri zostavovaní, ktorá udáva cestu k cieľovému priečinku v úložisku (niečo ako /gnu/store/...-my-libgit2-20180408).

Podobným spôsobom môžete nastaviť aj príznaky nastavenia:

#:configure-flags '("-DUSE_SHA1DC=ON")

Dostupná je aj premenná %build-inputs. Predstavuje tabuľku, ktorá priraďuje názvy vstupov k ich priečinkom v úložisku.

Kľúčové slovo phases predstavuje postupnosť krokov zostavovacieho systému. Medzi bežné kroky patria unpack, configure, build, install a check. Ak chcete o týchto krokoch zistiť viac, musíte nájsť to správne zadanie zostavovacieho systému v ‘$GUIX_CHECKOUT/guix/build/gnu-build-system.scm’:

(define %standard-phases
  ;; Standard build phases, as a list of symbol/procedure pairs.
  (let-syntax ((phases (syntax-rules ()
                         ((_ p ...) `((p . ,p) ...)))))
    (phases set-SOURCE-DATE-EPOCH set-paths install-locale unpack
            bootstrap
            patch-usr-bin-file
            patch-source-shebangs configure patch-generated-file-shebangs
            build check install
            patch-shebangs strip
            validate-runpath
            validate-documentation-location
            delete-info-dir-file
            patch-dot-desktop-files
            install-license-files
            reset-gzip-timestamps
            compress-documentation)))

Alebo cez REPL:

(add-to-load-path "/path/to/guix/checkout")
,use (guix build gnu-build-system)
(map first %standard-phases)
 (set-SOURCE-DATE-EPOCH set-paths install-locale unpack bootstrap patch-usr-bin-file patch-source-shebangs configure patch-generated-file-shebangs build check install patch-shebangs strip validate-runpath validate-documentation-location delete-info-dir-file patch-dot-desktop-files install-license-files reset-gzip-timestamps compress-documentation)

Ak chcete vedieť čo sa počas jednotlivých krokov odohráva, preštudujte si príslušné funkcie.

Napríklad, v čase písania týchto riadkov, bolo zadanie kroku unpack v zostavovacom systéme GNU nasledovné:

(define* (unpack #:key source #:allow-other-keys)
  "Unpack SOURCE in the working directory, and change directory within the
source.  When SOURCE is a directory, copy it in a sub-directory of the current
working directory."
  (if (file-is-directory? source)
      (begin
        (mkdir "source")
        (chdir "source")

        ;; Preserve timestamps (set to the Epoch) on the copied tree so that
        ;; things work deterministically.
        (copy-recursively source "."
                          #:keep-mtime? #true))
      (begin
        (if (string-suffix? ".zip" source)
            (invoke "unzip" source)
            (invoke "tar" "xvf" source))
        (chdir (first-subdirectory "."))))
  #true)

Všimnite si volanie chdir: zmení súčasný priečinok na umiestnenie, kde boli rozbalené zdrojové súbory. To znamená, že kroky nasledujúce po unpack použijú priečinok so zdrojovými súbormi ako ich pracovný priečinok. Preto môžeme priamo narábať so zdrojovými súbormi. Teda aspoň dovtedy, kým niektorý ďalší krok nezmení pracovný priečinok na iný.

Zoznam krokov %standard-phases zostavovacieho systému upravujeme pomocou makra modify-phases určujúceho aké úpravy sa majú vykonať, čo môže vyzerať asi takto:

Funkcia prijíma parametre inputs a outputs v tvare kľúčových slov. Každý vstup (či už pôvodný, rozšírený alebo nie) a výstupný priečinok je označený svojim názvom v týchto premenných. Takže (assoc-ref outputs "out") predstavuje priečinok úložiska hlavného výstupu balíka. Funkcia kroku vyzerá nasledovne:

(lambda* (#:key inputs outputs #:allow-other-keys)
  (let ((bash-directory (assoc-ref inputs "bash"))
        (output-directory (assoc-ref outputs "out"))
        (doc-directory (assoc-ref outputs "doc")))
    ;; ...
    #true))

Funkcia musí po úspešnom vykonaní vrátiť #true. Nie je veľmi spoľahlivé opierať sa o návratovú hodnotu posledného výrazu keďže nie je isté, že to bude práve #true. Koncové #true zaisťuje, že bude po úspešnom vykonaní vrátená správna hodnota.

2.1.3.6 Oddialené vykonanie

Ak ste boli pozorní, mohli ste si všimnúť obrátenú úvodzovku a čiarku v poli parametrov. Vskutku, zdrojový kód zostavenia v zadaní balíka by sa nemal vykonávať na strane klienta, ale až vtedy, keď sa odovzdá démonovi Guixu. Toto odovzdávanie zdrojového kódu medzi dvoma procesmi nazývame oddialené vykonanie.

2.1.3.7 Pomocné funkcie

Pri prispôsobovaní phases budete často potrebovať funkcie zodpovedajúce systémovým volaniam (make, mkdir, cp, atď.), ktoré sú zvyčajne dostupné na Unixových systémoch.

Niektoré z nich, ako napríklad chmod, sú priamo dostupné v jazyku Guile. Viď úplný zoznam v See Guile reference manual.

Guix poskytuje ďalšie pomocné funkcie, užitočné najmä v súvislosti so správou balíkov.

Niektoré z týchto funkcií sa nachádzajú v ‘$GUIX_CHECKOUT/guix/guix/build/utils.scm’. Väčšinou napodobňujú správanie pôvodných Unixových systémových príkazov:

which

Rovnaká ako systémový príkaz ‘which’.

find-files

Podobná príkazu ‘find’.

mkdir-p

Rovnaká ako príkaz ‘mkdir -p’, ktorý v prípade potreby vytvorí aj všetky nadradené priečinky.

install-file

Podobná ako príkaz ‘install’ na inštaláciu súboru do priečinka (aj nejestvujúceho). Guile má funkciu copy-file, ktorá funguje ako príkaz ‘cp’.

copy-recursively

Ako ‘cp -r’.

delete-file-recursively

Ako ‘rm -rf’.

invoke

Vyvolať spustiteľný súbor. Toto by ste mali používať namiesto system*.

with-directory-excursion

Vykoná telo funkcie v odlišnom pracovnom priečinku a následne obnoví pôvodný pracovný priečinok.

substitute*

Funkcia podobná príkazu sed.

Viď See Build Utilities in GNU Guix Reference Manual pre viac podrobností o pomocných funkciách.

2.1.3.8 Predpony modulov

Licencia v našom predošlom príklade je uvedená s predponou vzhľadom na spôsob akým bol načítaný modul licenses v tomto balíku: #:use-module ((guix licenses) #:prefix license:). Spôsob načítavania modulov v Guile (see Using Guile Modules in Guile reference manual) používateľovi dáva úplnú kontrolu nad menným priestorom. Môže sa tak predísť rozporom, povedzme, medzi premennou ‘zlib’ zo súboru ‘licenses.scm’ (názov licencie) a premennou ‘zlib’ zo súboru ‘compression.scm’ (názov balíka).


Next: Ďalšie zostavovacie systémy, Previous: Nastavenie, Up: Návod na zadávanie balíkov   [Contents][Index]