Partie 5 : Externaliser les sources
Lecture 3 min. âą
Table des matiĂšres
Bonjour Ă toutes et tous! đ
CinquiĂšme article sur Nix.
Aujourdâhui nous allons utiliser des sources qui ne sont pas dans la dĂ©rivation, cela rendra notre dĂ©rivation plus souple.
Plus de sources !
JusquâĂ prĂ©sent notre dĂ©rivation ressemble Ă ceci:
with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
gcc $SOURCE -o $out
''
];
PATH = "${pkgs.gcc}/bin";
SOURCE = builtins.toFile "main.c" ''
#include "stdio.h"
void main() {
printf("Hello World\n");
}
'';
}Nous utilisons la varaible dâenvironnement â$SOURCEâ pour stocker un chemin de fichier local que lâon gĂ©nĂšre directement Ă partir de la fonction toFile.
Câest trĂšs bien si lâon a quâun seul fichier mais si lâon commence Ă faire grandir le projet ça va devenir de plus en plus compliquĂ© de suivre la cadence.
Exemple deux fichiers de sources nous donne:
with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
mkdir src
cd src
ln -s $SOURCE main.c
ln -s $SOURCE2 hello.c
gcc main.c -o $out
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin";
SOURCE = builtins.toFile "main.c" ''
#include "stdio.h"
#include "hello.c"
void main() {
printf("%s\n", hello());
}
'';
SOURCE2 = builtins.toFile "hello.c" ''
const char* hello() {
return "Hello World";
}
'';
}- On introduit la dérivations
pkgs.coreutilsqui contient les commandeslnetmkdir. - On créé un dossier âsrcâ et on rentre dedans
- On symlink les sources dedans
Et si on veut le faire de maniĂšre cannonique, il faut en plus rajouter un header.
with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
mkdir src
cd src
ln -s $SOURCE main.c
ln -s $SOURCE2 hello.c
ln -s $HEADER hello.h
gcc main.c hello.c -o $out
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin";
SOURCE = builtins.toFile "main.c" ''
#include "stdio.h"
#include "hello.h"
void main() {
printf("%s\n", hello());
}
'';
HEADER = builtins.toFile "hello.h" ''
const char* hello();
'';
SOURCE2 = builtins.toFile "hello.c" ''
#include "hello.h"
const char* hello() {
return "Hello World";
}
'';
}Si en plus, nous voulons respecter les standards, on peut mĂȘme se crĂ©er le Makefile. đ
Mais pour ce faire nous allons déporter nos sources.
Fetch
Pour tester cela, jâai créé un projet sur github.
Nous avons appris de notre erreur, il nous faut quelque chose de stable dans le temps, de reproductible.
LâintĂ©rĂȘt de git est de crĂ©er des signatures uniques pour chaque modification. Nous allons utiliser cette propriĂ©tĂ© pour sâassurer de la stabilitĂ© de notre dĂ©rivation.
Sur github, il est possible de voir tous les commits dâune branche.
Et ainsi récupérer le SHA1 de ce commit.
On peut alors rĂ©cupĂ©rer les sources sous la forme dâune archive via une URL formatĂ©e comme suit:
https://github.com/<projet>/archive/<SHA1>.tar.gzMon commit est le 639841dcbc59ed24a461a9dadf6234073cdafad0.
Essayons de récupérer les sources, pour cela nous allons réutiliser la commande fetchTarball.
nix-repl> fetchTarball "https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz"
"/nix/store/83z8gfh3lmi8psikgv39fpl67awkg4fg-source"
$ ls -l /nix/store/83z8gfh3lmi8psikgv39fpl67awkg4fg-source
-r--r--r-- 1 root root 70 janv. 1 1970 hello.c
-r--r--r-- 1 root root 20 janv. 1 1970 hello.h
-r--r--r-- 1 root root 1295 janv. 1 1970 LICENSE
-r--r--r-- 1 root root 90 janv. 1 1970 main.c
-r--r--r-- 1 root root 42 janv. 1 1970 Makefile
-r--r--r-- 1 root root 83 janv. 1 1970 README.mdMagnifique, nous avons nos sources. đ
Pour les construire, nous allons utiliser la méthode standard du Makefile.
Pour constuire les sources, il faut sây dĂ©placer puis lancer la commande make.
Le Makefile ressemble Ă ceci:
all: main.c
gcc main.c hello.c -o ${out}On remarque le ${out} qui est directement défini par la dérivation. La sortie de compilation sera au bon endroit.
Nous pouvons créer la dérivation qui va bien.
nix-repl> :b with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
cd $SOURCE
make
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin:${pkgs.gnumake}/bin";
SOURCE = fetchTarball "https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz";
}
This derivation produced the following outputs:
out -> /nix/store/mbx1qs39fgqiyfiikfx98gbs9vvqqxnm-hello-world
$ /nix/store/mbx1qs39fgqiyfiikfx98gbs9vvqqxnm-hello-world
Hello world!De cette maniĂšre les sources de la dĂ©rivations ne sont plus contenues par elle, mais dĂ©portĂ©es tout en conservant lâaspect de reproductibilitĂ©.
En parlant de reproductibilitĂ©, nous pouvons faire mieux. đ
Checksum
Nix propose un outil nix-prefetch-url pour calculer la somme de contrĂŽle ou checksum de ce que lâon tĂ©lĂ©charge.
$ nix-prefetch-url --unpack https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz
path is '/nix/store/livh28m4dpk96q347s8j17fv2k5drb8g-639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz'
0pvjw2kf0fwv569j2caqc983qk3x78znj52brr1a0av8f2c8rwjlAttention!
Lâargument
--unpackest important, car sinon câest la signature nâest pas correcte, en effet lefetchTarballprocĂšde au dĂ©sarchivage du tar.gz aprĂšs son tĂ©lĂ©chargement.Sans
--unpackon calcule la signature de lâarchive pas de son contenu$ nix-prefetch-url https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz path is '/nix/store/qi5nmqi9np2jbjw4f52zakr10pa6j4pr-639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz' 1wh3vf4ydvvxyiw18wwdyr1xgcqpxnlrl0wl2wcjsysflbrxlhgp
Dâailleurs, si lâon utilise le mauvais checksum:
nix-repl> :b with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
cd $SOURCE
make
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin:${pkgs.gnumake}/bin";
SOURCE = fetchTarball {
url = "https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz";
sha256 = "1wh3vf4ydvvxyiw18wwdyr1xgcqpxnlrl0wl2wcjsysflbrxlhgp";
};
}
error: hash mismatch in file downloaded from 'https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz':
specified: sha256:1wh3vf4ydvvxyiw18wwdyr1xgcqpxnlrl0wl2wcjsysflbrxlhgp
got: sha256:0pvjw2kf0fwv569j2caqc983qk3x78znj52brr1a0av8f2c8rwjlLe systĂšme signale une incohĂ©rence entre le checksum calculĂ© dâune part et le checksum spĂ©cifiĂ©, dâautre part.
Si le SHA1 correspond, le build est possible.
nix-repl> :b with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz") {};
derivation {
name = "hello-world";
system = "x86_64-linux";
builder = "${pkgs.bash}/bin/bash";
args = [
"-c"
''
cd $SOURCE
make
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin:${pkgs.gnumake}/bin";
SOURCE = fetchTarball {
url = "https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz";
sha256 = "0pvjw2kf0fwv569j2caqc983qk3x78znj52brr1a0av8f2c8rwjl";
};
}
This derivation produced the following outputs:
out -> /nix/store/mbx1qs39fgqiyfiikfx98gbs9vvqqxnm-hello-worldEt on peut faire de de mĂȘme avec le nixpkgs.
$ nix-prefetch-url --unpack https://github.com/NixOS/nixpkgs/archive/release-21.11.tar.gz
1xk1f62n00z7q5i3pf4c8c4rlv5k4jwpgh0pqgzw1l40vhdkixk9On peut alors fixé également spécifier le SHA1 du nixpkgs dans la dérivation.
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"
''
cd $SOURCE
make
''
];
PATH = "${pkgs.gcc}/bin:${pkgs.coreutils}/bin:${pkgs.gnumake}/bin";
SOURCE = fetchTarball {
url = "https://github.com/Akanoa/nix-hello/archive/639841dcbc59ed24a461a9dadf6234073cdafad0.tar.gz";
sha256 = "0pvjw2kf0fwv569j2caqc983qk3x78znj52brr1a0av8f2c8rwjl";
};
}LĂ on commence Ă avoir quelque chose qui a de la gueule! đ€©
Ainsi, mĂȘme si les donnĂ©es pointĂ©e par lâURL changent, nous sommes capable de le dĂ©tecter et dâannuler la rĂ©alisation de la dĂ©rivation.
Ce mĂ©canisme permet de sâassurer que les sources nâont pas Ă©tĂ© corrompues dâune maniĂšre ou dâune autre.
Conclusion
Nous commençons Ă nous rapprocher dâune dĂ©rivation qui est utilisable pour de vrais projets.
Dans la partie 6, nous verrons comment construire des projets plus normalisés via mkDerivation.
Merci de votre lecture â€ïž
