Partie 6 : Vers une normalisation des dérivations

Lecture 9 min. ‱


Table des matiĂšres

Les articles de la série

Bonjour à toutes et tous! 😀

SixiĂšme article sur Nix.

Les dĂ©rivations pures c’est bien, mais elles donnent un peu trop de libertĂ©.

Absence de standard

Le problĂšme de l’informatique est souvent l’interopĂ©rĂ©rabilitĂ©.

L’interopĂ©rabiltĂ© est le fait de permettre Ă  deux sytĂšmes de pouvoir se parler au travers d’un canal normalisĂ©.

Prenons la dérivation de la partie 4 :

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};
derivation {          
  name = "hello-world";    
  system = "x86_64-linux";
  builder = "${pkgs.bash}/bin/bash";   
  args = [                 
    "-c"                                                                                                                               
    ''                       
    gcc $SOURCE -o $out         
    ''
  ];
  PATH = "${gcc}/bin";
  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"
  
    void main() {
      printf("Hello World\n");
    }
    '';
}

Elle complile les sources vers le chemin $out.

Et donc le $out est un exécutable.

A l’inverse, le paquet ${pkgs.bash} a son binaire dans le dossier $out/bin/bash.

Pour coller à ce mode fonctionnement, nous allons devoir modifier quelques peu notre dérivation.

La premiĂšre est de crĂ©er le dossier $out/bin que l’on souhaite devenir la destination du produit de compilation.

On modifie également le paramÚtre -o $out de gcc en -o $out/bin/hello-world.

On rajoute aussi coreutils dans le PATH pour accéder à la commande mkdir.

nix-shell> with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};
derivation {          
  name = "hello-world";    
  system = "x86_64-linux";
  builder = "${pkgs.bash}/bin/bash";   
  args = [                 
    "-c"                                                                                                                               
    ''
    mkdir -p $out/bin                       
    gcc $SOURCE -o $out/bin/hello-world         
    ''
  ];
  PATH = "${gcc}/bin:${coreutils}/bin/";
  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"
  
    void main() {
      printf("Hello World\n");
    }
    '';
}

This derivation produced the following outputs:
  out -> /nix/store/4wvz6l7l436ma226k4gky9985fanv8cg-hello-world

On peut ainsi visualiser le contenu de la réalisation de la dérivation.

$ tree /nix/store/4wvz6l7l436ma226k4gky9985fanv8cg-hello-world
/nix/store/4wvz6l7l436ma226k4gky9985fanv8cg-hello-world
└── bin
    └── hello-world

On se retrouve bien avec une structure semblable Ă  celle de ${pkgs.bash}/bin/bash.

Inputs

L’intĂ©rĂȘt principal de normaliser des maniĂšres de faire c’est que l’on peut facilement automatiser.

Par exemple, la définition du PATH.

Si tout les paquets respectent le mĂȘme schĂ©ma de dĂ©finitions des binaires.

PATH = "{bash}/bin:{gcc}/bin:{coreutils}/bin".

Alors, on peut simplifier l’écriture pour passer par un tableau.

buildInputs = [ bash gcc coreutils ]

Bon trùs bien, mais il n’y aura pas grand chose qui se passera.

$buildInputs n’est qu’une variable d’environnement.

Nous allons devoir la faire vivre.

Setup

Nous allons Ă©tablir une stratĂ©gie permettant d’utiliser notre variable $buildInputs.

Pour cela, nous allons déterminer un script qui fera le travail à notre place.

Je le défini délibérément naïf, dans la réalité, il faudrait le rendre plus versatile, mais ça suffira pour la démo.

On reset d’abord le $PATH.

Puis on profite de la propriĂ©tĂ© de la dĂ©rivation qui lorsque que l’on l’interpole sous la forme d’une chaĂźne devient le $out de la dĂ©rivation.

Propriété qui fonctionne également avec un tableau.

nix-repl> toString [ bash gcc coreutils ]
"/nix/store/zlf0f88vj30sc7567b80l52d19pbdmy2-bash-5.2-p15 
/nix/store/nlgyw2fv0cm8rkz8qm1jyw78vyif1bl9-gcc-wrapper-12.2.0 
/nix/store/arbxkmcgv9h8pjgj95c6d7r86yb77rl5-coreutils-9.1"

Comme nous avons choisi que les binaires serait dans le dossier $out/bin. Nous pouvons créer notre $PATH automatiquement.

