\mode*        %Follow up of Beamer configuration when using ignorenonframetext.

\begin{abstract}
  Ce document s'attache à montrer quelques fonctionnalités de l'outil \href{https://guix.gnu.org}{GNU Guix}.
  Il correspond à un tutoriel court d'une durée de 1 heure, cependant les
  informations données ici peuvent prendre plus de temps.
\end{abstract}

\indent

GNU Guix est un gestionnaire de paquets transactionnel et déclaratif.  Il
implémente une discipline de gestion de paquet fonctionnelle.  Autrement dit,
le processus de construction et d’installation des paquets est vu comme une
fonction dans le sens mathématique du terme : cette fonction a des entrées
(comme des scripts de construction, un compilateur, des bibliothèques ou
dépendances) et renvoie une construction (comme un programme compilé).  En
tant que fonction pure, son résultat ne dépend que de ses entrées ; par
exemple, il ne peut pas faire référence à des logiciels ou des scripts qui
n’ont pas été explicitement passés en entrée.  Par conséquent, une fonction de
construction produit toujours le même résultat quand on lui donne le même
ensemble d’entrée.  Les constructions sont dites reproductibles.

\indent

Basé sur ces fondations, Guix est un gestionnaire d'environnements logiciels :
il peut utiliser les paquets qu’il connaît pour créer des environnements sous
différentes formes, temporaires ou «~permanentes~».  Un environnement
(collection de paquets) peut être déclaré par un manifeste pour générer un «
profil~», chaque profil ayant son propre historique permettant de revenir en
arrière ou en avant.  Un environnement temporaire peut aussi être créé à la
volée, et optionnellement isolé (conteneur Linux), ou n'autorisant lecture,
écriture ou réseau que spécifiquement.  Aussi, ces environnements peuvent être
empaquetés dans des images Docker, Singularity ou simplement des archives
repositionnables.  Pour finir, Guix permet, sur le même principe, la
génération de «~machines virtuelles~» à partir d'une déclaration pouvant
contenir un système d'exploitation.  Une fois installé, Guix ne nécessite pas
de droits spécifiques pour manipuler ses différents environnements.

\indent

Dans ce tutoriel, nous nous proposons d'illustrer quelques spécificités de
Guix.  Ce tutoriel fait echo à la présentation «~Administration système
reproductible avec GNU Guix~» par Julien Lepiller au JRES 2019
(\hrefsf{https://replay.jres.org/videos/watch/c77b3a44-b75f-4c10-9f39-8fb55ae096d7}{vidéo}
et
\hrefsf{https://conf-ng.jres.org/2019/document_revision_5343.html?download}{article}).

\begin{center}
  (Les termes en police \textsf{sans serif} sont des hyperliens.)
\end{center}

Ce tutoriel n'est qu'une introduction à l'outil Guix.  Nous avons pris le
parti d'une approche aussi didactique que possible.  Ce document se veut une
invitation et non pas un menu exhaustif.



\thisslide{why}
\begin{frame}<presentation>[label=why, fragile, plain, noframenumbering]{Pourquoi j'en suis venu à GNU Guix}
  \begin{alertblock}{\(\approx\) 2010 \textbf{Thésard}}
    Développement d'1-2 outils utilisant un gestionnaire de paquets
    \uline{classique}

    \hfill (Simulation numérique \texttt{C} et \texttt{Fortran} avec Debian / Ubuntu /
    \texttt{apt})
  \end{alertblock}

  \begin{exampleblock}{\(\approx\) 2014 \textbf{Post-doc}}
    Développement de 2-3 outils utilisant un gestionnaire de paquets sans
    droit administrateur

    \hfill (Simulation numérique \texttt{Python} et \texttt{C++} avec \texttt{conda})
  \end{exampleblock}

  \begin{block}{2016 \textbf{Ingénieur. de Recherche}}
    \begin{itemize}
    \item Administration d'un \emph{cluster} (\texttt{modulefiles})
    \item Utilisation de 10+ outils pour un même projet
    \end{itemize}

    \hfill (Analyse «~bioinformatique~»)
  \end{block}

  \begin{center}
    \textbf{Question : \alert{pourquoi cela fonctionne-t-il pour Alice et pas pour Bob ? Et vice-versa.}}
  \end{center}
\end{frame}

De cette expérience, la question qui se dégage est la continuité du
déploiement de l'environnement computationnel : comment développer sur son
ordinateur portable, faire la mise au point sur son ordinateur de bureau et
calculer massivement sur la grappe de calcul (\emph{cluster}) mutualisée sans
perdre trop de temps sur des problèmes d'administration ?

Notre motivation dans l'utilisation de Guix est d'apporter une réponse aux
questions :

\begin{itemize}
\item Comment refaire demain là-bas ce que l'on a fait hier ici ?
\item Quelle granularité sur la transparence ?
\end{itemize}


\paragraph{Pour information :}
\begin{itemize}
\item \hrefsf{https://docs.conda.io/en/latest/}{Conda} est un gestionnaire
  d'environnement issu de la communauté Python et visant particulièrement
  le contexte de logiciels scientifiques.
\item La
  \hrefsf{https://modules.readthedocs.io/en/latest/modulefile.html}%
  {commande \texttt{module}}
  est un outil largement répandu sur les grappes de calcul qui permet, en
  jouant sur les variables d'environnement, de charger des outils spécifiques.
\end{itemize}
Nous précisons plus loin pourquoi nous ne les considérons pas satisfaisants.



\begin{frame}<presentation>[plain, noframenumbering]{Ce que nous allons aborder}
  \begin{center}
    \begin{minipage}{0.7\textwidth}
      \begin{itemize}
      \item Comment refaire demain là-bas ce que l'on a fait hier ici ?
      \item Quelle granularité sur la transparence ?
      \end{itemize}
    \end{minipage}
  \end{center}

  \setcounter{tocdepth}{2}
  \tableofcontents
\end{frame}


\clearpage
\section{Introduction}

Dans cette section, nous cherchons à souligner le cadre des problèmes et des
solutions existantes, ce qui permet, nous l'espérons d'avoir une idée où se
positionne l'outil Guix.

\subsection{Pourquoi seriez-vous intéressé par Guix ?}

Comme nous allons parler de \emph{logiciels}, de \emph{paquets},
\emph{dépendances}, puis de ce que fait un \emph{gestionnaire de paquets} pour
créer des environnements computationnels, voici quelques définitions (dans des
sens très larges) qui permettent de fixer les idées.


\thisslide{start}
\begin{frame}<presentation>[label=start, fragile]{Pour fixer les idées}
  \begin{tabular}{rl}
    \rule[-0.3cm]{0cm}{0.3cm} Logiciel
    & code source ou programme \emph{binaire} associé
    \\
    \rule[-0.3cm]{0cm}{0.3cm} Paquet
    & recette pour configurer, construire, installer un logiciel
    \\
    \rule[-0.3cm]{0cm}{0.3cm} Dépendance
    & autre paquet nécessaire
    \\
    \rule[-0.6cm]{0cm}{0.6cm} Gestionnaire de paquets
    &
      \begin{minipage}{0.6\linewidth}
        automatisation du processus traitant la
        recette du paquet (et ses dépendances)
      \end{minipage}
    \\
    Environnement computationnel
    &
      \begin{minipage}{0.6\linewidth}
        pile de tous les logiciels nécessaires
        pour la configuration, construction et
        installation d'une collection de logiciels
      \end{minipage}
  \end{tabular}

  \begin{exampleblock}{}
    \begin{center}
      Comment Alice et ses collaborateurs peuvent-ils obtenir le même environnement \\
      pour \emph{calculer} avec Python et Numpy ?
    \end{center}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      Tuto avec un biais issu d’un environnement plus «~scientifique~» et moins «~ASR~»

      \textbf{\uline{mais} \red{Guix s’adapte à tous les cas d’usage}}
      \scriptsize{(ou presque)}
    \end{center}
  \end{alertblock}
\end{frame}


Les collaborateurs d'Alice sont Carole, Charlie et Bob.  Tous travaillent sur
des machines différentes avec des distributions GNU/Linux différentes.  Dan
n'a pas d'interaction avec Alice et a sous la main uniquement un document
(article de recherche ou fichier de configuration).


\thisslide{scenarii}
\begin{frame}<presentation>[label=scenarii, fragile]{Scenarii}
  \begin{itemize}
  \item Alice utilise \texttt{python@3.9} et \texttt{numpy@1.20.3}
    \vspace{-0.25cm}
    \begin{center}
      \begin{minipage}{0.75\linewidth}
        \begin{exampleblock}{}
\begin{verbatim}
$ sudo apt install python python-numpy
\end{verbatim}
        \end{exampleblock}
      \end{minipage}
    \end{center}
  \item Carole \textbf{collabore} avec Alice\ldots{}
    mais utilise \texttt{python3.8} et \texttt{numpy@1.16.5} pour un autre
    projet
    \vspace{-0.6cm}
    \begin{center}
      \begin{minipage}{0.75\linewidth}
        \begin{exampleblock}{}
\begin{verbatim}
$ apt-cache madison python-numpy
python-numpy | 1:1.16.5-2ubuntu7 | ...
\end{verbatim}
        \end{exampleblock}
      \end{minipage}
    \end{center}
  \item Charlie \textbf{mets à jour} son système et \textbf{tout est cassé}
    \vspace{-0.25cm}
    \begin{center}
      \begin{minipage}{0.75\linewidth}
        \begin{exampleblock}{}
\begin{verbatim}
$ sudo apt upgrade
The following packages have unmet dependencies:
E: Broken packages
\end{verbatim}
        \end{exampleblock}
      \end{minipage}
    \end{center}
  \item Bob utilise les \textbf{\alert{mêmes} versions} qu'Alice mais n'a
    \textbf{pas le \alert{même} résultat}
  \item Dan essaie de \textbf{rejouer plus tard} le scénario d'Alice
    mais rencontre l'\alert{enfer des dépendances}
    \begin{center}
      \begin{minipage}{0.75\linewidth}
        \href{http://repeatability.cs.arizona.edu}%
        {Repeatability in Computer Science (lien)}
      \end{minipage}
    \end{center}
  \end{itemize}
\end{frame}

\begin{itemize}
\item Qui n’a pas été dans la situation de Carole qui devait installer
  plusieurs versions d'un même logiciel ?  Et ces versions peuvent
  entrer en conflit.  En général, par défaut, une distribution Linux
  installe uniquement une seule version d'un logiciel avec toutes ses
  dépendances.  Le problème est l'endroit où résident ces logiciels, par
  défaut le dossier nommé \texttt{/usr/}, et il ne peut pas y
  avoir deux exécutables, par exemple \texttt{python3}, à deux versions
  différentes, par exemple \texttt{3.9} et \texttt{3.10}.  Il faut donc un logiciel
  externe qui s'occupe de la gestion de \uline{différentes versions} (et leurs
  dépendances).
\item Qui n'a pas été dans la situation de Charlie la veille d'un évènement
  important et plus rien ne fonctionnait ?  À ma connaissance, cette
  difficulté de \uline{mise à jour} est une difficulté des administrateurs
  systèmes de machine partagée : une fois la mise à jour faite, s'il y a
  de la casse, pas de possibilités de \uline{revenir en arrière}.
\item Qui n'a pas été dans la situation de Bob «~pourquoi cela ne fonctionne
  pas pour moi, et pourtant tout est pareil~» ?  Car peut-être que les
  versions \texttt{python} et \texttt{numpy} de Bob sont bien les mêmes que
  celles d’Alice, mais le problème est : est-ce bien le cas pour toutes les
  dépendances et toutes les dépendances de dépendances ?
\item Qui n’a pas été dans la situation de Dan en lisant un article
  scientifique ou un tutoriel ou une documentation ?  Le problème est qu’il
  est difficile de s’assurer que la liste des logiciels requis (ainsi que
  toutes les dépendances et leurs dépendances) sont à la bonne version sur
  deux systèmes différents à deux moments différents.
\end{itemize}

Pour résumer, les problèmes sont :

\begin{enumerate}
\item installer le logiciel ainsi que toutes les dépendances,
\item installer plusieurs versions d’un même logiciel,
\item capturer l’état complet du système.
\end{enumerate}



\thisslide{solutions}
\begin{frame}<presentation>[label=solutions, fragile]{Solution(s)}
  \begin{enumerate}
  \item gestionnaire de paquets : APT (Debian/Ubuntu), YUM (RedHat), etc.
  \item gestionnaire d'environnements : Modulefiles, Conda, etc.
  \item conteneur : Docker, Singularity
  \end{enumerate}

  \begin{alertblock}{}
    \begin{center}
      Guix = \#1 + \#2 + \#3
    \end{center}
  \end{alertblock}

  \begin{description}
    \item[APT, Yum] Difficile de faire coexister plusieurs versions ou
      revenir en arrière ?
    \item[Modulefiles] Comment sont-ils maintenus ? (qui les utilise sur son
      \emph{laptop} ?)
    \item[Conda] Quelle granularité sur la transparence ? (qui sait comment a
      été produit PyTorch dans \texttt{pip install torch} ?
      \href{http://hpc.guix.info/blog/2021/09/whats-in-a-package/}%
      {\scriptsize{(lien)}})
      \item[Docker] Dockerfile basé sur APT, YUM etc.
        \begin{minipage}{1.0\linewidth}
        \begin{exampleblock}{}
\begin{verbatim}
RUN apt-get update && apt-get install
\end{verbatim}
        \end{exampleblock}
        \end{minipage}
    \end{description}
\end{frame}

Rappelons brièvement les termes des solutions :
\begin{itemize}
\item un gestionnaire de paquets automatise le processus pour configurer,
  construire et installer le logiciel ainsi que toutes les dépendances,
\item un gestionnaire d'environnements autorise la coexistence de plusieurs
  versions d'un même logiciel, le plus souvent en jouant sur les variables
  d’environnement,
\item un conteneur fournit tous les binaires pour être transporté d’une
  machine à l’autre et donc fonctionne indépendamment de la configuration de
  la machine hôte.
\end{itemize}

\bigskip

La double difficulté majeure est :
\begin{itemize}
\item d’une part, un contrôle fin dans la production du binaire,
\item d’autre part, la reproductibilité, au sens «~refaire ailleurs~» (autre
  configuration, autre moment).
\end{itemize}

\medskip

Guix, en étant un gestionnaire d’environnements sous \emph{stéroïde}, tente de
répondre à cette double difficulté.



\thisslide{interet}
\begin{frame}<presentation>[label=interet]{Concrètement}
  Soit
  \begin{itemize}
  \item vous vous reconnaissez dans un scénario,
  \item vous n'êtes pas satisfait par une des solutions,
  \item vous êtes curieux d'un nouveau outil.
  \end{itemize}

  \bigskip

  Dans les 3 cas, ce tutoriel illustre :

  \begin{itemize}
  \item Comment faire en pratique avec GNU Guix.
  \item Quel est le problème à traiter ?  Et pourquoi c'est compliqué.
  \end{itemize}

  \begin{alertblock}{}
      \begin{center}
        Guix est un gestionnaire d'environnements sous \emph{stéroïde}
      \end{center}
    \end{alertblock}

    Ce tutoriel est complémentaire de la présentation de Julien Lepiller en
    2019
    (\href{https://replay.jres.org/videos/watch/c77b3a44-b75f-4c10-9f39-8fb55ae096d7}{vidéo}
    et
    \href{https://conf-ng.jres.org/2019/document_revision_5343.html?download}{article})
\end{frame}



\thisslide{steroide}
\begin{frame}<presentation>[label=steroide]{\emph{Stéroïde} signifie\dots}
  \begin{tabular}{lr}
    un \uline{\textbf{gestionnaire de paquets}}
    & (comme APT, Yum, etc.)
    \\
    \ \ transactionnel et déclaratif
    & (revenir en arrière, versions concurrentes)
    \\
    \ \ \ \ qui produit des \uline{\textbf{\emph{packs} distribuables}}
    & (conteneur Docker ou Singularity)
    \\
    \ \ \  \ \ \ qui génèrent des \textbf{\uline{\emph{machines virtuelles}} isolées}
    & (\emph{à la} Ansible ou Packer)
    \\
    \ \ \ \ \ \ \ \ sur lequel on construit une distribution Linux
    & (nous n'en parlerons pas)
    \\
    \ \ \ \ \ \ \ \ \ \ \dots et aussi une bibliothèque Scheme\dots
    & (nous n'en parlerons pas, non plus)
  \end{tabular}

  \begin{alertblock}{}
    Ce tuto court est un coup de projecteur sur :
    \begin{itemize}
    \item la gestion de paquets \emph{fonctionnelle}
    \item création de \emph{machines virtuelles}
    \end{itemize}
    \begin{center}
      \textbf{\alert{Ce que nous présentons fonctionne sur n'importe quelle
          distribution Linux}}
    \end{center}
  \end{alertblock}
  \begin{flushright}
    \small{%
      (Facile à essayer\dots)
    }
  \end{flushright}
\end{frame}

\paragraph{Convention.} Nous notons \texttt{foo@1.2} pour le logiciel
\texttt{foo} à la version \texttt{1.2}.  Usuellement, une ligne commençant par
\texttt{\$} (dollar) représente une commande \emph{shell}, ainsi que par la suite
toutes les lignes commençant par \texttt{guix}.  La commande \texttt{sudo}
signifie des droits administrateur.


\clearpage
\subsection{Installation de GNU Guix}

Il est important de noter en tout premier lieu le
\hrefsf{https://guix.gnu.org/en/manual/devel/fr/}{manuel} (traduit en français)
qui fournit le point d’entrée pour l’installation et la configuration.  La
version de référence est la \hrefsf{https://guix.gnu.org/en/manual/devel/en/}%
{version anglaise}.

\subsubsection{Installation recommandée}

Nous recommandons d’installer Guix sur une distribution Linux, voir la section
\href{https://guix.gnu.org/en/manual/devel/fr/guix.fr.html#Installation-binaire}%
{\textsf{Installation binaire}} du manuel.  En tant que \texttt{root} (avec
les droits administrateur), il faut exécuter les commandes :

\begin{verbatim}
cd /tmp
wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
chmod +x guix-install.sh
./guix-install.sh
\end{verbatim}

\paragraph{Attention.}  Nous vous recommandons de parcourir le script \emph{shell}
\texttt{guix-install.sh} et de ne pas l’exécuter aveuglément.  Ce script fait
principalement 2 choses :
\begin{enumerate}
\item télécharge, installe et configure le démon \texttt{guix-daemon},
\item crée les différents dossiers nécessaires au bon fonctionnement.
\end{enumerate}

\paragraph{Cette installation n'interfère en rien avec la distribution hôte.}
Pour «~désinstaller~» Guix, il suffit de supprimer les dossiers \texttt{/gnu},
\texttt{/var/guix}, \texttt{\$HOME/\{.cache,.config\}/guix},
\texttt{/root/.config/guix} et les mécanismes de complétion de \emph{shell}
(p. ex. \texttt{/etc/bash\_completion.d}).

\paragraph{Remarques.} Pour une utilisation plus agréable, nous recommandons
d’au\-to\-ri\-ser les substituts binaires (voir la section
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Substituts}{\textsf{Substituts}})
lors de l’installation via le script.  Nous recommandons aussi de configurer
\emph{Name Service Switch} (\texttt{nscd}) sur la distribution hôte (voir la
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Name-Service-Switch-1}{\textsf{section}}
du manuel pour une explication du pourquoi).

\medskip

Pour des constructions locales, il est aussi possible d’utiliser un mécanisme
de déchargement (\emph{offload}) sur une machine tierce.  Nous renvoyons à la
section du manuel
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#R_00e9glages-du-d_00e9chargement-du-d_00e9mon}%
{\textsf{Utiliser le dispositif de déchargement}}.

\medskip

Pour finir, nous recommandons d’installer le paquet \texttt{glibc-locales},
dans le \emph{profil} \texttt{root} ainsi que dans le \emph{profil}
utilisateurs (voir la section
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Regionalisation}%
{\textsf{Régionalisation}}).
\begin{center}
  \texttt{sudo guix install glibc-locales}

  \texttt{guix install glibc-locales}
\end{center}
et d’exporter la variable d’environnement
\begin{center}
  \texttt{export GUIX\_LOCPATH=\$HOME/.guix-profile/lib/locale}
\end{center}
 ce qui évite des messages de \emph{warning}.



\begin{frame}<presentation>[fragile]{\emph{distro externe}}
  \begin{alertblock}{}
  \begin{center}
    Guix s’installe sur \textbf{\uline{n’importe quelle distribution}} Linux récente.
  \end{center}
  \end{alertblock}
  Il faut les droits administrateur (\texttt{root}) pour l’installation.

  \begin{exampleblock}{}
\begin{verbatim}
$ cd /tmp
$ wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
$ chmod +x guix-install.sh
$ sudo ./guix-install.sh
\end{verbatim}
  \end{exampleblock}

  \begin{center}
    (Quelques réglages supplémentaires sont expliqués dans les notes
    additionnelles)
  \end{center}

  Pour commencer :
  \begin{center}
    \begin{minipage}{0.75\linewidth}
\begin{verbatim}
$ guix help
\end{verbatim}
    \end{minipage}
  \end{center}

\end{frame}

\subsubsection{Autres méthodes d'installation}

\paragraph{Guix System, Guix dans une VM.}

Il nous apparaît plus aisé de commencer par installer Guix sur une
distribution Linux et d’utiliser l’outil comme gestionnaire de paquets sous
\emph{stéroïde}.  Mais les plus téméraires d’entre vous peuvent vouloir
installer Guix comme système d’exploitation complet ou dans une machine
virtuelle.  Dans ce cas, le manuel fournit une
\hrefsf{https://guix.gnu.org/en/manual/devel/fr/guix.fr.html\#Installation-du-syst\_00e8me}%
{section} dédiée. Nous recommandons d’utiliser
l’\hrefsf{https://guix.gnu.org/en/manual/devel/fr/guix.fr.html\#Installation-graphique-guid\_00e9e}%
{installateur graphique}.

\medskip

Par ailleurs, il est à noter que Guix n’a pas un modèle stable versus
expérimental mais des révisions considérées comme \emph{release},
intensivement testées mais ne recevant pas de correctifs.  Actuellement, c’est
l’étiquette
\hrefsf{https://guix.gnu.org/en/blog/2021/gnu-guix-1.3.0-released/}{v1.3.0}
sortie au mois de mai 2021.  Il est possible de télécharger des images soit
de la version dite «~\hrefsf{https://guix.gnu.org/fr/download/}{standard}~»
(v1.3.0), soit des images générées à partir des derniers
\hrefsf{https://guix.gnu.org/fr/download/latest/}{développements}.  Chacun a ses
avantages et inconvénients :
\begin{description}
\item[avantage «~standard~» :] bien testé,
\item[inconvénient «~standard~» :] potentiel manque de substituts binaires,
\item[avantage «~derniers développements~» :] inclus les correctifs depuis le
  dernier étiquetage,
\item[inconvénient «~derniers développements~» :] potentiellement instable ;
  ça peut fonctionner parfaitement comme cela peut être cassé.
\end{description}

\paragraph{Installation via le paquet Debian.}  Nous n’avons pas intensivement
testé cette méthode d’installation, c’est pourquoi nous la ne recommanderions
pas.  Mais elle est peut-être d’intérêt pour certains d’entre vous.  La
version Debian \hrefsf{https://packages.debian.org/bullseye/guix}{Bullseye}
fournit le paquet Guix :
\begin{verbatim}
$ sudo apt install guix
\end{verbatim}

\paragraph{Installation sur une grappe de calcul.}  Les grappes de calcul
(\emph{cluster}) ont souvent des configurations très spécifiques, nous
renvoyons à cette
\hrefsf{https://hpc.guix.info/blog/2017/11/installing-guix-on-a-cluster/}{explications}
pour les points essentiels.  Sinon, nous recommandons de prendre contact avec
la communauté via p. ex. \texttt{guix-science@gnu.org}.

\subsubsection{Révision de Guix pour ce tutoriel}

Ce tutoriel devrait être pouvoir être joué quelque soit la révision.
Cependant, il est possible que les exemples fournis évoluent ; comme les
versions des paquets Python ou autres.  La commande, en tant qu’utilisateur
sans privilège particulier,

\begin{center}
  \texttt{\$ guix pull -{}-commit=eb34ff1}
\end{center}

permet de se placer dans l’exact même révision que celle utilisée lors de
l’écriture de ce document.

\paragraph{Remarques.}  Les
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Serveur-de-substituts-officiel}%
{\textsf{fermes de substituts officielles}} n’étant pas des ressources illimitées, il
est possible que les substituts ne soient plus disponibles dans quelques mois
ou années après mai 2022.  Le projet Guix s’efforce autant que possible
d’assurer la conservation des substituts binaires qu’il produit et nous
espérons que cette remarque soit caduque.

\medskip

Dans le cas d’absence de substituts binaires, cela signifie que la commande
précédente (\texttt{pull}) risque de prendre plus de temps, mais surtout que
les exemples utilisant les piles logicielles risquent de compiler depuis les
sources toutes les dépendances (binaires) manquantes de la dite pile.  D’un
côté, c’est pour cela que Guix est un outil puissant pour la reproductibilité.

\medskip

D’un autre côté, si les substituts ne sont plus disponibles, alors il sera
difficile de suivre ce tutoriel avec votre ordinateur portable et nous
conseillons donc d’utiliser un
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#R_00e9glages-du-d_00e9chargement-du-d_00e9mon}%
{\textsf{déchargement (\emph{offload})}}.  Ou de saisir l’esprit général et
d’utiliser vos propres exemples avec substituts.


\begin{frame}<presentation>[plain,fragile,noframenumbering]{}

  \vfill{}
  \begin{center}
    \textbf{Comment faire la gestion de paquets ?}
  \end{center}

  \vfill{}
  \begin{flushright}
    (Exemple : Alice sans privilège particulier)
  \end{flushright}

  \vfill{}
  \begin{minipage}{0.57\linewidth}
    \begin{alertblock}{}
      \begin{itemize}
      \item Démos avec des outils du «~\emph{monde scientifique}~»
      \item Guix représente 20k+ paquets
        \scriptsize{(constante progression)}\normalsize{}
      \item Cela serait identique pour d'autres outils\\
        \hfill{} comme Nginx, LDAP, SSH, etc.
      \end{itemize}
    \end{alertblock}
  \end{minipage}
\end{frame}


\clearpage
\section{Gestion de paquets}

À partir de cette section, nous considérons une installation fonctionnelle de
l’outil Guix sur une distribution Linux récente.  Toutes les commandes seront
exécutées dans un terminal en tant qu’utilisateur régulier (sans droit
d’administration particulier).  La révision de Guix utilisée est
\texttt{eb34ff1}.

\medskip

Nous recommandons la lecture de la section
«~\href{https://guix.gnu.org/en/manual/devel/fr/guix.fr.html\#Pour-d\_00e9marrer}{Pour
  démarrer}~» du manuel.

\subsection{Utilisation de \texttt{guix package}}

Guix est avant tout un gestionnaire de paquets, c.-à-d. que Guix automatise le
processus pour configurer, construire et installer le logiciel ainsi que
toutes les dépendances.  Les fonctionnalités de gestion de paquets sont
données par la commande \texttt{guix package}.


\begin{frame}<presentation>[fragile]{Commandes basiques}
  \begin{center}
    Exemple : outils scientifiques classiques en Python
  \end{center}

  \bigskip

  \begin{center}
    (\texttt{demo/getting-started})
  \end{center}
\end{frame}



\thisslide{cli-basic}
\begin{frame}<presentation>[label=cli-basic, fragile]{Commandes basiques : Résumé}
  \begin{exampleblock}{}
    \begin{verbatim}
guix search dynamically-typed programming language # 1.
guix show    python                                # 2.
guix install python                                # 3.
guix install python-ipython python-numpy           # 4.
guix remove  python-ipython                        # 5.
guix install python-matplotlib python-scipy        # 6.
\end{verbatim}
  \end{exampleblock}

  \begin{center}
    alias de \texttt{guix package}, p. ex. \verb+guix package --install+
  \end{center}

  \begin{alertblock}{Transactionnel}
\begin{verbatim}
guix package --install python                                    # 3.
guix package --install python-ipython python-numpy               # 4.
guix package -r python-ipython -i python-matplotlib python-scipy # 5. & 6.
\end{verbatim}
  \end{alertblock}
\end{frame}

Les commandes précédentes sont des alias de la commande \texttt{guix package}.

\begin{center}
  \begin{tabular}{clcl}
    $1.$ & \texttt{guix search}  & $\leftrightarrow$ & \texttt{guix package -{}-search=}\\
    $2.$& \texttt{guix show}    & $\leftrightarrow$ & \texttt{guix package -{}-show=}\\
    $3.$& \texttt{guix install} & $\leftrightarrow$ & \texttt{guix package -{}-install=}\\
    $4.$& \texttt{guix remove}  & $\leftrightarrow$ & \texttt{guix package -{}-remove=}\\
  \end{tabular}
\end{center}

Pour de plus amples informations sur chacune des commandes, se référer au
manuel (section
\hrefsf{https://guix.gnu.org/en/manual/devel/fr/guix.fr.html\#Invoquer-guix-package}%
{Invoquer \texttt{guix package}}).  En quelques mots :

\begin{enumerate}
\item \texttt{guix search} : Recherche dans tous les paquets disponibles les
  termes \texttt{dynamically-typed programming language} dans les noms,
  synopsis et descriptions des paquets.
\item \texttt{guix show} : Affiche les informations relatives au paquet : nom, version,
  dépendances, synopsis, description, etc.  Par convention si aucune
  version n’est donnée, il choisit la dernière.
\item \texttt{guix install} : Installe le paquet \texttt{python}, par
  convention si aucune version n’est donnée, il choisit la dernière.
\item Installe les paquets \texttt{python-ipython python-numpy}.
\item \texttt{guix remove} : Supprime l’installation du paquet \texttt{python-ipython}.
\item Installe les deux autres paquets \texttt{python-matplotlib python-scipy}.
\end{enumerate}

Il est important de noter que les opérations d'installation / suppression
sont transactionnelles.  D'une part, une action (transaction) peut comporter
plusieurs opérations.  D'autre part, cette action (transaction) transforme un
état dans un autre et ces états sont sauvegardés (voir \emph{génération} et
la {Gestion de \emph{profil}}, section \textsf{\ref{sec:profil}}) ; en
d'autres termes il est toujours possible de défaire une action (transaction).



\thisslide{pkg-man}
\begin{frame}<presentation>[label=pkg-man]{Guix, un gestionnaire de paquets comme les autres ?}
  \begin{alertblock}{}
    \begin{itemize}
    \item Interface \emph{ligne de commande} comme les autres gestionnaires de
      paquets
    \item Installation/suppression sans privilège particulier
    \item Transactionnel (= pas d'état «~\emph{cassé}~»)
    \item \emph{Substituts} binaires (téléchargement d'éléments pré-construits)
    \end{itemize}
  \end{alertblock}
  \begin{center}
    \textbf{Trois fonctionnalités puissantes :}
  \end{center}

  \begin{exampleblock}{}
    \begin{itemize}
    \item Les \emph{profils} et leur composition
    \item Gestion déclarative
    \item Environnement isolé à la volée
    \end{itemize}
  \end{exampleblock}
\end{frame}

Toutes ces commandes ressemblent très fortement à toutes celles d’autres
gestionnaires de paquets, comme \texttt{apt} (Debian/Ubuntu) ou \texttt{yum}
(RedHat).  À la différence qu'il ne faut pas de droits d'administration
particuliers pour installer des paquets.

\medskip

Nous allons maintenant illustrer trois fonctionnalités qui font de Guix le
couteau suisse des gestionnaires d'environnement.  Les \emph{profils}
permettent de garder sous contrôle l'installation d'outils (paquets)
potentiellement en conflit.  La \emph{gestion déclarative} permet de
configurer les \emph{profils} dans un style de programmation fonctionnelle.
Pour finir, nous verrons la création à la volée d'un environnement
computationnel et optionnellement isolé.

\clearpage
\subsection{Gestion de \emph{profil}}
\label{sec:profil}

Un notion essentielle dans l’utilisation de Guix est la notion de
\emph{profil} : un répertoire contenant les paquets installés.


\thisslide{profil-default}
\begin{frame}<presentation>[label=profil-default, fragile]{Le \emph{profil} par défaut}
  Les commandes d’installation précédentes finissent avec le conseil :
  \begin{exampleblock}{}
\begin{verbatim}
hint: Consider setting the necessary environment variables by running:

     GUIX_PROFILE="/home/alice/.guix-profile"
     . "$GUIX_PROFILE/etc/profile"

Alternately, see `guix package --search-paths -p "$HOME/.guix-profile"'.
\end{verbatim}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      \texttt{\$HOME/.guix-profile} est le \emph{profil} par défaut
    \end{center}
  \end{alertblock}
\end{frame}

Il n'est pas nécessaire d'entrer dans ces détails pour utiliser Guix mais ce
tutoriel nous apparaît opportun pour décortiquer.

\medskip

Le profil par défaut est \texttt{\$HOME/.guix-profile} et nous pouvons
afficher les variables d'environnements de ce profil avec la commande
\begin{verbatim}
$ guix package --search-paths -p $HOME/.guix-profile
export PATH="/home/alice/.guix-profile/bin"
export GUIX_PYTHONPATH="/home/alice/.guix-profile/lib/python3.9/site-packages"
export GI_TYPELIB_PATH="/home/alice/.guix-profile/lib/girepository-1.0"
export XDG_DATA_DIRS="/home/alice/.guix-profile/share"
\end{verbatim}
et ce profil est un lien symbolique
\begin{verbatim}
$ file $HOME/.guix-profile
/home/alice/.guix-profile: symbolic link to
                               /var/guix/profiles/per-user/alice/guix-profile
\end{verbatim}
et vers quoi pointe le lien ?
\begin{verbatim}
$ readlink -f $HOME/.guix-profile
/gnu/store/jy24qk0vdgqvysnryldqn52b3fg03z10-profile
\end{verbatim}
où \texttt{jy24qk...} ressemble à un condensat (\emph{hash}) -- il condense
toutes les entrées (dépendances) pour la construction dudit profil.  Le type
du lien pointé est un dossier
\begin{verbatim}
$ file $(readlink -f ~/.guix-profile)
/gnu/store/jy24qk0vdgqvysnryldqn52b3fg03z10-profile: directory
\end{verbatim}
et ce dossier contient
\begin{verbatim}
$ tree -L 1 $(readlink -f ~/.guix-profile)
/gnu/store/jy24qk0vdgqvysnryldqn52b3fg03z10-profile
|-- bin
|-- etc
|-- include
|-- lib
|-- manifest
`-- share
\end{verbatim}



\thisslide{profil}
\begin{frame}<presentation>[label=profil, fragile]{Mais qu'est-ce un \emph{profil} ?}
  \begin{center}
    Filesystem Hierarchy Standard (FHS) = norme de la hiérarchie des systèmes
    de fichiers

    \medskip

    (définit l'arborescence et contenu des répertoires systèmes pour les systèmes Unix)
  \end{center}

  \begin{exampleblock}{}
    \begin{Verbatim}
      usr
      |-- bin       Binaires exécutables
      |-- etc       Fichiers de configuration
      |-- include   Entêtes des bibliothèques partagées
      |-- lib       Bibliothèques partagées
      |-- share     Documentation entre autres
    \end{Verbatim}
  \end{exampleblock}

  \begin{center} % XXXX: demo ?
    \verb+ls $HOME/.guix-profile+
  \end{center}

  \begin{alertblock}{}
    \begin{center}
      Un \emph{profil} est un répertoire contenant les paquets installés
    \end{center}
  \end{alertblock}
\end{frame}

\textbf{Conclusion}
\begin{itemize}
\item Un \emph{profil} contient les variables d’environnements ajustées.
\item Un \emph{profil} est un lien symbolique.
\item Un \emph{profil} pointe vers un dossier du dépôt (\emph{store}).
\item Un \emph{profil} a la structure hiérarchique de FHS (comme \texttt{/usr/}).
\end{itemize}

Sans entrer dans les détails, le dépôt (\emph{store}) est monté à
\texttt{/gnu/store} et il est dédupliqué, c.-à-d. qu'il pourrait être vu comme
une forêt de liens symboliques (voir \textsf{Fig. \ref{fig:symlinks}}).
\begin{figure}[!htb]
  \centering
  \includegraphics[width=0.7\textwidth]{static/forest-symlinks.pdf}
  \caption{Forêt de liens symboliques \label{fig:symlinks}}
\end{figure}
L'exemple \textsf{Fig. \ref{fig:symlinks}} utilise des paquets qui sont classiques
dans le contexte bioinformatique.  Cependant, on peut se poser la question des
nombres 42 et 43.  Examinons ceci.
\begin{verbatim}
$ ls -l /var/guix/profiles/per-user/alice/guix-profile*
/var/guix/profiles/per-user/alice/guix-profile -> guix-profile-5-link
/var/guix/profiles/per-user/alice/guix-profile-0-link -> /gnu/store/0fv...-profile
/var/guix/profiles/per-user/alice/guix-profile-1-link -> /gnu/store/vsr...-profile
/var/guix/profiles/per-user/alice/guix-profile-2-link -> /gnu/store/k3c...-profile
/var/guix/profiles/per-user/alice/guix-profile-3-link -> /gnu/store/dks...-profile
/var/guix/profiles/per-user/alice/guix-profile-4-link -> /gnu/store/33d...-profile
/var/guix/profiles/per-user/alice/guix-profile-5-link -> /gnu/store/jy2...-profile
\end{verbatim}
Par conséquent, l'historique est en quelque sorte conservé et Guix donne la
possibilité de changer vers quoi les liens pointent.  Le profil lui-même est
donc immutable.



\thisslide{profil2}
\begin{frame}<presentation>[label=profil2, fragile]{Exemples de fonctionnalités des \emph{profils}}

  \begin{alertblock}{}
    \begin{itemize}
    \item Historique des paquets installés / supprimés (\verb+--list-generations+)
    \item Retour en arrière (\verb+--roll-back+ or \verb+--switch-generations+)
    \end{itemize}
  \end{alertblock}

  \begin{center}
    (\texttt{demo/generations})
  \end{center}

  \begin{alertblock}{}
    \begin{itemize}
    \item Profils indépendants
    \item Contrôle fin des variables d'environnement (\verb+--search-paths+)
    \item Composition
    \end{itemize}
  \end{alertblock}

  \begin{center}
    (\texttt{demo/multi-profiles})
  \end{center}
\end{frame}

Une première fonctionnalité est la conservation des actions (installation ou
suppression) sur un profil.  Chaque action complète va créer une
\emph{génération} (état) -- c'est en ce sens que Guix est transactionnel.  Il
est donc possible de revenir en arrière (\texttt{roll-back}) ou de basculer
vers une autre génération (\texttt{switch-generation}).  Par exemple,
\begin{verbatim}
$ guix package --list-generations
Generation 1    avril 21 2022 20:22:28
 + python            3.9.9   out     /gnu/store/sz7...-python-3.9.9

Generation 2    avril 21 2022 20:38:30
 + python-numpy      1.20.3  out     /gnu/store/s89...-python-numpy-1.20.3
 + python-ipython    7.27.0  out     /gnu/store/rj0...-python-ipython-7.27.0

Generation 3    avril 21 2022 20:41:38
 - python-ipython    7.27.0  out     /gnu/store/rj0...-python-ipython-7.27.0

Generation 4    avril 21 2022 21:05:14
 + python-scipy      1.7.3   out     /gnu/store/x3x...-python-scipy-1.7.3
 + python-matplotlib 3.5.1   out     /gnu/store/inl...-python-matplotlib-3.5.1

Generation 5    avril 21 2022 21:19:34  (current)
 + tree              2.0.2   out     /gnu/store/b9z..-tree-2.0.2
\end{verbatim}
où le symbole \texttt{+} représente un ajout de paquet, le symbole \texttt{-}
une suppression pour chaque génération et \texttt{guix package
  -{}-list-installed} fournit la liste complète des paquets de l'état courant.

\medskip

Il est possible de supprimer une (ou plusieurs) génération avec l'option
\texttt{-{}-delete-generations}.  Nous renvoyons à la section du manuel sur le
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-gc}%
{\textsf{ramasse-miette}} qui permet une gestion de ce que contient le dépôt
(\emph{store}).

\bigskip

Pour finir, autant de profils que l'on souhaite peuvent être créés.  D'une
part, chaque profil est indépendant et d'autre part, ils peuvent être
composés. En d'autres termes
\begin{verbatim}
guix install python --profile=interpreteur
guix install python-numpy --profile=bibliotheque
eval $(guix package --search-paths=prefix -p interpreteur -p bibliotheque)
\end{verbatim}
et l'environnement résultant contiendra \texttt{python} et
\texttt{python-numpy}.  D'autre part, l'ajout des variables d'environnement
(\texttt{search-paths}) est contrôlable avec la valeur de l'argument
\texttt{prefix}, \texttt{suffix} ou \texttt{exact} ; les variables
d'en\-vi\-ron\-nement peuvent être, respectivement, placées avant ou après
les valeurs actuelles, ou remplacer les valeurs actuelles.

\bigskip

Nous recommandons
\href{https://guix.gnu.org/en/cookbook/fr/guix-cookbook.fr.html#Gestion-avanc_00e9e-des-paquets}%
{\textsf{Les profils en pratique}} du livre de cuisine.


\thisslide{profil3}
\begin{frame}<presentation>[label=profil3, fragile]{\emph{Profil}, en résumé}
  Les paquets sont installés dans un \emph{profil} qui est :
  $\left. \text{\parbox{0.55\linewidth}{
        \begin{itemize}
        \item un lien symbolique,
        \item pointant vers un élément du dépôt (\emph{store}),
        \end{itemize}
      }} \only<1|article:1>{\right.}\only<2-|article:0>{\right\}} $
  \only<2-|article:0>{%
  \hfill
  \begin{minipage}{0.3\linewidth}
    \begin{alertblock}{Dépôt (\emph{store})}
      \begin{itemize}
      \item Monté à \texttt{/gnu/store}
      \item Dédupliqué
      \end{itemize}
    \end{alertblock}
  \end{minipage}
  }
  $\left. \text{\parbox{1.0\linewidth}{
  \begin{itemize}
  \item et les éléments ont une structure hiérarchique type FHS (comme \texttt{/usr/}).
  \end{itemize}
  }} \right.$

  \begin{exampleblock}{}
    \begin{center}
      On peut créer autant de profils que l’on souhaite
    \end{center}
  \end{exampleblock}

  \vfill

  \begin{alertblock}{}
    \begin{center}
      \textbf{Toutes les options de \texttt{guix package} s’appliquent à n’importe quel profil}
    \end{center}
  \end{alertblock}

  \vfill

  \begin{center}
    \texttt{guix install python python-numpy -{}-profile=outils-python}
  \end{center}

\end{frame}


\clearpage
\subsection{Gestion déclarative}

Il devient vite fastidieux de saisir à l'invite du \emph{shell} la liste des
paquets et il apparaît naturel de vouloir sauvegarder cette liste dans un
fichier.  Par exemple, il n'est pas rare de versionner cette liste.  Guix
permet ceci, et un peu plus, au travers d'une gestion déclarative.


\thisslide{declarative}
\begin{frame}<presentation>[label=declarative, fragile]{Gestion déclarative}
  \vspace{-0.3cm}
  \begin{center}
    déclaratif = fichier de configuration
  \end{center}

  \begin{exampleblock}{%
      Un fichier \texttt{some-python.scm} peut contenir cette déclaration :%
    }
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/some-python.scm}
  \end{exampleblock}

  \begin{center}
    \verb+guix package --manifest=some-python.scm+
  \end{center}
  équivalent à
  \begin{center}
    \verb+guix install python python-matplotlib python-numpy python-scipy+
  \end{center}
\end{frame}

Le fichier de configuration est usuellement appelé \texttt{manifest}.  Il
contient la liste des paquets comme saisi à l'invite du \emph{shell}.  Cette liste
est une spécification du manifeste à instancier dans le profil.


\thisslide{declarative2}
\begin{frame}<presentation>[label=declarative2, fragile]{Gestion \emph{déclarative} : remarques}
  \begin{description}
  \item[Version ?] Nous le verrons dans la suite
    \medskip
  \item[Langage ?] \emph{Domain-Specific Language} (DSL) basé sur
    \href{https://fr.wikipedia.org/wiki/Scheme}%
    {Scheme}
    \href{https://fr.wikipedia.org/wiki/Lisp}%
    {(«~langage fonctionnel Lisp~»)}%
    \medskip
    \begin{itemize}
    \item \verb+(Oui (quand (= Lisp parenthèses) (baroque)))+
      \medskip
    \item Mais \uline{\textbf{continuum}} :
      \begin{enumerate}
      \item configuration (\texttt{manifest})
      \item définition des paquets (ou services)
      \item extension
      \item le c\oe ur est écrit aussi en Scheme
      \end{enumerate}
    \end{itemize}
  \end{description}
  \begin{alertblock}{}
    \begin{center}
      Guix est \textbf{adaptable} à ses besoins
    \end{center}
  \end{alertblock}

  \vfill

  \footnotesize{%
    \href{https://fr.wikipedia.org/wiki/Programmation_déclarative}{Déclaratif}
    vs
    \href{https://fr.wikipedia.org/wiki/Programmation_impérative}{Impératif}
  } \hfill \scriptsize{%
    (%
    et non pas
    % \hfill
    Donnée inerte vs Programme%
    )
  }

  \footnotesize{%
    Programmation déclarative = programmation fonctionnelle ou descriptive (\LaTeX) ou logique (Prolog)
  }
\end{frame}

Tout d'abord, il est important de noter que \emph{déclaratif} ne signifie pas
donnée inerte, comme l'on pourrait retrouver avec un format comme
\hrefsf{https://fr.wikipedia.org/wiki/Comma-separated_values}{CSV} ou
\hrefsf{https://fr.wikipedia.org/wiki/YAML}{YAML}.  Le terme
\hrefsf{https://fr.wikipedia.org/wiki/Programmation_déclarative}{déclaratif}
(«~on décrit le \emph{quoi}, c'est-à-dire le problème~») s'oppose à
\hrefsf{https://fr.wikipedia.org/wiki/Programmation_impérative}{impératif}
(«~on décrit le \emph{comment}, c'est-à-dire la structure de contrôle
correspondant à la solution~»).

Avec le \textsf{Tableau \ref{tab:cloc}}, nous espérons illustrer ce
\emph{continuum} dans Guix.

\begin{table}[!htb]
  \centering
  \begin{tabular}{l|rrrr}
    Language     &files &blank &comment &code\\
    \hline
    Scheme       &1105  &47761 &63485   &804643\\
    ~\texttt{\textasciigrave-{}-~packages}  &538   &26787 &37972   &642152\\
    ~\texttt{\textasciigrave-{}-~guix}      &272   &9699  &13346   &75577\\
    ~\texttt{\textasciigrave-{}-~services}  &53    &3232  &2764    &26723\\
    C++          & 50 &3425 &2198 &10635\\
    make         &  4 &213  &292  &3087\\
    Bourne Shell & 29 &850  &1213 &2891
  \end{tabular}
  \caption{\texttt{cloc -{}-exclude-ext=patch -{}-exclude-dir=po .}}
  \label{tab:cloc}
\end{table}

Les paquets, les services et Guix lui-même sont écrits dans le même langage
\hrefsf{https://fr.wikipedia.org/wiki/Scheme}{Scheme} (pour être précis
\hrefsf{https://www.gnu.org/software/guile/}{GNU Guile}).  Ce langage est
dérivé du langage fonctionnel Lisp et il facilite la définition de langages
dédiés (DSL, \emph{domain-specific language}).



\thisslide{trans-declarative}
\begin{frame}<presentation>[label=trans-declarative, fragile]{Gestion déclarative : exemple de transformation
    \small{%
    (\href{https://fr.wikipedia.org/wiki/Machine_de_Rube_Goldberg}%
    {machine de \smiley{Goldberg} \tiny{(lien)}})}} % \ddot\smile
  \vspace{-0.3cm}
  \begin{exampleblock}{}
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/some-python-bis.scm}
  \end{exampleblock}
  Guix DSL, \somevariable{\emph{variables}}, \someguile{Scheme} et \somestring{chaîne de caractères}.
\end{frame}

Par exemple, nous illustrons la capacité de manipuler
\emph{programmatiquement} les paquets.  Avec le mots-clé \texttt{append}, deux
listes sont concaténées.  Le mot-clé \texttt{map} applique une fonction aux
éléments d’une liste et retourne une liste.  Le mot-clé \texttt{lambda}
définit une fonction (anonyme).

\medskip

Ainsi, il est possible de déclarer des transformations à appliquer aux
paquets.


\clearpage
\paragraph{Transformation de paquets.}
Les
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Options-de-transformation-de-paquets}%
{\textsf{transformations de paquets}} sont des options qui rendent possible la
définition de variantes de paquets -- par exemple, des paquets construit en
utilisant une
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#La-cha_00eene-d_0027outils-GCC}%
{\textsf{chaîne d’outils}} différente que celle par défaut.


\thisslide{transformation}
\begin{frame}<presentation>[label=transformation, fragile]{Transformations de paquet : survol}
    \begin{exampleblock}{}
    \begin{center}
      Comment utiliser GCC@7 pour compiler le paquet \texttt{python} ?
    \end{center}
  \end{exampleblock}

  \begin{center}
    Un paquet = recette pour configurer, construire, installer un logiciel

    \medskip

    (\texttt{./configure \&\& make \&\& make install})
  \end{center}
  La recette définit :
  \begin{itemize}
  \item un \blue{code source} et potentiellement des modifications \emph{ad-hoc} (\verb+patch+)
  \item des \magenta{outils de construction} (compilateurs, moteur de
    production etc., p. ex. \verb+gcc+, \verb+cmake+)
  \item des \violet{dépendances}
  \end{itemize}

  \begin{alertblock}{}
    \begin{center}
      Une transformation permet de les réécrire
    \end{center}
  \end{alertblock}
\end{frame}



\thisslide{cli-trans}
\begin{frame}<presentation>[label=cli-trans, fragile]{Transformations : ligne de commande}
  \begin{exampleblock}{}
    \begin{center}
      \verb+guix package --help-transformations+
    \end{center}
  \end{exampleblock}
\begin{Verbatim}[commandchars=\\\{\}]
\blue{--with-source      use SOURCE when building the corresponding package}
\blue{--with-branch      build PACKAGE from the latest commit of BRANCH}
\blue{--with-commit      build PACKAGE from COMMIT}
\blue{--with-git--url    build PACKAGE from the repository at URL}
\blue{--with-patch       add FILE to the list of patches of PACKAGE}
\blue{--with-latest      use the latest upstream release of PACKAGE}
\magenta{--with-c-toolchain build PACKAGE and its dependents with TOOLCHAIN}
\magenta{--with-debug-info  build PACKAGE and preserve its debug info}
\magenta{--without-tests    build PACKAGE without running its tests}
\violet{--with-input       replace dependency PACKAGE by REPLACEMENT}
\violet{--with-graft       graft REPLACEMENT on packages that refer to PACKAGE}
\end{Verbatim}
\end{frame}

Les transformations sont appliquées récursivement, donc elles s’appliquent
aussi aux dépendances de dépendances.  Par exemple, la ligne de commande pour
recompiler le paquet \texttt{python} et toutes ses dépendances avec le
compilateur GCC à la version 7 à la place de la version 10 (par défaut) est
\begin{verbatim}
guix install python --with-c-toolchain=python=gcc-toolchain@7
\end{verbatim}
et ceci se traduit naturellement dans un fichier de configuration
\emph{manifest}.


\thisslide{trans-manif}
\begin{frame}<presentation>[label=trans-manif, fragile]{Transformations via fichier manifeste}
  \vspace{-0.3cm}
  \begin{exampleblock}{}
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/some-python-with-gcc7.scm}
  \end{exampleblock}
\end{frame}

Ici, nous utilisons le module définissant les transformations et nous
définissions la transformation \texttt{transform} via
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#index-options_002d_003etransformation}{la
procédure \texttt{options->transformation}} ; autrement dit \texttt{transform}
est une fonction prenant en argument un paquet et retournant un nouveau paquet
dans lequel la chaîne de compilation a été remplacée.  Pour finir,
\texttt{compose} permet de composer deux fonctions et nous aurions pu écrire à
la place
\begin{center}
  \texttt{(lambda (pkg) (transform (specification->package pkg)))}
\end{center}
Le manuel fournit un
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Index-de-programmation}%
{\textsf{index de programmation}} qui aide à se familiariser avec le langage
dédié.


\clearpage
\subsection{Environnement isolé à la volée}

À ce stade, nous sommes capables de créer des profils.  Par exemple, la
commande \texttt{guix package -{}-list-profiles} liste tous les profils de
l'utilisateur.  Tant qu'il y a un élément qui pointe dans un profil, le
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-gc}{ramasse-miettes}
ne peut pas \emph{glaner} les paquets non utilisés.  Dans certains cas, nous
voulons temporairement tester un outil sans se préoccuper de la gestion du
profil.  C'est la fonctionnalité de \texttt{guix shell}.



\begin{frame}<presentation>[fragile]{Profils temporaires}
    \begin{center}
    Exemple : ajouter temporairement \texttt{IPython}
  \end{center}

  \bigskip

  \begin{center}
    (\texttt{demo/shell-ipython})
  \end{center}
\end{frame}


\thisslide{shell}
\begin{frame}<presentation>[label=shell,fragile]{Étendre temporairement un \emph{profil}}
  \begin{exampleblock}{}
\begin{verbatim}
guix shell -m manifest.scm
guix shell -m manifest.scm python-ipython -- ipython3
\end{verbatim}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{tabular}{lcl}
      \red{$\blacktriangleright$} \verb+--pure+ &:& réinitialise des variables
                                                    d’environnement existantes
      \\
      \red{$\blacktriangleright$} \verb+--container+ &:& lance un conteneur isolé
      \\
      \red{$\blacktriangleright$} \verb+--development+ &:& inclus les dépendances du paquet
    \end{tabular}
  \end{alertblock}

  \begin{exampleblock}{}
\begin{verbatim}
guix shell -m some-python.scm python-ipython             # 1.
guix shell -m some-python.scm python-ipython --pure      # 2.
guix shell -m some-python.scm python-ipython --container # 3.
\end{verbatim}
  \end{exampleblock}

  \begin{center}
    Bonus : \verb+guix shell emacs git git:send-email --development guix+
  \end{center}
\end{frame}

La commande \texttt{guix shell} permet de créer ou étendre temporairement un
profil.  Par exemple, dans la section précédente, le programme \texttt{cloc}
est utilisé pour compter les lignes de code.  La commande \texttt{guix shell
  cloc} a permis de lancer un \emph{shell} temporaire contenant le programme.

\medskip

Les options \texttt{pure} et \texttt{container} permettent de vérifier que
toutes les dépendances de l'application sur laquelle on travaille sont bien
capturées.  En particulier, l'option \texttt{container} permet de lancer un
\emph{shell} temporaire totalement isolé.

\bigskip

\paragraph{Nota bene~:} La commande \texttt{guix shell} a été introduite récemment pour
remplacer \texttt{guix environment}.  Cette dernière est encore conservée pour
assurer une rétro-compatibilité.  Toutefois, nous recommandons d'utiliser
\texttt{guix shell}, en particulier si vous n'avez jamais utilisé Guix
auparavant.



\begin{frame}<presentation>[plain,fragile,noframenumbering]{}
  À ce stade, il semble naturel de vouloir \uline{partager ou construire des conteneurs isolés}.

  \vfill{}
  \begin{center}
    \textbf{Comment créer des images ?}
  \end{center}
  \vfill{}
  \begin{flushright}
    (Exemple : Alice sans privilège particulier)
  \end{flushright}
\end{frame}


\clearpage
\section{Création d'images}

Dans la section précédente, nous avons vu comment créer des environnements
«~isolés~».  Il semble naturel de vouloir les partager ou les distribuer.

\subsection{Création d’un \emph{pack}}

La technologie usuelle pour transporter du matériel est celle d’un
\textbf{conteneur}.  Cependant, il ne faut \uline{\textbf{pas perdre de vue}}
la \uline{\textbf{transparence}} et la
\textbf{\uline{re\-pro\-duc\-ti\-bi\-li\-té}}.


\thisslide{conteneur}
\begin{frame}<presentation>[label=conteneur,fragile]{Comment capturer un environnement ? Conteneur}
  \begin{center}
    Conteneur = \smiley{smoothie}
  \end{center}

  \begin{itemize}
  \item Comment est construit le conteneur ? Dockerfile ?
  \item Comment sont construits les binaires inclus dans le conteneur ?
  \end{itemize}

  \begin{exampleblock}{}
\begin{verbatim}
FROM amd64/debian:stretch
RUN apt-get update && apt-get install git make curl gcc g++ ...
RUN curl -L -O https://... && ... && make -j 4 && ...
RUN git clone https://... && ... && make ... /usr/local/lib/libopenblas.a ...
\end{verbatim}
    \begin{center}
      \href{https://gitlab.onelab.info/gmsh/gmsh/-/blob/c7544ec812982dbe15e105059983f1b0c3896536/utils/docker/Dockerfile.debian.stretch.64bit}%
      {source (lien) : Gmsh~}%
      \href{http://gmsh.info/}%
      {A three-dimensional finite element mesh generator (lien)}
    \end{center}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      Avec un Dockerfile au temps t, comment regénérer l'image au temps t’ ?
    \end{center}
  \end{alertblock}
\end{frame}

\bigskip % workaround

Un conteneur est comme un «~smoothie~» dans le sens où nous pouvons
immédiatement dire si nous l’aimons ou non, mais il est difficile, si ce n’est
impossible, de donner précisément la liste exhaustive des ingrédients.  Par
conséquent, comment, à deux moments différents, reproduire exactement le même
conteneur sur deux machines différentes ?

\bigskip


\thisslide{pack}
\begin{frame}<presentation>[label=pack, fragile]{Qu’est-ce qu’un \emph{pack} ?}
  \begin{center}
    \emph{pack} = collection de paquets dans un format d’archive
  \end{center}

  Quel est le but d’un \emph{pack} ?
  \begin{itemize}
  \item Alice  distribue «~tout~» à Carole,
  \item Carole n’a pas installé Guix mais aura l’exact même environnement.
  \end{itemize}

  \begin{exampleblock}{Qu’est-ce qu’un format d’archive ?}
    \begin{itemize}
    \item \texttt{tar} (\emph{tarballs})
    \item Docker
    \item Singularity
    \item paquet binaire Debian \texttt{.deb}
    \end{itemize}
  \end{exampleblock}
\end{frame}

Un \emph{pack} est un \emph{lot de logiciels} enregistrés sous leur forme
binaire dans un format spécifique.  Le format d’archivage \texttt{tar} est
probablement le plus connu, historiquement.  Aujourd’hui,
\hrefsf{https://www.docker.com/}{Docker} ou
\hrefsf{https://sylabs.io/guides/3.4/user-guide/quick_start.html}{Singularity}
sont très largement utilisés comme format de conteneur.



\thisslide{tout}
\begin{frame}<presentation>[label=tout, fragile]{Qu'est-ce que «~tout~» ?}
  \begin{center}
    Carole a besoin de la \emph{clôture transitive} (= toutes les dépendances)
  \end{center}
  \begin{exampleblock}{}
\begin{verbatim}
$ guix size python-numpy --sort=closure
store item             total    self
python-numpy-1.20.3    301.5    23.6   7.8%
...
python-3.9.9           155.3    63.7  21.1%
openblas-0.3.18        152.8    40.0  13.3%
...
total: 301.5 MiB
\end{verbatim}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      \texttt{guix pack} permet de créer cette archive contenant «~tout~»
    \end{center}
  \end{alertblock}
\end{frame}

\clearpage % workaround

Le but d’un conteneur est de capturer l’intégralité de la pile logicielle pour
fonctionner indépendamment du système hôte.  Guix fournit une commande
(\texttt{guix size}) pour examiner la taille des éléments à inclure.  Par
exemple, le paquet \texttt{python-numpy} ne représente que moins de 8\% des
301,5Mo totaux nécessaires à son bon fonctionnement.  Nous voyons que le paquet
\texttt{python-numpy} a aussi besoin du paquet \texttt{python} ainsi que de la
bibliothèque d’algèbre linéaire \texttt{openblas}, entre autres.


\thisslide{pack2}
\begin{frame}<presentation>[label=pack2, fragile]{Création d’un \emph{pack}
    pour le distribuer}

  \begin{itemize}
  \item Alice construit un \emph{pack} au format Docker
    \begin{exampleblock}{}
      \begin{center}
        \verb+guix pack --format=docker -m manifest.scm+
      \end{center}
    \end{exampleblock}
    puis distribue ce conteneur Docker (via un \emph{registry} ou autre).

  \item Carole n'utilise pas \small{(encore?)}\normalsize{} Guix
    \begin{exampleblock}{}
\begin{verbatim}
$ docker run -ti projet-alice python3
Python 3.9.9 (main, Jan  1 1970, 00:00:01)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
\end{verbatim}
    \end{exampleblock}
    et utilise l'exact même environnement computationnel qu'Alice.
  \end{itemize}
\end{frame}

\paragraph{Prenons un exemple :} Construire et déployer cette présentation.
Les deux commandes suivantes sur une machine ayant Guix permettent de
récupérer les sources (\LaTeX) puis de construire la présentation au format
PDF.

\begin{verbatim}
guix shell git nss-certs \
     -- git clone https://gitlab.com/zimoun/jres22-tuto-guix

guix shell -m manifest.scm \
     -- rubber --pdf presentation.tex
\end{verbatim}

Alice souhaite pouvoir générer cette présentation sur une infrastructure ne
possédant pas Guix.  À la place, l’infrastructure utilise des conteneurs
Docker.  Par conséquent, Alice empaquette au format Docker
\begin{verbatim}
guix pack                                                \
     --format=docker                                     \
     -C none                                             \
     -S /bin=bin -S /lib=lib -S /share=share -S /etc=etc \
     -m manifest.scm                                     \
     --save-provenance
\end{verbatim}
qui produit l’élément dans le dépôt (\emph{store})
\texttt{/gnu/store/n92...-rubber-...-docker-pack.tar}.  Nous renvoyons à la
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-pack}%
{\textsf{section du manuel}} pour une description exhaustive des options de la
commande \texttt{guix pack}.  Notons que \texttt{-{}-symlink / -S} ajoute les
liens symboliques spécifiés dans le \emph{pack} ; par exemple, \texttt{-S
  /bin=bin} crée un lien symbolique \texttt{/bin} qui pointe vers le
sous-répertoire \texttt{bin} du profil.

\bigskip

Ce \emph{pack} une fois créé peut être chargé en local comme image Docker
pour, par exemple, ajouter une étiquette (\emph{tag}) et pousser cette image sur un
dépôt (\emph{registry})
\begin{verbatim}
$ docker load < $(guix pack ...)
$ docker images
REPOSITORY                            TAG    IMAGE ID     CREATED      SIZE
rubber-texlive-base-texlive-fonts-ec  latest 6f08ec6e1f4c 52 years ago 1.03GB
$ docker tag 6f08ec6e1f4c zimoun/jres
$ docker push zimoun/jres
\end{verbatim}
où les points \dots~ sont par exemple les options précédentes.

\medskip

Il faut noter la date qui correspond au 1\ier{} janvier 1970, c.-à-d. qui
donne les conditions pour reproduire l'image bit-à-bit.  D'autre part, il faut
aussi noter que Guix vérifie si l'élément est déjà présent dans le dépôt
(\emph{store}).

\bigskip

Maintenant, il suffit pour Carole de télécharger depuis le dépôt
(\emph{registry}) le conteneur Docker.  Par exemple, ce conteneur pourrait
être utilisé pour de l'intégration continue à travers GitLab~CI (voir l'%
\hrefsf{https://gitlab.com/zimoun/jres22-tuto-guix/-/blob/main/.gitlab-ci.yml}%
{exemple dédié} pour construire cette présentation).



\thisslide{pack3}
\begin{frame}<presentation>[label=pack3, fragile]{Au final, \texttt{guix pack}, c’est\dots}

  \begin{center}
    \emph{Agnostique} sur le format du «~conteneur~»
  \end{center}

  \begin{tabular}{cc}
    \begin{minipage}{0.4\linewidth}
      \begin{exampleblock}{}
        \begin{itemize}
        \item \texttt{tar} (\emph{tarballs})
        \item Docker
        \item Singularity
        \item paquet binaire Debian \texttt{.deb}
        \end{itemize}
      \end{exampleblock}
    \end{minipage}
    &
      \begin{minipage}{0.5\linewidth}
        \begin{alertblock}{}
          \begin{itemize}
          \item archives repositionnables
          \item sans \texttt{Dockerfile}
          \item via \texttt{squashfs}
          \item sans \texttt{debian/rule} (expérimental)
          \end{itemize}
        \end{alertblock}
      \end{minipage}
  \end{tabular}

  \bigskip

  \begin{center}
    \textbf{Adaptable aux cas d’usage}
  \end{center}
\end{frame}

\paragraph{Pour aller plus loin :} Peut-on extraire le manifeste Guix d’un
\emph{pack} au format Docker ?
\begin{center}
  \hrefsf{https://hpc.guix.info/blog/2021/10/when-docker-images-become-fixed-point/}%
  {Reproductibilité d'un conteneur Docker généré par Guix}
\end{center}

\bigskip

Internet étant fait de serveurs qui vont et viennent, les URL risquent de
ne plus pointer vers le contenu.  Par conséquent, nous donnons ici des liens
vers des archives (meilleure pérennité) pour le contenu de ce tutoriel :

\begin{itemize}
\item
  \hrefsf{https://archive.softwareheritage.org/browse/origin/directory/?origin_url=https://gitlab.com/zimoun/jres22-tuto-guix}%
  {Source} sur \hrefsf{https://www.softwareheritage.org/}{Software Heritage}
\item
  \hrefsf{https://web.archive.org/web/*/https://zimoun.gitlab.io/jres22-tuto-guix}%
  {Déploiement} sur \hrefsf{https://web.archive.org/}{Web Archive}
\end{itemize}

en plus, évidemment, des JRES.


\clearpage
\subsection{Création d'une machine virtuelle}

Dans la section précédente, nous avons vu comme créer des \emph{pack}
contenant un déploiement de paquets.  Cependant, nous souhaiterions aussi
pouvoir déployer des services.


\thisslide{image}
\begin{frame}<presentation>[label=image, fragile]{Création d’une image avec
    \texttt{guix system} : un monde de services}

  \begin{alertblock}{}
    \begin{center}
      \texttt{guix system} permet une
      \uline{\textbf{configuration déclarative} d'un \emph{système}}
    \end{center}
  \end{alertblock}

  \begin{itemize}
  \item \texttt{guix system search} pour trouver les services disponibles
  \item \texttt{guix system image} pour construire une image de type :
    \begin{itemize}
    \item qcow2
    \item docker
    \item iso9660, uncompressed-iso9660, efi-raw, raw-with-offset
    \item rock64-raw, pinebook-pro-raw, pine64-raw, novena-raw
    \item hurd-raw, hurd-qcow2
    \end{itemize}
  \item
    \begin{minipage}{1.0\linewidth}
      \begin{exampleblock}{}
        \texttt{guix system vm} pour construire une machine virtuelle (VM)
        \begin{center}
          (la VM partage son dépôt avec le système hôte)
        \end{center}
      \end{exampleblock}
    \end{minipage}
  \end{itemize}
\end{frame}

Sur le même principe que la commande \texttt{guix package}, il est possible de
chercher les services disponibles avec \texttt{guix system search}.  De plus,
la commande \texttt{guix system} permet de générer une image suivant
différents formats.  Par exemple, ceci permet d’obtenir une image
\emph{bootable} qui donne une distribution complète – appelée Guix System.

\bigskip

La commande qui nous intéresse particulièrement est \texttt{guix system vm}.
Elle permet de générer une machine virtuelle (VM) qui partage son dépôt avec
son hôte (n’importe quelle distribution Linux avec Guix installé).  L’avantage
principal est une isolation complète qui, par exemple, permet de fournir des
services.  Le déploiement de services avec Guix mériterait un tutoriel en soi,
nous donnons ici un point d’entrée.



\thisslide{image2}
\begin{frame}<presentation>[label=image2, fragile]{Configuration déclarative
    d'une machine virtuelle}
  \vspace{-0.3cm}
  \begin{exampleblock}{}
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/config-vm-1.scm}
  \end{exampleblock}
\end{frame}

Comme pour la gestion de paquets, la configuration de la machine virtuelle se
fait dans un langage déclaratif.  Le point d’entrée est le mot-clé
\texttt{operating-system}
(\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#r_00e9f_00e9rence-de-operating_002dsystem}%
{\textsf{décrit dans le manuel}}) qui spécifie les options.  En particulier,
un champ liste les paquets à provisionner et un autre champ liste les services
avec éventuellement leurs caractéristiques.


\thisslide{image3}
\begin{frame}<presentation>[label=image3, fragile]{Configuration déclarative
    d'une machine virtuelle (2)}
  \vspace{-0.3cm}
  \begin{exampleblock}{}
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/config-vm-2.scm}
  \end{exampleblock}
\end{frame}


\thisslide{image4}
\begin{frame}<presentation>[label=image4, fragile]{Machines virtuelles avec Guix}

  % \begin{center}
  %   (\texttt{demo/vm})
  % \end{center}

  \begin{alertblock}{}
    \begin{itemize}
    \item Gestion déclarative
    \item Réutilisation via des patrons (\emph{template})
    \end{itemize}
  \end{alertblock}

\end{frame}

Par exemple, la commande
\begin{center}
  \texttt{guix system vm src/example/vm-image.scm}
\end{center}
produit le script \texttt{/gnu/store/0n5...-run-vm.sh} qui lance QEMU avec les
éléments du dépôt (\emph{store}) adéquats, c.-à-d.
\begin{verbatim}
$ /gnu/store/0n5...-run-vm.sh -nic user
\end{verbatim}
démarre la machine virtuelle avec, ici, le réseau.  Ces machines virtuelles
peuvent être administrées avec le paquet \texttt{virt-manager}.



\begin{frame}<presentation>[plain,fragile,noframenumbering]{}
  Très bien tout cela, mais en quoi est-ce \uline{reproductible} ?

  \vfill{}
  \begin{center}
    \textbf{Parlons de versions !}
  \end{center}
  \vfill{}
  \begin{flushright}
    (Exemple : Carole collabore avec Alice)
  \end{flushright}
\end{frame}


\clearpage
\section{Une histoire de versions}

Le but de cette section est double, d'une part montrer par l'exemple la
capacité de Guix de s'affranchir de l'état externe et d'autre part en quoi
Guix est dit \emph{fonctionnel}.

\subsection*{Version ?  Graphe ?}

Une question récurrente des nouveaux utilisateurs de Guix est~: comment est-ce
que je spécifie la version de l’outil à utiliser ?  Une réponse à cette
question appelle une autre question~: qu’est-ce que l’on appelle version ?
Est-ce la version du code source ?  Est-ce la version du binaire ?  Mais
alors, pour le le même code source transformé par deux chaînes de compilation
différentes, appelle-t-on les deux binaires résultants la même \emph{version}
?


\thisslide{version}
\begin{frame}<presentation>[label=version, fragile]{Quelle est ma version de Guix ?}
  % \vspace{-0.25cm}
  \begin{exampleblock}{}
\begin{verbatim}
$ guix describe
Generation 76	Apr 25 2022 12:44:37	(current)
  guix eb34ff1
    repository URL: https://git.savannah.gnu.org/git/guix.git
    branch: master
    commit: eb34ff16cc9038880e87e1a58a93331fca37ad92

$ guix --version
guix (GNU Guix) eb34ff16cc9038880e87e1a58a93331fca37ad92
\end{verbatim}
  \end{exampleblock}

  % \vspace{-0.175cm}
  \begin{alertblock}{}
    \begin{center}
      Un état fixe toute la collection des paquets et de Guix lui-même
    \end{center}
  \end{alertblock}

  (Un état peut contenir plusieurs canaux (\emph{channel} = dépôt Git),\\
  \hfill avec des URL, branches ou commits divers et variés)

%   \vspace{-0.175cm}
% \begin{verbatim}
% $ guix package --list-available=^python | head -2
% python              	3.9.9    out,tk,idle	gnu/packages/python.scm:431:2
% python-absl-py      	0.6.1    out        	gnu/packages/python-xyz.scm:23415:2
% \end{verbatim}
\end{frame}

Guix capture un état : la liste de tous les paquets et les commandes Guix
elles-mêmes.  Les commandes Guix sont données par le canal principal et ce
canal fournit un ensemble de paquets (et de services).  Il est tout à fait
possible d’étendre la collection de paquets en fournissant d’autres canaux
pour avoir des paquets variants.  Par exemple, l’initiative
\hrefsf{https://hpc.guix.info/about/}{GuixHPC} (qui correspond à Guix dans un
contexte scientifique) essaie de maintenir une \hrefsf{liste de canaux}.

\medskip

Pour spécifier un canal supplémentaire, l’utilisateur (sans droit particulier)
doit modifier le fichier \texttt{\$HOME/.config/guix/channels.scm}, p. ex.
\begin{verbatim}
(cons (channel
       (name 'guix-hpc)
       (url "https://gitlab.inria.fr/guix-hpc/guix-hpc"))
      %default-channels)
\end{verbatim}
Si la canal fournit aussi des substituts binaires ce qui évite de consommer
des ressources, alors il faut
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Autoriser-un-serveur-de-substituts}%
{autoriser le serveur de substituts}.  Dans le cas de ce canal, la clé
publique est
\begin{verbatim}
(public-key
 (ecc
  (curve Ed25519)
  (q #89FBA276A976A8DE2A69774771A92C8C879E0F24614AAAAE23119608707B3F06#)))
\end{verbatim}
L’ajout de serveurs de substituts nécessite cependant des droits
d’administration privilégiés pour des raisons de sécurité.


\thisslide{dag}
\begin{frame}<presentation>[label=dag, fragile]{État = Graphe Acyclique Dirigé (\emph{DAG})}
  \vspace{-0.5cm}
  \begin{center}
    \texttt{guix graph -{}-max-depth=6 python | dot -Tpng > graph-python.png}
  \end{center}

  \vfill{}
  \includegraphics[width=\textwidth]{static/graph-python.png}
  \vfill{}

  Graphe complet : Python = 137 n\oe uds, Numpy = 189, Matplotlib = 915, Scipy
  = 1439 n\oe uds
% graph python-scipy -t bag | grep label | cut -f2 -d'[' | sort | uniq | wc -l
\end{frame}

Guix capture un état, c.-à-d. que Guix capture le graphe complet pour produire
le binaire résultant.  Il capture les relations de dépendances, les recettes
de construction et la machinerie de Guix elle-même pour traiter tout cela.

\medskip

Il n’y a pas de résolveur de dépendances qui cherche à trouver la meilleure
solution à un problème sous-contraintes.  Guix lui construit un graphe à
partir de la collection de paquets qu’il connaît dans son état courant.
Ensuite, ce graphe peut être
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Options-de-transformation-de-paquets}%
{\textsf{transformé}} pour obtenir les variants.

\medskip

Ainsi la variabilité est contrôlée aussi finement que possible.  Dans la
plupart des cas d’usage, le résultat final (la courbe publiée par Alice,
l’utilisation de tel ou tel outil par Carole, etc.) ne sera pas impacté.  La
question se pose à l’inverse quand il y a une différence dans ce résultat.
D’où vient l’erreur ?  En d’autres termes, ce contrôle fin est d’intérêt quand
on cherche à redéployer une pile logicielle pour reproduire ou dupliquer.


\subsection*{Définir un paquet}


\thisslide{def-pkg}
\begin{frame}<presentation>[label=def-pkg, fragile]{Définition d’un paquet (n\oe ud du graphe)}
  \vspace{-0.3cm}
  \begin{exampleblock}{}
    \lstinputlisting[language=Scheme,columns=space-flexible]{example/mock-define-python.scm}
  \end{exampleblock}

  \vspace{-0.2cm}
  \begin{alertblock}{}
    \begin{itemize}
    \item Chaque \texttt{inputs} est une définition similaire
      \hfill (récursion $\rightarrow$ graphe)
    \item Il n’y a pas de cycle
      \hfill (\texttt{bzip2} ou ses \texttt{inputs} ne peuvent pas utiliser \texttt{python})
    \end{itemize}
  \end{alertblock}

  \vspace{-0.25cm}
  \begin{center}
    \small{%
    (Quel commencement du graphe ?  Problème du \emph{bootstrap} dont nous ne
    parlerons pas ici)
    }\normalsize
  \end{center}
\end{frame}

Un paquet correspond à un n\oe ud du graphe.  D’une part, il contient des
\emph{meta} informations comme le nom, la version du code source, un synopsis
et description, la licence.  D’autre part, il contient la recette pour être
construit par Guix~: où trouver les sources, quelle chaîne de compilation par
défaut, quelles dépendances, et quelles modifications spécifiques
(\texttt{arguments}) pour indiquer les options de compilation ou les
changements mineurs dans la chaîne de compilation.

\medskip

Pour faciliter la création de nouveaux paquets,
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-import}%
{\textsf{la commande \texttt{guix import}}} permet de générer une recette Guix
à partir des dépôts dédiés à un écosystème (PyPI, CRAN, Bioconductor, etc.).
Il faut noter que l’\emph{utilisabilité} de la recette résultante est très
variable car elle dépend fortement de la qualité ou disponibilité des
métadonnées du dépôt source.

\medskip

De notre point de vue, empaqueter pour Guix est généralement plus facile que
pour les autres gestionnaires.  Cependant, la construction totalement isolée
de Guix oblige à une certaine gymnastique.  Au final, nous tenons à souligner
que le travail d’empaquetage quelque soit le gestionnaire sous-jacent est un
tâche laborieuse.


\clearpage
\subsection*{Changer d'état}

La
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-pull}%
{\textsf{commande \texttt{guix pull}}} permet de changer d’état en mettant à
jour la collection de paquets des différents canaux et Guix lui-même.  Par
exemple, la commande \texttt{guix pull --news} permet de savoir quelles sont
les différences entre notre état précédent et notre état courant.

\medskip

La commande \texttt{guix upgrade} permet de mettre à jour les paquets d’un
profil.  Cette commande respecte les transformations, s’il y a, dans la mise à
jour.

\medskip

En ayant la capacité d’utiliser d’autres canaux, de créer des profils et de
mettre à jour la collection des paquets, un utilisateur sans privilège devient
autonome dans la gestion de ses outils.  Bien entendu, sur une machine
mutualisée, l’administrateur peut créer des profils exposés aux utilisateurs
pour leurs fournir des suites d’outils par défaut.


\thisslide{pull}
\begin{frame}<presentation>[label=pull, fragile]{Concrètement, en pratique ?}

  \begin{alertblock}{}
    \begin{center}
      une version = un graphe
    \end{center}
  \end{alertblock}

  \begin{center}
    Mise à jour de Guix

    \texttt{guix pull}

    (création d'une nouvelle \emph{génération} interne)
  \end{center}

  \begin{itemize}
  \item Il est possible de \uline{spécifier un \emph{état}} :
    \begin{exampleblock}{}
      \begin{center}
        \begin{tabular}{rl}
          \blue{\texttt{alice@laptop\$}} & \texttt{guix describe -{}-format=channels >
                                           alice-laptop.scm}
          \\
          \violet{\texttt{carole@desktop\$}} & \texttt{guix pull -{}-channels=alice-laptop.scm}
        \end{tabular}
      \end{center}
    \end{exampleblock}
  \item Il est possible de se placer \uline{\textbf{temporairement} dans un état spécifique}\\
    \hfill pour exécuter une commande (comme créer un profil)

    \begin{exampleblock}{}
      \begin{center}
        \texttt{guix time-machine -{}-commit=c61df1792c -{}- install python -p python/autres}
      \end{center}
    \end{exampleblock}
  \end{itemize}
\end{frame}

Comme il est possible de connaître l’historique d’installation et de
suppression des paquets d’un profil avec la commande \texttt{guix package -l},
la commande \texttt{guix pull -{}-list-generations} fournit l’historique des
états de l’utilisateur.  Notons que les commandes Guix elle-mêmes vivent dans
un profil particulier (nommé \texttt{\$HOME/.config/guix/current}).

\medskip

Ainsi, sur une machine multi-utilisateurs, cette liste des états peut différer
entre les utilisateurs.  La commande \texttt{guix describe} permet de capturer
l’état courant pour soit le \emph{versionner} avec un projet, soit le
partager.  Par exemple, Alice sauvegarde son état courant dans le fichier
\texttt{alice-laptop.scm} et transmet à Carole ce fichier.  Ensuite, Carole
sur une autre machine peut se placer dans l’exact même état qu’Alice.

\medskip

Lorsque l’on travaille sur plusieurs projets, il peut devenir fastidieux de
changer d’état \emph{globalement} et il est souhaitable d’avoir la capacité de
se placer temporairement dans un état donné pour réaliser une opération
(installation, création de profil, etc.).  Ceci est possible avec la
\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Invoquer-guix-time_002dmachine}%
{\textsf{commande} \texttt{guix time-machine}}.



\thisslide{time-machine}
\begin{frame}<presentation>[label=time-machine, fragile]{Reproductibilité en arrière, en avant :
    \texttt{guix time-machine}}

  \vspace{-1cm}
  \begin{center}
    \begin{tikzpicture}
      % draw horizontal line
      \draw[thick, -Triangle] (0,0) -- (12,0) node[font=\scriptsize,below left=3pt and -8pt]{time};

      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] at (0,-.3) {2018};

      % draw vertical lines
      \foreach \x in {1,...,11}
      \draw (\x cm,3pt) -- (\x cm,-3pt);

      \foreach \x/\descr in {3/Carole,6/Alice,8/Bob}
      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] at (\x,-.3) {$\descr$};

      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] (Carole) at (3,+.3)  {d7e57e};
      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] (Alice) at (6,+.3)  {eb34ff1};
      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] (Dan) at (8,+.3)  {3682bd};

      \draw[->] (Carole.north) to [out=50,in=150] (Alice.west);
      \draw[->] (Dan.north) to [out=100,in=50] (Alice.east);

      \draw[lightgray!0!red, line width=4pt] (2,-.6) -- +(8,0);
      \foreach \x/\percol in {1/75,9/75}
      \draw[lightgray!\percol!red, line width=4pt] (\x,-.6) -- +(1,0);

      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] at (11,-.3)  {$Dan$};
      \node[font=\scriptsize, text height=1.75ex, text depth=.5ex] (Dan) at (11,+.3)  {c99c3d};
      \draw[dashed,->] (Dan.north) to [out=40,in=90] (Alice.north);

    \end{tikzpicture}
  \end{center}

  \begin{exampleblock}{}
    Pour être \uline{reproductible dans le temps}, il faut :
    \begin{itemize}
    \item Une préservation de \textbf{tous} les codes source~%
      \small{%
        (\href{https://ngyro.com/pog-reports/latest/}%
        {$\approx 75\%$ archivés \tiny{(lien)}\small} dans~%
        \href{https://www.softwareheritage.org/}%
        {Software Heritage \tiny{(lien)}\small})%
      }\normalsize
    \item Une \emph{backward} compatibilité du noyau Linux
    \item Une compatibilité du \emph{hardware} (p. ex. CPU, disque dur \tiny{(NVMe)}\normalsize, etc.)
    \end{itemize}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      Quelle est la taille de la fenêtre temporelle avec les 3 conditions
      satisfaites ?
    \end{center}
  \end{alertblock}
  \begin{center}
    \scriptsize{(À ma connaissance, le projet Guix réalise une expérimentation
      grandeur nature et quasi-unique depuis sa v1.0 en 2019)}
  \end{center}
\end{frame}

Carole et Bob, les collaborateurs d’Alice, qui aussi travaillent sur d’autres
projets avec d’autres collaborateurs peuvent convenir d’un état et s’y
placer.  Ils auront le même environnement logiciel.  Grâce aux mécanismes
d’\href{https://guix.gnu.org/manual/devel/fr/guix.fr.html#Inf_00e9rieurs}%
{inférieurs}, il est possible de tendre à une reproductibilité dans le temps.

\medskip

Pour assurer cette reproductibilité, le seul point sur lequel nous pouvons
directement agir est la sauvegarde de tous les codes sources.  Le projet Guix
participe à la mise en place de ponts avec des systèmes d’archivage comme
Software Heritage.  Chaque état correspond à une collection de paquets et donc
à des codes sources et des recettes Guix de construction.  Le chantier est en
cours pour préserver «~quoi~» et «~comment~» construire.


\clearpage
\section{Au final\dots}
\subsection*{Au final\dots}


\thisslide{continuum2}
\begin{frame}<presentation>[label=continuum2, fragile]{\dots Guix est un \emph{continuum}%
    \hfill \small{(sur n'importe quelle distribution Linux)}}

  \vspace{-0.5cm}

  \begin{center}
    \begin{tabular}{llr}
      un \uline{\textbf{gestionnaire de paquets}} déclaratif
      & \texttt{guix package}
      & (\texttt{-m} \emph{manifest})
      \\
      \ \ temporairement étendu à la volée
      & \texttt{guix shell}
      & (\texttt{-{}-container})
      \\
      \ \ \ \ maîtrisant exactement l'\emph{état}
      & \texttt{guix time-machine}
      & (\texttt{-C} \emph{channels})
      \\
      \ \ \ \ \ \ qui produit des \uline{\textbf{\emph{packs} distribuables}}
      & \texttt{guix pack}
      & (\texttt{-f docker})
      \\
      \ \ \ \ \ \ \ \ qui génèrent des \textbf{\uline{\emph{machines virtuelles}} isolées}
      & \texttt{guix sytem vm}
      \\
      \ \ \ \ \ \ \ \ \ \ \ \ \ et aussi une bibliothèque Scheme
      & \texttt{guix repl}
      & (\emph{extensions})
      \\
      $\Big($
      la distribution Linux elle-même
      & \texttt{config.scm}
      & (Guix System)
        $\Big)$
    \end{tabular}

    \begin{alertblock}{}
      \begin{center}
        \textbf{%
          Guix permet un contrôle fin du graphe de configuration sous-jacent
        }
      \end{center}
    \end{alertblock}
  \end{center}

  \begin{exampleblock}{}
    \begin{center}
      \texttt{guix time-machine -C channels.scm -{}-}
      \emph{commande options}
      \texttt{une-config.scm}
    \end{center}
  \end{exampleblock}

  \begin{alertblock}{}
    \begin{center}
      \texttt{une-config.scm} est \textbf{reproductible}
      d'une machine à l'autre et dans le temps
    \end{center}
  \end{alertblock}
\end{frame}



\thisslide{scenarii2}
\begin{frame}<presentation>[label=scenarii2,fragile]{Scenarii}
  \vspace{-0.2cm}
  \begin{itemize}
  \item Alice utilise \texttt{python@3.9} et \texttt{numpy@1.20.3}
    \vspace{-0.1cm}
    \begin{exampleblock}{}
\begin{verbatim}
$ guix install python python-numpy
\end{verbatim}
    \end{exampleblock}
  \item Carole \textbf{collabore} avec Alice\ldots{}
    mais utilise d'autres outils pour un autre projet
    \vspace{-0.1cm}
    \begin{exampleblock}{}
\begin{verbatim}
$ guix time-machine -C version-alice.scm \
       -- install -m outils-alice.scm -p projet/alice
\end{verbatim}
        \end{exampleblock}
  \item Charlie \textbf{mets à jour} son système et \textbf{tout est cassé}
    \vspace{-0.1cm}
    \begin{exampleblock}{}
\begin{verbatim}
$ guix pull --roll-back
\end{verbatim}
    \end{exampleblock}
  \item Bob utilise les \textbf{{mêmes} versions} qu'Alice mais n'a
    \textbf{pas le {même} résultat}
    \vspace{-0.1cm}
    \begin{exampleblock}{}
\begin{verbatim}
error: You found a bug
\end{verbatim}
    \end{exampleblock}
  \item Dan essaie de \textbf{rejouer plus tard} le scénario d'Alice\dots
    \vspace{-0.25cm}
    \begin{flushright}
      \scriptsize{(voir ligne commande Carole)}\normalsize
      \hfill{}
      \dots ça dépend de la date du scénario ;-)
    \end{flushright}
  \end{itemize}
\end{frame}

\clearpage
\subsection*{Limitations}

En tant que contributeur régulier, j'ai une vision biaisée qui peut-être
sur-estime les défauts à traiter et sous-estime toutes les
fonctionnalités qui résolvent un large spectre de problèmes.  Pour sûr, après
plus de deux années d'utilisation intensive de l'ordinateur portable à la
machine de calcul en passant pour la station de travail, je ne reviendrai
pas à des outils sans un paradigme déclaratif et fonctionnel.


\thisslide{limit}
\begin{frame}<presentation>[label=limit,fragile]{On s'habitue vite\dots}
  \begin{itemize}
  \item Fonctionne uniquement avec Linux.
  \item Environnement isolé implique une forte transparence,
    \begin{flushright}
      c.-à-d., difficile avec des parties propriétaires.
    \end{flushright}

  \item Certaines commandes peuvent apparaître lentes (\texttt{pull}, \texttt{search}, etc.),
    \begin{flushright}
      ou retourner des erreurs obscures.
    \end{flushright}
  \item Les premiers pas requièrent un peu de patience,
    \begin{flushright}
      et d’accepter que ce
      n’est \uline{pas \emph{comme d’habitude}}.
    \end{flushright}
  \end{itemize}

  \vfill{}
  \begin{alertblock}{}
    \begin{center}
      \textbf{La communauté est très accueillante et toujours disponible pour aider}
    \end{center}
  \end{alertblock}
\end{frame}

\begin{enumerate}
\item Le problème est la transparence de la chaîne de \emph{bootstrap} : comment
  construire à «~partir de rien~».  Techniquement, en quelques mots, le
  nœud du problème est le port de la bibliothèque C \texttt{glibc} pour un autre
  noyau.  Autrement dit, quelle est la taille de la graine binaire que l'on
  s'autorise comme racine du graphe des dépendances ?
\item Il est possible d’utiliser des pilotes spécifiques pour certains
  matériels \emph{hardware} mais c’est du travail.  D’un autre côté, dans un
  contexte de reproductibilité scientifique, ne doit-on pas chercher au
  maximum la transparence de toute la chaîne de traitement ?

  L’autre implication est l’utilisation de logiciels requérant par exemple un
  jeton de licence – comme le compilateur Fortran d’Intel \texttt{ifort}.
  L’environnement de construction étant totalement isolé, l’accès au jeton est
  impossible lors de la compilation.
\item Tout est régulièrement amélioré, dans la mesure du possible avec les
  moyens disponibles.
\item On y vient, on n’en repart pas.
\end{enumerate}

\subsection*{Ressources}


\thisslide{prod}
\begin{frame}<presentation>[label=prod]{En production}
  \vspace{-0.2cm}
  \begin{exampleblock}{}
    \begin{tabular}{lcrl|c}
      \textbf{Grid’5000}           &          &  828-nodes  &(12,000+ cores, 31 clusters) &(France)     \\
      \textbf{GliCID (CCIPL)}      & Nantes   &  392-nodes  &(7500+ cores)                 &(France)    \\
      \textbf{PlaFrIM Inria}       & Bordeaux &  120-nodes  &(3000+ cores)                 &(France)    \\
      \textbf{GriCAD}              & Grenoble &  72-nodes   &(1000+ cores)                 &(France)    \\
      \textbf{Max Delbrück Center} & Berlin   &  250-nodes  &+ workstations                &(Allemagne) \\
      \textbf{UMC}                 & Utrecht  &  68-nodes   &(1000+ cores)                 &(Pays-Bas)  \\
      \textbf{UTHSC Pangenome}     &          &  11-nodes   &(264 cores)                   &(USA)       \\
      \\
      \quad (le vôtre ?)
    \end{tabular}
  \end{exampleblock}

  \vspace{-0.25cm}
  \begin{center}
      \includegraphics[width=0.25\paperwidth]{static/guixhpc-logo-transparent-white}

    \vspace{-0.25cm}

    \href{https://hpc.guix.info/}{\texttt{https://hpc.guix.info}}
  \end{center}

  \vspace{-1.2cm}
  \begin{flushright}
    \includegraphics[width=0.175\paperwidth]{static/cafe-guix}
  \end{flushright}
\end{frame}


\thisslide{thanks}
\begin{frame}<presentation>[label=thanks]{Remerciements}
  \begin{itemize}
  \item Ludovic Courtès
  \item Ricardo Wurmus (Guix comme bibliothèque Scheme : Guix Workflow Language)
  \item Mathieu Othacehe
    (\href{https://guix.gnu.org/cuirass/}%
    {Cuirass \scriptsize{(lien)} \normalsize = CI}
    qui assure la disponibilité des \emph{substituts} binaires)
  \item tous les contributeurs (de la question au \emph{patch} en passant par
    la rapport de \emph{bug})
  \end{itemize}

  \vfill{}

  \emph{«~Présidents~» de la session} JRES :
  \begin{itemize}
  \item Yann Dupont
  \item Emmanuel Halbwachs
  \end{itemize}
\end{frame}
