> Avant de commencer, je tiens à dire que j'ai fait ce post en partie pour l'entreprise [Unova](https://unova.fr/) où je travaillais. Je tiens à les remercier pour m'avoir autorisé à réutiliser le contenu sur mon site.
Nix est un gestionnaire de paquets basé sur le langage Nix. Il permet de gérer facilement une configuration système, d'un projet ou même d'un package (logiciel) et surtout de s'assurer de la reproductibilité de la configuration. Cependant, par défaut, Nix ne permet pas de "lock" la version de la configuration sur l'ensemble des machines. C'est pour cela que les développeurs développent Flake.
Flake est une feature experimentale qui permet de lock les dépendances sur une version très précise.
Un peu comme le Gemfile.lock ou même le package-lock.json.
Nix est un langage de programmation dédié pour la configuration d'une machine ou compilation de programme donc il peut être compliqué à prendre en main.
Il est différent des langages traditionnels, on peut le voir comme un language de construction d'un `attribut set` qui sera utilisé ensuite.
Je ferrais surement un post pour expliquer plus en détail le langage car il est assez complexe. J'ai rajouté quelques liens utiles [ici](#liens-utiles)
La dépendance `nixpkgs` correspond au repo [github nixpkgs](https://github.com/NixOS/nixpkgs). En général, on l'utilise pour récupérer des packages ou utiliser les outils mis à disposition par les contributeurs de NixOS.
> Les nouveaux packages doivent être mis dans le sous-dossier `by-name`. C'est un nouveau standard du projet. Les packages déjà existants migrent dessus petit à petit. Si un package manque, n'hésitez surtout pas à contribuer au projet.
Le flake.nix vient avec un fichier flake.lock qui permet de vérrouiller la version de chaque input. Si on souhaite mettre à jour nos packages pour notre projet. Il est nécessaire de le mettre à jour.
On retrouve deux commandes:
-`nix flake update` Mets à jour tous les inputs
-`nix flake lock --update-input <input>` Mets à jour uniquement un input en particulier
Il existe une console depuis la version expérimentale de nix `nix-command`. On peut y accéder avec la commande `nix repl`.
Normalement, on doit avoir un shell comme ci-dessous
```bash
$ nix repl
Welcome to Nix 2.18.2. Type :? for help.
nix-repl>
```
Dedans, on peut écrire n'importe quoi en nix mais aussi lui demander de charger notre configuration flake avec l'aide de la commande `:lf [path racine ou ce trouve le flake]`
> `lf` est l'abréviation de `Load Flake`
```bash
$ nix repl
Welcome to Nix 2.18.2. Type :? for help.
nix-repl> :lf .
Added 13 variables.
```
Une fois chargé, on peut accéder aux outputs avec `outputs.<type de conf>.<system>.<nom>`
> Tips : Vous pouvez appuyer deux fois sur Tab pour avoir de l'aide.
Les devShells permettent de configurer des environnements par défaut.
On peut y accéder avec l'aide de la commande `nix develop [path du flake]#[nom de l'environnement]`.
Ex: `nix develop .#default`
> Le path par défaut est déjà le répertoire courant et la configuration utilisée par défaut est également default
> Donc la commande `nix develop` suffit dans notre cas, mais si on configure par exemple `outputs.devShells.<system>.monshell`.
> Dans ce cas, il faudra utiliser `nix develop .#monshell` ou `nix develop /home/user/monflake#monshell`
On peut accéder aux environnements utilisés pour développer n'importe quel package nix. Par exemple, si l'on souhaite aider au développement de ruby. On peut lancer une console de développement avec la commande `nix develop nixpkgs#ruby` ou même voir la configuration d'un package avec `nix edit nixpkgs#ruby`
> On remarquera qu'ici j'utilise `nixpkgs` et pas le path du flake. Ça permet d'utiliser la configuration d'un package depuis nixpkgs directement.
> Pour des logiciels compilés, en général, il faut d'abord configurer le compilateur via les `phases` du logiciel. ex: `configurePhase` et ensuite compiler le logiciel ex: `buildPhase` . Les phases peuvent varier en fonction du logiciel.
# Parfois nécessaire pour configurer des projets comme Ruby avec bundle
# Certaines gems Ruby génèrent un fichier .c avec du code en dure et surtout un `#include <malib.h>` dedans.
# Sauf qu'ils utilisent pas les outils de configuration du compilateur fournis par les OS. Donc, il faut créer des variables d'environnements pour dire au compilateur ou chercher les fichiers requis.