PATH=""
for input in $buildInputs; do
  PATH="$PATH:$input/bin"
done

Nous allons alors faire deux choses:

La réunion de ces deux actions nous donnes la dérivation suivante:

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};
derivation {          
  name = "hello-world";    
  system = "x86_64-linux";
  builder = "${pkgs.bash}/bin/bash";   
  args = [                 
    "-c"                                                                                                                               
    ''
    source $SETUP

    # builder
    mkdir -p $out/bin                       
    gcc $SOURCE -o $out/bin/hello-world         
    ''
  ];

  SETUP = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
    '';

  buildInputs = [ bash gcc coreutils ];

  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"
  
    void main() {
      printf("Hello World\n");
    }
    '';
}

Cela peut sembler Ă©trange de vouloir Ă©crire plus de lignes pour le mĂȘme rĂ©sultat, mais nous sommes en train de nous rapprocher de l’automatisation.

Et nous allons aller encore plus loin !

Builder

Nous allons sortir dans un builder.sh le contenu du build.

mkdir -p $out/bin                       
gcc $SOURCE -o $out/bin/hello-world   

Je vais alors définir deux variables:

Et on rajoute le source builder.sh qui va bien.

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};
derivation {          
  name = "hello-world";    
  system = "x86_64-linux";
  builder = "${pkgs.bash}/bin/bash";   
  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];

  buildPhase = builtins.toFile "builder.sh" ''
    mkdir -p $out/bin
    gcc $SOURCE -o $out/bin/hello-world
  '';

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  buildInputs = [ bash gcc coreutils ];

  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"
  
    void main() {
      printf("Hello World\n");
    }
  '';
}

Ok, et donc, ça nous avance à quoi ?

J’y arrive ^^ ^

Normalisation de la dérivation

Maintenant que nous avons normalisĂ© ce que l’on pouvais, nous allons pouvoir passer Ă  l’automatisation !

Pour cela, nous allons créer une fonction qui va retourner une dérivation.

Mais avant de pouvoir y arriver, nous allons encore manipuler un peu de Nix.

Ne vous plaignez pas c’est pour votre bien. ^^ C’est comme pour aller Ă  l’étranger, savoir commander une biĂšre c’est bien.

Pouvoir Ă©galement dire en cas d’arrestation: “Je suis français, je voudrai appeler l’Ambassade” dans la langue, c’est mieux ^^

Nous allons donc dĂ©couvrir d’autres syntaxes de la grammaire.

ParamĂštres optionels

Lorsque l’on dĂ©fini une fonction en Nix, nous pouvons lui donner un set en entrĂ©e, ce set possĂšde des champs qui sont nommĂ©s.

Si notre fonction a pour signature

f = {x, y} : x + y

Il est obligatoire de remplir tous les champs

nix-repl> f {x = 12;}
error: function 'anonymous lambda' called without required argument 'y'

Ici, Nix, nous averti qu’il manque un paramùtre.

Bien que cela soit pratique dans certains cas, cela peut ĂȘtre ennuyeux. Car l’obligation de conformitĂ© est Ă©galement contraignante lorsqu’il y a trop de paramĂštres.

nix-repl> f { x = 12; y = 4; z = 42;}
error: function 'anonymous lambda' called with unexpected argument 'z'

Nix attendait seulement un paramĂštre x et y. Nous lui avons donnĂ© un paramĂštres ‘z’.

Sauf que parfois, nous ne contrĂŽlons pas avec exactitude les paramĂštres d’entrĂ©es, il peut y avoir les bons champs au bon nom mais avec des des champs supplĂ©mentaires.

data = { x = 12; y = 4; z = 42; t = { a = "chat"; b = true; }; }

A l’appel, nous avons sans surprise une erreur.

nix-repl> f data
error: function 'anonymous lambda' called with unexpected argument 'z'

Il est possible de déclarer différement notre fonction pour lui faire accepter des paramÚtres optionels.

f2 = {x, y, ...} : x + y

Et maintenant ça marche correctement ^^

nix-repl> f2 data
16

Bien entendu, les rĂšgles de champs obligatoires restent valides.

nix-repl> f { x = 12; }
error: function 'anonymous lambda' called without required argument 'y'

Et il est également possible de mélanger les concepts de champs par défaut et optionnel.

f3 = { x, y ? 0, ...} : x + y

