URL: https://linuxfr.org/news/le-gestionnaire-de-paquets-nix-en-version-2-0 Title: Le gestionnaire de paquets Nix en version 2.0 Authors: Collectif nokomprendo, Guillaum, Olivier HUMBERT, Bruno Michel, Davy Defaud, Yves Bourguignon, palm123, ZeroHeure, Nÿco et Benoît Sibaud Date: 2018年02月23日T23:02:09+01:00 License: CC By-SA Tags: nix et nixos Score: 48 Nix est un gestionnaire de paquets fonctionnel dont la version 2.0 est sortie récemment. Parmi les nouveautés, on peut noter qu’une commande `nix` a été introduite pour uniformiser les différentes sous‐commandes (`nix-build`, `nix-env`, etc.) et avoir de meilleures options par défaut (pour la recherche de paquets notamment). Une bonne partie du reste du travail concerne des couches moins visibles mais néanmoins importantes : prise en charge de [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2), amélioration de sécurité, etc. ![Logo Nix](https://nixos.org/logo/nixos-lores.png) Nix peut être utilisé sur n’importe quelle distribution GNU/Linux en complément du gestionnaire de paquets habituel. Il existe également une distribution GNU/Linux articulée autour de Nix : NixOS. La version 18.03 de NixOS, prévue pour sortir très prochainement, inclura Nix 2.0. **Mise à jour** : [Nix 18.03](https://nixos.org/nixos/manual/release-notes.html#sec-release-18.03) est sorti. ---- [Site officiel de Nix](https://nixos.org/nix/) [NixOS, la distribution GNU/Linux autour de Nix](https://nixos.org/) [Les notes de version pour Nix 2.0](https://nixos.org/nix/manual/#ssec-relnotes-2.0) [[LinuxFr.org] Vidéos d’introduction à Nix et NixOS, par nokomprendo](https://linuxfr.org/users/nokomprendo-3/journaux/le-style-fonctionnel-en-videos-nix-nixos-haskell) [[LinuxFr.org] L’heure du test — épisode 1 — NixOS](https://linuxfr.org/news/l-heure-du-test-episode-1-nixos) [[LinuxFr.org] Nix pour les développeurs](https://linuxfr.org/news/nix-pour-les-developpeurs) ---- # Qu’est‐ce que Nix ? Nix est un gestionnaire de paquets. Contrairement à de nombreux autres gestionnaires, qui sont le plus souvent liés à une distribution particulière, celui‐ci peut être installé sur n’importe quelle distribution. Nix permet de créer des environnements de développement reproductibles. Au lieu d’installer globalement une version particulière d’une bibliothèque, Nix l’installe dans un dossier spécifique. Ceci permet de faire cohabiter différentes versions d’une même bibliothèque et de définir des profils utilisateur ou par projet (c’est‐à‐dire des ensembles de liens vers les bibliothèques, aux versions voulues). # Quels sont les cas d’usages ? Nix peut être utile à des utilisateurs non développeurs : - cela peut être un moyen efficace d’installer des paquets qui ne sont pas disponibles via le gestionnaire de paquets de sa distribution ; - cela permet de tester l’installation de programmes ou bibliothèques sans polluer son système ; Nix conserve même l’historique des installations et permet de revenir aux états antérieurs ; - Nix gère les paquets efficacement en calculant une somme de contrôle du paquet ; ainsi, quand deux utilisateurs installent une même version d’un paquet, c’est le même dossier d’installation qui est utilisé, ce partage est sans risque car le dossier est en lecture seule et ne sera jamais supprimé tant qu’un utilisateur y fait référence ; - ce n’est pas un système de conteneurs ni de machines virtuelles, les logiciels installés par Nix sont exécutés directement par le système. Pour des développeurs, Nix est particulièrement avantageux : - c’est pratique pour les développeurs qui jonglent avec plusieurs projets, avec des dépendances dans différentes versions ; par exemple, on peut facilement ouvrir un shell avec Python 2 par défaut et un autre avec Python 3 par défaut ; - Nix permet de définir explicitement un environnement, par exemple pour un projet de développement ; pour cela, il suffit d’ajouter un fichier `.nix` et d’y indiquer les dépendances (bibliothèques nécessaires...) et le système de compilation à utiliser (autotools, cmake, ant, go...) ; on peut alors compiler et installer le projet ou lancer un shell contenant toutes les dépendances nécessaires ; - c’est un gain de temps important pour commencer à travailler sur un projet : il suffit de cloner le dépôt et de faire `nix-shell` pour obtenir un environnement de travail complet ; - l’environnement étant utilisé par les développeurs eux‐mêmes, il est donc constamment testé et à jour ; il peut également servir de point de départ pour construire le projet dans un autre contexte, par exemple pour en faire un paquet RPM, Deb, etc. ; - enfin, cela peut simplifier les scripts de construction : il n’y a plus besoin de rechercher les chemins vers les bonnes versions des différents outils, tout est pris en charge par Nix. # Quelles sont les faiblesses ? - Le gestionnaire de paquets Nix utilise son propre langage, également appelé Nix, qu’il faut donc apprendre si l’on veut créer ses propres paquets ; - l’aspect fonctionnel de Nix est très puissant mais peut être déroutant au début : on ne peut notamment pas aller bidouiller dans un dossier d’installation pour corriger un problème, il faut le faire en amont dans l’empaquetage du logiciel ; - Nix est conçu pour fonctionner dans son écosystème et non comme un outil pour distribuer un programme dans d’autres écosystèmes ; il existe cependant des approches comme [nix-bundle](https://github.com/matthewbauer/nix-bundle) ou [dockerTools](https://nixos.org/nixpkgs/manual/#sec-pkgs-dockerTools) pour cela ; - OpenGL (et à peu près tous les outils qui dépendent d’un pilote) est complexe à utiliser ; en effet, on ne peut pas compiler un programme en incluant toutes les versions possibles du pilote OpenGL. Sous NixOS, le problème n’existe pas, mais les utilisateurs de Nix sur d’autres systèmes se retrouvent face à des programmes OpenGL qui ne tournent pas directement. Le problème se contourne avec des outils comme [nixGL](https://github.com/guibou/nixGL) ou avec des [petites bidouilles](https://unix.stackexchange.com/questions/292772/run-opengl-application-installed-by-nix-package-manager). # Nouveautés de Nix 2.0 ## Nouvelle commande `nix` La nouvelle commande `nix` simplifie et uniformise certaines commandes `nix-*`, et devrait à terme toutes les remplacer : - aide en ligne avec `nix --help` ; - sortie écran moins verbeuse, apparition d’une barre de progression ; - possibilité de formater la sortie en JSON ; - `nix build` remplace `nix-build` (construit un paquet) ; - `nix run` remplace `nix-shell -p` (exécute une commande avec les dépendances spécifiées) et ne charge plus un nouveau shell ; - `nix search` remplace `nix-env -qa` (recherche de paquets) et utilise désormais un système de cache pour accélérer les recherches ; - etc. ## Extension des types de store - stores locaux : LocalStore, LocalBinaryCacheStore - stores http, ssh ou amazon S3 : HttpBinaryCacheStore, SSHStore, S3BinaryCacheStore - etc. ## Améliorations de sécurité - ajout de signatures pour les stores locaux ; - commande `nix verify` pour vérifier les paquets ; - ajout d’une vérification par signature lors des basculements sur des paquets binaires ; - etc. ## Autres - prise en charge de [HTTP/2](https://fr.wikipedia.org/wiki/Hypertext_Transfer_Protocol/2) ; - nettoyage automatique lors des constructions s’il y a un manque d’espace disque ; - prise en charge des nombres flottants dans le langage Nix ; - nouvelles fonctions prédéfinies : _builtins.fetchGit_ (récupère un dépôt Git à l’évaluation d’une expression nix), _builtins.split_ (découpe un texte selon une expression rationnelle POSIX), etc. ; - suppression de Perl et de tous ses composants dans le code de base de nix ; - etc. # Exemple pour développer en C++ avec Nix ## Code source Nous allons démontrer l’utilisation de nix sur un programme C++ complet : ```cpp #include #include #include #include int main() { for(auto &&p: std::experimental::filesystem::directory_iterator(".")) { OIIO::ImageInput *im = OIIO::ImageInput::open (p.path().c_str()); if(!im) continue; std::string s; std::cout << "Editer le fichier: " << p << " (o/N) ? "; std::cin>> s; if(s == "o") { boost::process::system(boost::process::search_path("gimp"), p.path().c_str()); break; } } } ``` Ce programme semble simple à première vue, il liste tous les fichiers d’un répertoire (grâce à `directory_iterator`) puis, pour chaque fichier, il tente d’ouvrir celui‐ci grâce à la bibliothèque OpenImageIO `OIIO`. Si l’ouverture est réussie, il propose à l’utilisateur d’éditer le fichier et si celui‐ci accepte, il sera ouvert dans GIMP grâce à un appel à la bibliothèque `boost::process`. ## Gestion des dépendances Le programme précédent a cependant des dépendances complexes : - une version d’un compilateur C++ suffisamment récent pour prendre en charge le C++11 et au moins `std::experimental::filesystem` ; - `boost` ; - `openimageio`. Nous pouvons commencer par créer un shell contenant les dépendances nécessaires à notre travail : ```bash $ nix-shell -p openimageio -p gcc -p openexr -p boost [nix-shell] $ g++ nix_test.cpp -std=c++14 -lstdc++fs -lOpenImageIO -lboost_filesystem -lboost_system [nix-shell] $ ./a.out Editer le fichier: "./passport2016.jpg" (o/N) ? o ... lancement de gimp ``` Comme vous pouvez l’observer, `nix-shell` prend en charge le approvisionnement de l’environnement de développement et il n’est pas nécessaire de spécifier de répertoire de recherche de fichiers d’en‐tête (_includes_) `-I` ni de recherche de bibliothèque `-L`. ## Environnement de développement et empaquetage La création d’un shell est une solution rapide pour l’exécution d’une tâche ponctuelle, mais il est souvent pratique de passer par un fichier `default.nix`, qui indique les directives de compilation en plus des dépendances : ```nix with import {}; stdenv.mkDerivation { name = "linuxfr_depeche_nix_20"; buildInputs = [openimageio gcc openexr boost]; src = ./.; buildPhase = '' g++ nix_test.cpp -std=c++14 -lstdc++fs -lOpenImageIO -lboost_filesystem -lboost_system ''; installPhase = '' mkdir -p $out/bin; cp a.out $out/bin/linuxfr_depeche_nix_2.0 ''; } ``` `with import {}` décrit la version de _nixpkgs_ à utiliser, nous y reviendrons. La suite décrit le nom `name` du paquet, sa liste de dépendances `buildInputs`, le répertoire où sont les sources `src`, ainsi que les commandes à effectuer pour construire le paquet `buildPhase` et installer celui‐ci avec `installPhase`. La commande `nix build` construit le paquet et le stocke dans `./result` : ```shell $ ls -R ./result ./result: bin ./result/bin: linuxfr_depeche_nix_2.0 ``` Le binaire est exécutable directement par le biais de `./result bin/linuxfr_depeche_nix_2.0`, mais peut aussi être installé : ```shell $ nix-env -i ./result installing 'linuxfr_depeche_nix_20' building '/nix/store/45l04x4nqidap70skizmvvmi7p48dgmz-user-environment.drv'... created 4407 symlinks in user environment $ linuxfr_depeche_nix_2.0 Editer le fichier: "./passport2016.jpg" (o/N) ? n Editer le fichier: "./IMG_20170521_174328.jpg" (o/N) ? o ... lancement de gimp ``` ## Personnalisation des dépendances Supposons que nous soyons dans un cas de dépendances bien plus complexes, avec les contraintes suivantes : - seul `gcc6` peut être utilisé ; - seul `boost-1.63` peut être utilisé ; - `openimageio` dépend aussi de `boost` et malheureusement la dérivation (i.e. « paquet » nix) par défaut est compilée avec `boost-1.66`, ce qui pose un conflit avec `boost-1.63`. Ce scénario peut sembler dingue, mais c’est malheureusement une constante souvent rencontrée dans le développement logiciel. Traditionnellement, ce genre de situation est réglé par la compilation à la main de toutes les dépendances, impliquant un processus long et fragile. Nix permet de surcharger tout cela très facilement. Éditons notre fichier `default.nix` : ```nix with import {}; stdenv.mkDerivation rec { name = "linuxfr_depeche_nix_20"; openimageioWithBoost163 = openimageio.override { boost = boost163; }; buildInputs = [openimageioWithBoost163 gcc6 openexr boost163]; src = ./.; buildPhase = '' g++ nix_test.cpp -std=c++14 -lstdc++fs -lOpenImageIO -lboost_filesystem -lboost_system ''; installPhase = '' mkdir -p $out/bin; cp a.out $out/bin/linuxfr_depeche_nix_2.0 ''; } ``` On note l’utilisation des paquets `gcc6` et `boost163`, fournis de base par nix. Cependant, il faut surcharger `openimageio` pour changer sa version de `boost`. Le prochain appel à `nix build` se chargera de créer la nouvelle version d’`openimageio` compilée avec la bonne version de `boost`. On note toutefois que ce processus de compilation ne sera effectué qu’une seule fois, le résultat étant stocké dans le cache local de nix. ## Reproductibilité parfaite en bloquant la version Par défaut, notre fichier `default.nix` utilise `with import {}`, c’est‐à‐dire la définition de paquets actuellement configurés sur le système. Cette approche est souple mais fragile car, en cas de mise à jour de cette liste, notre projet peut ne plus fonctionner. Il est toutefois possible de fixer cette version en se limitant à un _commit_ précis du dépôt GitHub [`nixpkgs`](https://github.com/NixOS/nixpkgs), par exemple avec : ```nix with import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/1bc5bf4beb759e563ffc7a8a3067f10a00b45a7d.tar.gz") {}; ``` Cette approche garantit une construction parfaitement reproductible. Couplée à la précision sur les versions des dépendances, nix permet d’obtenir un processus de construction de paquet très robuste. Il est maintenant possible de construire n’importe quel projet de façon robuste en deux commandes : ```bash $ (git|hg|svn|darcs|pujil|cvs) clone $ nix build ``` ## Autres fonctionnalités L’exemple précédent montre l’intérêt de Nix pour développer un projet C++. Nix apporte également de nombreuses fonctionnalités pour développer dans d’autres langages et même pour utiliser plusieurs langages dans un même projet. Enfin, Nix apporte également d’autres fonctionnalités comme la gestion de services (nixos), la création et le déploiement d’environnements logiciels légers (nixops), etc.

AltStyle によって変換されたページ (->オリジナル) /