URL: https://linuxfr.org/news/de-zig-et-des-zags Title: De Zig et des zags Authors: alberic89 _seb_, Ysabeau, orfenor, BAud, palm123, Benoît Sibaud et Strash Date: 2023-07-30T17:06:23+02:00 License: CC By-SA Tags: zig Score: 3 Cette dépêche, sous son titre énigmatique, va vous présenter un langage de programmation relativement nouveau, nommé *Zig*, avec ses caractéristiques principales ainsi que son écosystème (_toolchain_). Le but n’est pas de vous faire à tout prix adopter ce langage, mais seulement de découvrir quelques morceaux choisis, pour le plaisir des yeux. ![Logo de Zig](https://raw.githubusercontent.com/ziglang/logo/master/zig-logo-dark.svg) ---- [Dépôt Git de Zig](https://github.com/ziglang/zig) [Page Wikipédia de Zig](https://fr.wikipedia.org/wiki/Zig_(langage)) [Page d’accueil de Zig](https://ziglang.org/fr/) [Documentation de Zig](https://ziglang.org/documentation/master/) [Ziglings, des programmes Zig à réparer](https://github.com/ratfactor/ziglings) [Notes de sortie de la version 0.11.0](https://ziglang.org/download/0.11.0/release-notes.html) ---- _Note : ce langage est relativement jeune, la première version date de 2016 et la dernière version stable (0.10.1) parue en janvier 2023 est déjà considérée comme obsolète par rapport à la branche master ! Le développement est donc très actif et les diverses documentations ne peuvent rester à jour bien longtemps. Une nouvelle [version 0.11.0](https://ziglang.org/download/0.11.0/release-notes.html) est d’ailleurs sortie pendant la rédaction de la dépêche._ Présentation =========== Le langage Zig est une idée d’[Andrew Kelley](https://andrewkelley.me/post/intro-to-zig.html). Il est l’un des contributeurs principaux et [travaille à plein temps](https://andrewkelley.me/post/full-time-zig.html) sur le projet. [Zig](https://ziglang.org/) est un langage compilé impératif polyvalent, typé statiquement, « bas niveau » type C/C++/Rust. Il se décrit ainsi : > Zig est un langage de programmation généraliste ainsi qu’une toolchain ayant pour objectifs la robustesse, l’optimisation et la réutilisation du code. Ce langage se veut [plus simple](https://ziglang.org/fr/learn/overview/#un-langage-simple) que ses prédécesseurs [(« Concentrez-vous sur le debug de votre application et non sur le debug de votre connaissance du langage. »)](https://ziglang.org/fr/#-un-langage-simple) et néanmoins puissant et sécurisé. Il a aussi l’ambition avouée dès ses débuts de vouloir être un C meilleur que C, une véritable évolution, tout en restant compatible. C’est pourquoi vous pouvez faire en Zig tout ce que vous faisiez en C, mais en mieux. Installation =========== L’installation de Zig est des plus simples et universelle, puisqu’il s’agit d’une simple archive tar à extraire. On y trouve un exécutable nommé `zig` qui contient tous les outils nécessaires, et quelques fichiers de documentation ainsi que la librairie standard zig. (À noter que la source de la libc [musl](https://en.m.wikipedia.org/wiki/Musl) est également fournie pour pouvoir compiler un bon nombre de cibles, bien que Zig n’en dépende pas.) Le tout tient dans une petite archive de 45 Mo, ce qui est fort raisonnable. La deuxième étape, optionnelle, consiste à permettre l’appel à l’exécutable `zig` depuis n’importe où, soit en ajoutant le dossier contenant `zig` au `PATH`, soit en créant un lien symbolique pointant sur cet exécutable dans votre dossier `bin`. Notons que certains gestionnaires de paquets proposent déjà un package zig, même si parfois celui-ci est obsolète à cause du développement très actif de Zig. Hello, world! =========== Voici le traditionnel « Bonjour, le monde ! » : ```c const std = @import("std"); pub fn main() !void { const stdout = std.io.getStdOut().writer(); try stdout.print("Hello, {s}!\n", .{"world"}); } ``` Dans votre terminal : ```bash $ zig build-exe hello.zig $ ./hello Hello, world! ``` Un autre exemple qui sera peut-être plus intéressant, il s’agit d’extraire des entiers d’une chaine de caractère, séparés par des espaces ou des virgules. À noter que ce programme s’auto-teste : ```c const std = @import("std"); const parseInt = std.fmt.parseInt; test "parse integers" { const input = "123 67 89,99"; const ally = std.testing.allocator; var list = std.ArrayList(u32).init(ally); // Ensure the list is freed at scope exit. // Try commenting out this line! defer list.deinit(); var it = std.mem.tokenize(u8, input, " ,"); while (it.next()) |num| { const n = try parseInt(u32, num, 10); try list.append(n); } const expected = [_]u32{ 123, 67, 89, 99 }; for (expected, list.items) |exp, actual| { try std.testing.expectEqual(exp, actual); } } ``` D’autres exemples sont disponibles sur https://ziglearn.org/. Vous pouvez aussi voir le code d’un [TapTempo abondamment commenté](https://github.com/alberic89/taptempo-zig). Un mot sur l’écosystème =========== Zig fournit une chaîne de compilation qui compile le langage Zig, [mais aussi C et C++](https://ziglang.org/fr/learn/overview/#zig-est-%C3%A9galement-un-compilateur-c). Cette chaîne de compilation prend en charge la [cross-compilation](https://ziglang.org/fr/learn/overview/#la-cross-compilation-est-un-usage-de-premi%C3%A8re-importance) ainsi que la [compilation statique](https://ziglang.org/fr/learn/overview/#zig-fournit-la-libc). Zig intègre également son propre [système de construction](https://ziglang.org/fr/learn/overview/#syst%C3%A8me-de-construction-de-zig) rendant superflus l’usage de Make/Cmake/etc. Un [gestionnaire de paquets est prévu](https://github.com/ziglang/zig/issues/943), pour gérer aussi bien les bibliothèques écrites en C qu’en Zig. La [version 0.11.0 a commencé à introduire](https://ziglang.org/download/0.11.0/release-notes.html#Package-Management) ce gestionnaire de paquets et il est déjà considéré suffisamment stable pour être utilisé. Le compilateur est à lui seul une petite merveille puisqu’il est fourni avec [musl](https://musl.libc.org/) (une implémentation de la bibliothèque standard C) qu’il compile à la demande et utilise pour générer des binaires statiques. Il peut construire des exécutables pour un grand nombre [d’OS et d’architectures](https://ziglang.org/learn/overview/#cross-compiling-is-a-first-class-use-case), intègre un [cache de compilation](https://ziglang.org/download/0.4.0/release-notes.html#Build-Artifact-Caching) et [quatre modes de compilation](https://ziglang.org/documentation/master/#Build-Mode). Il [supporte même une génération du code en WebAssembly](https://ziglang.org/documentation/master/#WebAssembly) sans manipulations ésotériques, simplement en spécifiant la cible appropriée. Il est à noter qu’en mode de compilation _Release_, le compilateur est déterministe jusque dans ses optimisations, et il produira le même binaire pour la même source, au bit près ! Tout ceci fait que le compilateur C du projet Zig est tout à fait honorable (voir plus pour [certains](https://zig.news/kristoff/series/3)) face aux principaux compilateurs C du marché. Spécificité du langage =========== Quant au langage lui-même, il est conçu pour être simple et lisible, sans rien de caché : ni [flots de contrôle](https://ziglang.org/fr/learn/why_zig_rust_d_cpp/#pas-de-flot-de-contr%C3%B4le-cach%C3%A9), ni [allocations de mémoire](https://ziglang.org/fr/learn/why_zig_rust_d_cpp/#aucune-allocation-cach%C3%A9e). Si un code en Zig ne semble pas faire appel à une fonction, c’est qu’il ne le fait pas. L’objectif de cette conception est d’améliorer la lisibilité. Zig ne gère pas lui-même les allocations mémoire sur le tas. Il n’y a pas de mot clé `new` ou autre fonctionnalité qui utiliserait un allocateur de mémoire (comme un opérateur de concaténation de chaînes de caractères par exemple). Le concept de tas est géré par une bibliothèque ou le code de l’application, pas par le langage. Le principal problème avec les allocations de mémoire cachées est qu’elles empêchent la réutilisation du code dans certains environnements. Certains cas nécessitent de n’avoir aucune allocation mémoire, donc le langage de programmation doit fournir cette garantie. [La bibliothèque standard de Zig est entièrement optionnelle.](https://ziglang.org/fr/learn/why_zig_rust_d_cpp/#prise-en-charge-de-zig-sans-biblioth%C3%A8que-standard) Chaque API n’est compilée dans le programme que si elle est utilisée. Zig a la même prise en charge avec ou sans libc. Zig encourage son utilisation directement sur le matériel et le développement à haute performance. Ceci est le meilleur des deux mondes. Par exemple, les programmes WebAssembly peuvent utiliser les fonctionnalités habituelles de la bibliothèque standard, et quand même avoir des exécutables de petite taille comparés aux autres langages prenant en charge WebAssembly. [Zig n’a pas de macros ni de métaprogrammation](https://ziglang.org/fr/learn/why_zig_rust_d_cpp/#simplicit%C3%A9), et pourtant le langage exprime des programmes complexes d’une manière claire, non répétitive. Même Rust implémente en dur certaines macros, comme `format!`. L’équivalent en Zig est implémenté dans la bibliothèque standard sans code en dur dans le compilateur. [Zig 0.5.0 a introduit les fonctions `async`](https://ziglang.org/fr/learn/overview/#concurrence-avec-les-fonctions-async). Cette fonctionnalité n’a pas de dépendance au système d’exploitation hôte ou même à l’allocation de mémoire dans le tas. Cela veut dire que les fonctions `async` sont disponibles pour la cible « freestanding » (sans système d’exploitation). Dans d’autres langages de programmation, les références `null` sont sources d’erreurs à l’exécution, et sont même soupçonnées être la pire erreur en informatique. [Les pointeurs en Zig ne peuvent pas être `null`](https://ziglang.org/fr/learn/overview/#type-optionnel-plut%C3%B4t-que-des-pointeurs-null). Il existe néanmoins un type optionnel. Zig défini un [type spécial de gestion des erreurs](https://ziglang.org/documentation/0.11.0/#Errors). Les erreurs ne peuvent être ignorées. Zig vous permet d’énumérer toutes les raisons possibles de défaillance de manière exhaustive et de traiter chacune d’entre elles de manière spécifique si vous le souhaitez. Cette énumération est produite et vérifiée par le compilateur (ce qui fait partie des particularités du langage Zig), de sorte que vous ne pouvez manquer aucun cas. Il convient donc d’en tenir compte et de les traiter au moyen des mots-clés `catch`, `try`, `switch` et `unreachable`. Il a été dit plus haut que Zig n’a pas de macros. Mais il a mieux. Il peut exécuter du code à [la compilation plutôt qu’à l’exécution](https://ziglang.org/documentation/0.11.0/#comptime). En effet, une variable marquée du mot-clé `comptime` sera connue à la compilation. Les boucles marquées du mot-clé `inline` seront exécutées à la compilation. Cela permet d’exécuter à l’avance les parties du code qui ne dépendent pas des entrées utilisateur, et d’optimiser l’exécution, ou simplement automatiser des tâches répétitives pour le programmeur sans que cela ne se ressente à l’exécution. Un exemple : je veux que mon programme affiche son nom à différent stade de son exécution, avec de grandes lettres en art ASCII. On dispose pour cela d’une chaîne de caractère contenant le nom du programme, et d’une fonction `foo` qui retourne une chaine avec de grandes lettres en art ASCII en échange d’une chaîne de caractère. La plupart du temps, on se contenterait d’appeler une fois la fonction `foo` au début du programme et à stocker dans une variable le résultat pour l’afficher. Mais Zig permet d’aller plus loin. Avec l’exécution à la compilation, on peut n’exécuter la fonction donnant les grandes lettres qu’à la compilation, augmentant ainsi légèrement le temps d’exécution. La fonction `foo` n’étant pas utile à l’exécution, elle ne sera pas incluse dans le binaire, tout comme la chaîne contenant le nom du programme. Cet exemple est trivial, mais peut vous donner un aperçu de la puissance du _comptime_. Pour un article plus détaillé sur le _comptime_ Zig, voir https://zig.news/edyu/wtf-is-zig-comptime-and-inline-257b Vous pourrez en apprendre encore plus en lisant la [vue d’ensemble du projet](https://ziglang.org/fr/learn/overview/), ou en jouant avec les [ziglings](https://github.com/ratfactor/ziglings) ! Les outils =========== Il n’existe à ce jour aucun IDE conçu pour Zig, mais certains éditeurs de texte supportent déjà des fonctionnalités telles que la coloration syntaxique. Ces éditeurs sont [Emacs, Vim, Kate, VS Code et Sublime Text](https://ziglang.org/fr/learn/tools/#%C3%A9diteurs-de-texte). Un [serveur de langue](https://en.wikipedia.org/wiki/Language_Server_Protocol) est [fourni](https://ziglang.org/fr/learn/tools/#serveurs-de-langue) également pour les [clients le supportant](https://langserver.org/#implementations-client). Quant au débogage, il peut se faire tout simplement avec `gdb`, ou n’importe quel débogueur C/C++. Néanmoins, le compilateur fournit des indications si précises sur les erreurs qu’on a pu commettre que le recours à un débogueur pour la plupart des erreurs triviales est inutile. Les librairies Zig, elles, sont, pour l’instant, peu nombreuses, et il n’existe pas d’index « officiel » pour les référencer puisque la communauté est décentralisée. À la place, on retrouve plusieurs petits index maintenus par la communauté. Il existe tout de même un [projet en cours de gestionnaire de paquet](https://kristoff.it/blog/zig-self-hosted-now-what/#the-official-package-manager) livré avec Zig, qui n’est relié à aucun index en particulier, et qui gèrera aussi bien les modules Zig que C/C++. Usage =========== Zig est un langage de programmation assez généraliste, il peut donc convenir à la plupart des usages. Il est notamment plébiscité pour des programmes ayant des contraintes de performance et de consommation mémoire que l’on peut retrouver dans les systèmes embarqués et applications en « temps réel ». Une communauté d’utilisateurs (des _ziguanas_) dans ce domaine ([_zig embedded group_](https://microzig.tech/)) s’organise autour du projet [microzig](https://github.com/ZigEmbeddedGroup/microzig/) afin d’offrir l’outillage nécessaire pour ce type de développement. On peut trouver plusieurs [listes de projets écrits en Zig](https://github.com/zigcc/awesome-zig-list), parmi lesquels on trouve un [lecteur de flux Fediverse pour bureau GTK](https://github.com/donpdonp/zootdeck), un [solveur de sudoku](https://github.com/user00e00/sudokuinzig), un [interpréteur Brainfuck](https://github.com/dantecatalfamo/brainfuck-zig), un [éditeur de pixel art](https://github.com/fabioarnold/MiniPixel), [un système d’exploitation](https://github.com/birth-software/birth), un [environnement d’exécution JavaScript](https://github.com/oven-sh/bun), un [jeu RPG 2D](https://github.com/foxnne/aftersun)… Les usages de Zig sont multiples et variés ! Zig est aussi utilisé par des entreprises comme [Uber](https://zigmonthly.org/letters/2022/may-june/#how-zig-is-used-at-uber) ou [TigerBeetle](https://tigerbeetle.com/). La version 0.11.0 ================= Cette sortie de version inclut 8 mois de travail : des changements de la part de 269 contributeurs différents, répartis dans 4457 changements. Un total de 1012 tickets résolus ! C’est également [« the début of Package Management »](https://ziglang.org/download/0.11.0/release-notes.html#Package-Management). Le mot de la fin =========== Zig est sous licence MIT. L’organisation [_Zig Software Foundation_](https://ziglang.org/zsf/) est une organisation à but non lucratif 501(c)(3)) dont l’objectif est de soutenir le projet Zig que ce soit par la rémunération, voire, l’embauche, de développeurs ([Jakub Konka, Rich Felker, Meghan Denny, Andrew Kelley](https://ziglang.org/news/jakub-konka-hired-full-time/)) ou le sponsoring d’autres projets gravitant autour du projet ([Zig books](https://kristoff.it/blog/note-about-zig-books/) par exemple ou indirectement [musl](https://andrewkelley.me/post/why-donating-to-musl-libc-project.html)). ![Zero the Ziguana, une des mascottes de Zig](https://raw.githubusercontent.com/ziglang/logo/master/zero.svg)