Et dĂ©sormais y n’est plus obligatoire.

nix-repl> f3 { x = 12; }
12

Le mot-clef inherit

Il s’agit d’un sucre syntaxique qui permet de ne pas rĂ©pĂ©ter le champ et la valeur lorsque les deux possĂšdent le mĂȘme nom.

nix-repl> x = 12
nix-repl> { x = x; }
{ x = 12; }

Est équivalent à

nix-repl> { inherit x; }
{ x = 12; }

Set Binding

J’ai pas trouvĂ© de traduction satisfaisante.

C’est l’idĂ©e que l’on puisse rĂ©cupĂ©rer le set dans une variable.

La syntaxe est:

args @ { x = 12; y = true; }

ou

{ x = 12; y = true; } @ args

On peut utiliser cette propriété pour copier les champs dans un set:

wrapping = inner @ {x, y ? 0, ... } : name : 
  { inherit inner; inherit name; }

On peut alors utiliser notre data et lui donner un label.

nix-repl> wrapping data "toto"
{ inner = { ... }; name = "toto"; }

Fusion (merge) de sets

Il est possible de combiner plusieurs sets en un seul.

nix-repl> { x = 12; } // { y = true; }
{ x = 12; y = true; }

Ce qui peut se faire à répétitions

nix-repl> { x = 12; } // { y = true; } // { z = { a = 12.2; }; }
{ x = 12; y = true; z = { ... }; }

Le merge peut également réécrire des champs.

nix-repl> { x = 12; y = true; } // { x = 42; }
{ x = 42; y = true; }

Supprimer un champ

Ce n’est pas forcĂ©ment un outil du langage, mais c’est trĂšs pratique pour nore besoin.

Nix est fourni avec une série de fonctions, dont une qui nous intéresse builtins.removeAttrs.

Celle-ci prend deux paramĂštres:

Comme son nom l’indique permet de supprimer des champs d’un set.

nix-repl> builtins.removeAttrs { x = 12; y = true; z = 12.2; } [ "x" "z" ]
{ y = true; }

Notre fonction makeDerivation

Nous avons tous les outils, maintenant assemblage !!

Que voulons-nous faire déjà ?

Nous avons créé une dérivation normalisée:

derivation {          
  name    = "hello-world";    
  system  = "x86_64-linux";
  builder = "${pkgs.bash}/bin/bash";   
  args    = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];

  buildPhase  = ...;
  setupPhase  = ...;
  buildInputs = ...;
}

Le but est de pouvoir remplir seulement les champs pertinents, nous donnerons le nom de makeDerivation Ă  notre fonction.

Par exemple, notre setupPhase sera toujours identique, de mĂȘme que le builder.

A contrario, d’autres champs sont Ă  redĂ©finir pour chaque dĂ©rivation, comme buildPhase, buildInputs et name.

On dĂ©sire Ă©galement dĂ©finir le <nixpkgs> que l’on dĂ©sire pour conserver la reproductivitĂ©.

Et derniĂšre contrainte, nous voulons pouvoir dĂ©finir n’importe quelle variable d’environnement.

Prenons les choses dans l’ordre, rĂ©glons les problĂšmes un par un.

D’abord les champs obligatoires:

Et un champ possédant une valeur par défaut buildInputs.

Ce qui nous donne la signature

makeDerivation = { pkgs, name, buildPhase, buildInputs ? [] } : {}

Ok, rajoutons le corps de la dérivation avec les champs obligatoires:

makeDerivation = { pkgs, name, buildPhase, buildInputs ? [] } : 
derivation {

  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";

  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
}

Il manque les champs définis par la fonction, on les rajoute:

makeDerivation = { pkgs, name, buildPhase, buildInputs ? [] } : 
derivation {

  # champs hérités
  inherit name;
  inherit buildPhase;
  inherit buildInputs;

  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";

  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
}

Sauf que l’on peut ĂȘtre plus malin et utiliser le merge Ă  la place

makeDerivation = { pkgs, name, buildPhase, buildInputs ? [] } @ args : 
derivation {

  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";

  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
} // args

Il nous manque un bout, comment rajouter les variables d’environnement personnalisĂ©es ?

Nous utilisons les paramĂštres optionels, plus le merge

makeDerivation = { pkgs, name, buildPhase, buildInputs ? [], ... } @ args : 
derivation ( {

  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";

  args = [                 
    "-c"
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
} // args )

Attention!

Il faut bien entourĂ© de paranthĂšses sinon le merge est appliquĂ© sur le rĂ©sultat de l’appel Ă  la dĂ©rivation et non comme paramĂštre de dĂ©rivation

Ok, c’est pas mal.

Testons notre fonction:

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};

makeDerivation { 
  name = "hello-world";

  buildPhase = builtins.toFile "builder.sh" ''
    mkdir -p $out/bin
    gcc $SOURCE -o $out/bin/hello-world
  '';

  buildInputs = [ bash gcc coreutils ];

  inherit pkgs;

  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"

    void main() {
      printf("Hello World\n");
    }
  '';
}

Hum, pas fameux 



 while evaluating derivation 'hello-world'
         whose name attribute is located at «string»:7:3

       
 while evaluating attribute 'pkgs' of derivation 'hello-world'

         at «string»:16:10:

           15|
           16|   inherit pkgs;
             |          ^
           17|

AprĂšs, je ne vous ai pas parlĂ© du removeAttrs pour rien 😁

Avant de l’utiliser, qu’est ce qui se passe ?

La mĂ©thode dĂ©rivation, ne prend pas de paramĂštre autre que tu type “chaĂźne de caractĂšres”.

Or pkgs est un set qui ne peut pas ĂȘtre converti en string, ce pkgs Ă©tant passĂ© lors du merge, il se retrouve dans le paramĂštre de la dĂ©rivation qui le refuse.

On va donc nettoyer notre set d’entrĂ© pour qu’il n’y ait plus de champ pkgs.

makeDerivation =
{ pkgs, name, buildPhase, buildInputs ? [], ... } @args : derivation ({           
  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";   
  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
} // builtins.removeAttrs args ["pkgs"] )

Nous pouvons alors utiliser notre makeDerivation fraßchement réparée

deriv = with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};

makeDerivation { 
  name = "hello-world";

  buildPhase = builtins.toFile "builder.sh" ''
    mkdir -p $out/bin
    gcc $SOURCE -o $out/bin/hello-world
  '';

  buildInputs = [ bash gcc coreutils ];

  inherit pkgs;

  SOURCE = builtins.toFile "main.c" ''
    #include "stdio.h"

    void main() {
      printf("Hello World\n");
    }
  '';
}

Ce qui donne

nix-repl> :b deriv

This derivation produced the following outputs:
  out -> /nix/store/ij9lwz1wm1x02zhcix5fsdzxqf969s96-hello-world
$ /nix/store/ij9lwz1wm1x02zhcix5fsdzxqf969s96-hello-world/bin/hello-world
Hello World

C’est plus court et plus lisible, non ? 😀

Essayons avec quelque chose de plus consistant.

Nous allons reprendre le projet github au commit.

On oublie pas les bonnes habitudes et on prefetch pour récupérer la signature:

$ nix-prefetch-url --unpack https://github.com/Akanoa/nix-hello/archive/9e363d35a44b00b190a5fa8376dc2d4a221d94a2.tar.gz
path is '/nix/store/dl6rj73hw5qpj14sk7wazzh16cvrjpvv-9e363d35a44b00b190a5fa8376dc2d4a221d94a2.tar.gz'
106ra1nd19y57rnzndb87d59x1vhr6magy4y46vk98d5x6fhmr6y

Il est construit via Autotools.

Et donc notre buildPhase sera:

./configure --prefix $out
make
make test
make install

Nous avons besoin de make et de gcc.

On rajoute Ă©galement une busybox car make demande tout un tas de commandes. Sans busybox, cela ne fonctionnerait pas. Essayez sans pour voir. 🙂

Bon, nous avons tout, nous pouvons construire notre dérivation

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};

makeDerivation { 
  name = "hello-world";

  buildPhase = builtins.toFile "builder.sh" ''
    cd $SOURCE
    ./configure --prefix $out
    make
    make test
    make install
  '';

  buildInputs = [ busybox gcc gnumake ];

  inherit pkgs;

  SOURCE = fetchTarball {
    url = "https://github.com/Akanoa/nix-hello/archive/9e363d35a44b00b190a5fa8376dc2d4a221d94a2.tar.gz";
    sha256 = "106ra1nd19y57rnzndb87d59x1vhr6magy4y46vk98d5x6fhmr6y";
  };
  
}

Ben oui, mais non 


error: builder for '/nix/store/7lb3z8dxl1hwkmdk0irwkcxal2wbqias-hello-world.drv' failed with exit code 2;
last 10 log lines:
> ./configure: line 1460: can't create config.log: Permission denied

Le configure va vouloir crĂ©er des fichiers de mĂȘme que le make. RĂ©sultat, ça ne fonctionne pas. Il faut donner accĂšs au dossier.

Or, rappelez-vous, les sources sont dans le /nix/store qui n’appartient pas à notre utilisateur de build.

la stratĂ©gie est donc de copier les sources avant de modifier les droits du dossier pour finalement lancer la procĂ©dure Ă  l’intĂ©rieur.

cp -r $SOURCE work
chmod -R u+w work
cd work

Ce qui nous donne au final:

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};

makeDerivation { 
  name = "hello-world";

  buildPhase = builtins.toFile "builder.sh" ''
    cp -r $SOURCE work
    chmod -R u+w work
    cd work
    ./configure --prefix $out
    make
    make test
    make install
  '';

  buildInputs = [ busybox gcc gnumake ];

  inherit pkgs;

  SOURCE = fetchTarball {
    url = "https://github.com/Akanoa/nix-hello/archive/9e363d35a44b00b190a5fa8376dc2d4a221d94a2.tar.gz";
    sha256 = "106ra1nd19y57rnzndb87d59x1vhr6magy4y46vk98d5x6fhmr6y";
  };
  
}

Et cette fois-ci notre dĂ©rivation fonctionne 😁

$ /nix/store/m9gibyx0yxn4raa4bd0xhrfa6jwxaqm8-hello-world/bin/hello 
Hello World!

On peut mĂȘme se donner un dernier sucre syntaxique.

Il est possible de fusionner deux tableaux

nix-repl> [ 1 ] ++ [ 2 3 4 ]  
[ 1 2 3 4 ]

Nous pouvons utiliser cette propriĂ©tĂ© pour nous simplifier le travail en rendant la busybox “prĂ©-remplie”.

Ne pas oublier de retirer également le champs buildInputs du merge avec args, sinon le busybox est écrasé.

makeDerivation =
{ pkgs, name, buildPhase, buildInputs ? [], ... } @args : derivation ({           
  system = "x86_64-linux";

  setupPhase = builtins.toFile "setup.sh" ''
    PATH=""
    for input in $buildInputs; do
      PATH="$PATH:$input/bin"
    done
  '';

  builder = "${pkgs.bash}/bin/bash";

  buildInputs = [ pkgs.busybox ] ++ buildInputs;
  
  args = [                 
    "-c"                                                                                                                               
    ''
    source $setupPhase
    source $buildPhase
    ''
  ];
} // builtins.removeAttrs args ["pkgs" "buildInputs" ] )

Ce qui permet de ne plus nous en soucier:

with import (fetchTarball {
  url = "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz";
  sha256 = "1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9";
}) {};

makeDerivation { 
  name = "hello-world";

  buildPhase = builtins.toFile "builder.sh" ''
    cp -r $SOURCE work
    chmod -R u+w work
    cd work
    ./configure --prefix $out
    make
    make test
    make install
  '';

  buildInputs = [ gcc gnumake ];

  inherit pkgs;

  SOURCE = fetchTarball {
    url = "https://github.com/Akanoa/nix-hello/archive/9e363d35a44b00b190a5fa8376dc2d4a221d94a2.tar.gz";
    sha256 = "106ra1nd19y57rnzndb87d59x1vhr6magy4y46vk98d5x6fhmr6y";
  };
  
}

On pourrait encore rafiner plus la buildPhase pour Ă©crire encore moins de code, mais nous allons nous arrĂȘter lĂ , nous avons la philosophie de crĂ©ation de dĂ©rivation normalisĂ©e.

Philosophie que nous appliqueront plus tard avec de meilleurs outils.

Conclusion

Nous avons bien manipulĂ© et mĂȘme triturĂ© le langage dans tous les sens, mais vous vous doutez bien que ce n’est pas de cette façon quasi artisanale que l’on créé des dĂ©rivations dans Nix.

Dans la partie 7, nous verrons comment utiliser stdenv.mkDerivation qui n’est autre que le pendant de la fonction que nous avons créé mais en bien plus sophistiquĂ©e et directement fournie par la librairie standard!

Merci de votre lecture et Ă  la prochaine ❀