Greboca  

DLFP - Dépêches  -  E.T. téléphone Meson

 -  Octobre 2018 - 

Meson est une technologie récente de la catégorie des systèmes de configuration et de gestion de la compilation de projets, à l’instar d’Autotools et de CMake. Nous proposons dans cette dépêche un tour de Meson, avec une explication des technologies en jeu, puis des comparaisons et quelques tests de rapidité et performance. En aucun cas nous ne tomberons dans le cassage des autres technologies et nous essaierons de comparer de manière la plus neutre possible.

Meson a été initié par Jussi Pakkanen en 2013. Frustré par Autotools, insatisfait par CMake, il a décidé de s’attaquer au problème et défini les buts à atteindre. Meson est le fruit de son travail, aidé de la communauté de contributeurs qui s’est formée.

Bien entendu, nous ne sommes pas omniscients et attendons des commentaires pertinents des lecteurs de LinuxFr.org pour corriger toute erreur, dans la joie et la bonne humeur.

Sommaire

N. D. M. : Cette dépêche est une reprise à partir d’une version longtemps restée inchangée dans l’espace de rédaction, ça arrive. :-) La liste des contributeurs est donc réellement la suivante : Jehan, et 16 autres : Anonyme, BAud, Olivier Humbert, palm123, _PhiX_, Cyril Brulebois, Storm, Marco, David Marec, dourouc05, ZeroHeure, vpinon, Bruno Michel, Oliver H, Boiethios et Snark.

Culture et Histoire

Au commencement le compilateur était bien seul

Quand vous souhaitez compiler un logiciel très simple, disons juste un fichier source, en général, vous ne vous embêtez avec aucun des logiciels précités. Vous sortez juste votre compilateur préféré et en une ligne de commande, vous avez votre exécutable :

gcc main.c

Même avec plusieurs fichiers, parfois on va juste enchaîner les quelques fichiers sur une ligne de commande unique et mettre le tout dans un script shell. Allez, avouez, vous avez tous fait ça un jour. Mais si, vous savez, pour votre premier jet, avant de faire votre premier commit ! Faut pas rougir !

Dans le monde des logiciels libres, les deux compilateurs les plus souvent rencontrés sont le vénérable GCC et Clang/LLVM.

Puis vint le Makefile

make propose une syntaxe de définition d’éléments de compilation dans les fichiers Makefile.

Ce format a permis de segmenter une compilation compliquée en éléments de plus petite taille. Mais surtout, il a ajouté des notions de dépendances et de compilation conditionnelle. Ainsi, la commande make ne recompile que les parties dont les fichiers sources ont été modifiés, accélérant considérablement la compilation par rapport à une compilation totale.

Chaque machine est potentiellement différente, il faut donc adapter : où installer les binaires ? Et les fichiers de données ? Ah, tu veux utiliser un autre compilateur que gcc ? Selon que tu compiles sous GNU/Linux, BSD, Windows ou macOS, tu as besoin de compiler des fichiers différents ? Ton code a besoin de savoir si la machine cible a telle API disponible ? Certaines fonctionnalités sont optionnelles ? etc.

Cette configuration est possible avec make, mais cela rend les Makefile compliqués à l’extrême. C’est là que sont nés les Autotools.

Et enfin les Autotools

Les trois principaux outils d’autotools sont autoconf, autoheader et automake.

autoconf, par exemple, va créer un fichier de configuration adapté au projet (le fameux ./configure), et automake génèrera les scripts Makefile à partir de modèles utilisant une syntaxe similaire, de plus haut niveau.

L’une des avancées majeures des autotools est la standardisation des logiciels qui en est née (voir la section Makefile Conventions des GNU Coding Standards).

Cette standardisation segmente le type de données (exécutables, bibliothèques, données du système, données du logiciel, données de l’utilisateur, configuration, etc.) et définit divers emplacements : exécutables dans /bin, données du système dans /share, configurations dans /etc

Il y eut également une standardisation des fonctionnalités de base attendues d’un système de compilation, avec des cibles/actions par défaut (par exemple, l’installation, la désinstallation, les tests unitaires, le nettoyage de fichiers construits), ainsi que de nombreuses options par défaut (pour la compilation croisée, les compilations hors de l’arbre des sources, la gestion fine des divers chemins d’installation, etc.)

Enfin, cela a standardisé les règles de compilation et d’installation avec les concepts de « préfixe », « datadir », « DESTDIR », etc. Les gens savaient à quoi s’attendre et compiler un logiciel utilisant le fameux triptyque ./configure && make && make install. À tel point que le fichier INSTALL est désormais généré par les Autotools (s’il n’existe pas, car toute installation autotools a une base similaire).

Chérie, j’ai les mêmes à la Meson ?

Meson ne prend pas make en charge. C’est un choix de conception et utilise Ninja (développé pour s’affranchir des contraintes historiques de Make).

Vous avez dit Ninja ?

Meson est souvent mis en avant pour sa rapidité de construction, mais elle est surtout due à ninja, globalement plus performant que make. En effet, les fichiers que lit ninja pour la construction ne contiennent pas de script, là où make peut être amené à réévaluer des portions de code (portions de code shell embarqué dans un Makefile par exemple).

Nous vous conseillons la lecture des raisons qui ont motivé la création de Ninja.

Pourquoi ninja est‐il plus rapide que make ?

Les raisons sont principalement historiques. La première raison est que le format Makefile fut créé pour être écrit originellement à la main (les Autotools sont nés après). Le langage a donc toutes les fonctionnalités possibles et imaginables qui auraient pu être nécessaires dans l’histoire du développement d’applications.

Le projet Ninja a fait le choix dès le début de n’avoir presque aucune fonctionnalité, sinon les plus basiques, dans les fichiers ninja eux‐mêmes :

Original : « In contrast, Ninja has almost no features; just those necessary to get builds correct while punting most complexity to generation of the ninja input files. »

Traduction : « En comparaison [de Make], Ninja n’a presque aucune fonctionnalité : seulement le strict nécessaire pour compiler correctement en déplaçant la complexité durant la génération des fichiers d’entrée Ninja. »

En particulier, on parle là de fonctionnalités décisionnelles. Même si l’étape de configuration existe avec le triptyque autotools, elle va principalement créer des variables qui seront utilisées ensuite dans les scripts Makefile. Il y a donc en réalité toujours beaucoup de code « décisionnel » exécuté lors du make. De son côté, ninja étant fait dès le début pour ne jamais être utilisé directement, ils ont délégué, par design, la plupart des décisions au script de configuration. Cela peut éventuellement amener à des scripts ninja plus verbeux et moins évidents à lire, mais néanmoins plus rapides.

Ninja se repose donc entièrement sur les projets de type meson pour gérer la partie décisionnelle, comme le manuel le dit lui‐même en conclusion de l’extrait précédent :

Original : « Ninja by itself is unlikely to be useful for most projects. »

Traduction : « Ninja, en soi, a peu de chance d’être utile à la plupart des projets. »

Alors qu’il est toujours possible, bien que déconseillé, de créer des fichiers Makefile à la main, un projet qui utilisera ninja le fera indirectement (avec cmake ou meson).

Construire un projet avec Meson

Configuration

Le projet Meson en fait une seule étape et demande donc à tout le monde d’installer meson.

Là où les Autotools faisaient :

/chemin/vers/sources/configure --prefix=/mon/prefix --enable-some-option

… Meson fait :

meson /chemin/vers/sources/ --prefix=/mon/prefix -Dsome-option=true

Les options de compilation se passent aussi sur cet appel. Pour reconfigurer, avec Autotools, il faut utiliser la même commande à nouveau. Avec meson, on doit utiliser :

meson configure -Dprefix=/autre/prefix -Dsome-option=false

Enfin pour voir seulement les options configurées, ce qui n’est pas faisable facilement avec les Autotools, on peut lancer :

meson configure

Notons que si vous avez mis à jour meson entre deux configurations, vous risquez d’obtenir l’erreur suivante :

$ meson configure
Meson configurator encountered an error:

Version mismatch (0.44.1 vs 0.44.0)

(voir le rapport de bogue)

Compilation/construction

Cette partie remplace simplement make par ninja.

Installation

Là aussi, le make install est simplement remplacé par ninja install.

Autres cibles classiques

  • make uninstall (Autotools seulement, absent de CMake par conception) est remplacé par ninja uninstall ;
  • make check (Autotools) ou make test (CMake) est remplacé par meson test ;
  • make dist et make distcheck (Autotools seulement, absent de CMake) n’existent pas ;
  • make clean (Autotools et CMake) est remplacé par ninja clean ;
  • make distclean (Autotools seulement) n’existe pas (avec une compilation hors sources, cela peut sembler moins nécessaire puisque l’on peut aussi supprimer entièrement le répertoire de compilation ; mais en réalité, make distclean est un nettoyage en profondeur et néanmoins contrôlé qui peut permettre de garder certains fichiers que l’on aurait rajoutés par exemple).

Meson génère également des projets pour deux environnements de développement intégré (EDI/IDE) répandus :

Sortie standard

Un travail a été fait sur la sortie standard, aussi bien de la configuration que de la compilation, notamment sur les couleurs, mais aussi pour la rendre plus claire et donc lisible. Un travail similaire avait aussi été fait dans CMake, ce qui est un des points agréables de ces deux systèmes de compilation. Cela est particulièrement utile pour la lecture d’erreurs de compilation.

Ainsi, lors de la compilation, ce type de sortie est affiché :

[292/912] Compiling C object 'gobject/tests/object@exe/object.c.o'

Et au lieu d’imprimer les sorties les unes au‐dessous des autres, la sortie précédente est effacée, permettant d’éviter les défilements trop longs et de se concentrer sur le dernier élément. En outre, le compteur d’étape est agréable pour savoir où l’on en est dans la compilation (particulièrement pour les très gros projets aux longues compilations).

Enfin, il est possible d’afficher la configuration actuelle grâce à la commande meson configure (avec les Autotools notamment, hormis si le projet implémente cela explicitement, il faut lire la sortie peu lisible de ./configure ou le fichier config.log). Meson n’est pas parfait non plus, mais n’en est pas loin, car il est utile de visualiser cet affichage de configuration lors de tout changement de ladite configuration :

meson configure -Dsome-option=true
meson configure

Notons que CMake a une interface curses extrêmement cool — ccmake — et qu’idéalement il faudrait que Meson crée une interface similaire (travail en cours). Cette interface permet d’avoir constamment une vision d’ensemble des options d’un projet.

Comparaisons et discussions sur les qualités de meson

Les avancées

La rapidité de ninja ne fait cependant pas tout. Parlons maintenant de Meson.

L’une des premières bonnes choses que l’on remarque est que Meson est dans une optique de standardisation de la compilation (malgré encore quelques incohérences), une chose que l’on avait un peu perdue avec CMake, qui semblait encourager les projets à redoubler d’originalité sur les options et les fonctionnalités de compilation (cette tendance s’est un peu calmée et les projets utilisant CMake se sont beaucoup standardisés ces dernières années grâce au module GNUInstallDirs, mais les premières années étaient plutôt terribles sur ce point, dans la gestion des options, mais aussi l’absence des cibles de compilation standards, par exemple pour désinstaller un paquet, nettoyer un répertoire de compilation…) !

On remarque aussi que le projet Meson semble vouloir encourager les bonnes pratiques qui se sont créées à travers l’histoire de la compilation de projet. Ainsi les warnings de compilation sont activés par défaut, et surtout les compilations hors de l’arbre des sources (aussi appelées compilations VPATH dans les Autotools) sont rendues obligatoires. Il ne s’agit pas là de fonctionnalités nouvelles ou exceptionnelles, puisqu’elles existent et sont utilisées massivement dans les projets utilisant Autotools ou CMake, mais il est intéressant de voir que le système de compilation fait le choix de proposer par défaut ces pratiques, plutôt que d’attendre des projets ou des gens de les appliquer.

Un autre apport de Meson est la gestion des en‐têtes précompilés, qui ajouterait plus de rapidité à l’étape de compilation et expliquerait partiellement que la compilation avec Meson serait plus rapide que d’autres systèmes de compilation utilisant aussi Ninja, comme CMake.

Enfin l’une des autres qualités appréciables est le faible nombre de dépendances à l’heure actuelle, à savoir : Python 3 et Ninja uniquement.

Des reculs ?

Cette section et la suivante sont un retour d’expérience d’utilisation de Meson sur des projets.

La compilation croisée semble avoir connu un recul. Les Autotools sont extrêmement bien pourvus en ce sens, une logique d’exécution sans faille avec les notions de « nom canonique » pour host, build et target. Ces notions combinées avec une très bonne détection des plates‐formes (script config.guess), permettent d’exécuter une compilation croisée avec uniquement le nom canonique de la plate‐forme cible, et les outils de compilation adéquats préfixés par ce nom canonique. Malheureusement, Meson semble avoir choisi l’approche de CMake, qui consiste en la création d’un fichier ’environnement rempli d’informations redondantes.

Ainsi, prenons ce fichier typique pour la compilation croisée pour Windows 32 bits, utilisé dans l’outil de compilation croisée, crossroad :

[binaries]
c = 'i686-w64-mingw32-gcc'
cpp = 'i686-w64-mingw32-g++'
ar = 'i686-w64-mingw32-ar'
strip = 'i686-w64-mingw32-strip'
pkgconfig = 'i686-w64-mingw32-pkg-config'

[host_machine]
system = 'windows'
cpu_family = 'x86'
cpu = 'i586'
endian = 'little'

Comme vous le notez, toutes ces informations sont entièrement redondantes et pourraient être résumée en une chaîne de caractères unique : « i686-w64-mingw32 ».

Les divers binaires par exemple sont tous préfixés du nom canonique de la plate‐forme, ce qui est tout simplement le standard à l’heure actuelle pour les outils de compilation croisée. En fait, les lister explicitement est même prompt à créer des bogues, puisque si l’on a oublié de lister un outil, Meson se rabattra sur la version non préfixée, alors même que la version préfixée existerait et serait installée. Ainsi, mon fichier est en fait incomplet, et si l’on tombait sur un projet particulier nécessitant des binaires moins communs, par exemple nm, Meson ne le trouverait pas car il n’a pas été listé, alors que x86_64-w64-mingw32-nm est pourtant bien installé sur la machine.

Quant aux informations sur le système, le processeur et le boutisme (endianness) du processeur, elles sont aussi contenues dans le nom canonique (puisqu’ils sont standardisés) et sont tout aussi redondantes.

De leur côté, les Autotools effectuent la compilation croisée avec seulement ce type de configuration :

./configure --host=x86_64-w64-mingw32

L’ensemble des informations est contenu dans cette chaîne de caractères avec la base de connaissance des plates‐formes connues, et cela évite les oublis et erreurs dans la maintenance d’un fichier à part. Notamment, par défaut, le script ./configure sélectionne toute variante dédiée à la compilation automatique et se rabat sur la version native en cas de non‐existence. Ainsi, PKG_PROG_PKG_CONFIG() utilise x86_64-w64-mingw32-pkg-config, s’il existe, et pkg-config autrement. Bien sûr, comme pour tout, il est toujours possible de passer outre les comportements par défaut, ce qui permet aussi de reproduire l’équivalent du fichier de compilation croisée au besoin, par exemple si vous utilisez des outils ou un environnement peu standard (mais, par défaut, Autotools considère que votre environnement est standard).

Il s’agit d’un choix étonnant de la part du projet Meson, puisque l’approche « à la CMake » cause quelques soucis. Il s’agit cependant d’un choix assumé, comme le confirment les développeurs dans un rapport de bogue, car les outils préfixés seraient une approche trop « GNU‐centrique ».

Enfin, malgré le choix de suivre l’esprit des Autotools en prenant en charge les cibles standards courantes, certaines cibles ont tout de même disparu. On pense notamment à make dist et make distcheck, deux cibles extrêmement importantes pour la solidité d’une archive TAR de sortie.

Meson exige donc un soin particulier à la réalisation des fichiers d’environnement, ceci peut être vue comme une qualité ou un défaut, à chacun de juger. Il y a néanmoins certaines informations que l’on ne peut considérer que comme redondantes, mais qui (pour le moment ?) sont nécessaires.

On veut des chiffres !

Pour l’étape de configuration en particulier, en utilisant le dépôt de glib qui contient maintenant autotools et meson, un simple test semble montrer vingt secondes de configuration avec les Autotools (./configure) et dix secondes avec Meson (meson).

Meson montre vraiment un grand avantage sur la reconfiguration (changer certains paramètres de configuration) : celle‐ci est quasiment instantanée avec Meson alors qu’elle prend le même temps que la première configuration avec les Autotools et CMake.

Ainsi, sur ce petit exemple de la compilation de glib, on constate une compilation de binaires durant 3 min et 40 s avec les scripts Makefile générés par Autotools, et 1 min et 11 s avec les scripts Ninja générés par Meson.

De son côté, GStreamer se configure en 14 secondes avec Autotools et 4,5 secondes avec Meson, puis se compile en 2 min et 36 s avec les Autotools et 1 min 57 s avec Meson.

Tierces notes
Notons que d’autres outils comme Bazel et Buck ont une approche différente pour optimiser les temps de compilation. Ces outils de construction utilisent en direct les compilateurs de différents langages de programmation sans passer par l’intermédiaire des outils de construction comme make ou ninja. Chaque approche à ses avantages et inconvénients. Ici, l’avantage de Meson, par rapport à Bazel et Buck, est de permettre au développeur ou à l’intégrateur d’avoir la main sur l’outil de construction (ninja, Visual C++ ou Xcode).

De son côté, GNOME Builder 3.28 prend en charge nativement les projets utilisant Meson, en plus de la prise en charge de CMake.

Le constructeur de distribution GNU/Linux Yocto le prend en charge directement dans sa base depuis la version 2.5-sumo.

Exemples de projets portés sur meson

Depuis 2016 environ, Meson est considéré comme assez mûr et a déclenché la migration de certains projets. Plus de 70 projets ont déjà basculé sur Meson. Parmi eux :

  • GStreamer (dès 2016) ;
  • GTK+ et GNOME (en 2017) ;
  • systemd ;
  • Wayland ;
  • Mesa 3D ;
  • libVA ;
  • fwupd ;
  • sysprof ;
  • X.Org ;
  • etc. (retrouvez ici la liste complète).

Conclusion

Meson est :

  • multi‐plate‐forme : GNU/Linux, macOS, Windows, GCC, Clang, Visual Studio ;
  • multi‐langage : Fortran, C, C++, Rust, Java, D ;
  • facile : configuration et définitions lisible et amicale ;
  • optimisé : pour faciliter les compilations complètes et incrémentales ;
  • moderne : gère les builds reproductibles ;
  • possède gestionnaire intégré de dépendances : fonctionne avec les paquets des distros ;
  • bien documenté ;
  • fun !

Si quelques choix peuvent paraître hasardeux, cela ne gêne personne, au regard de la liste des projets l’utilisant dès à présent, et par leurs tailles pour certains. Au final, Meson semble sur la bonne voie, sans être pour autant une révolution. Il s’agit davantage d’une évolution naturelle après quelques dizaines d’années de pratiques de la compilation de projets standards et multi-plates‐formes.

Commentaires : voir le flux atom ouvrir dans le navigateur

par Julien Jorge, Davy Defaud, Trollnad Dump, Benoît Sibaud, ZeroHeure, Bruno Michel

DLFP - Dépêches

LinuxFr.org

Tribune April : Techsoup et Solidatech, instruments d'influence

 -  27 mars - 

Après une première position sur Solidatech en 2020, l'April a passé à nouveau du temps pour étudier et comprendre la place des structures Solidatech (...)


TuxRun et le noyau Linux

 -  27 mars - 

Il y a quelques années, je vous avais présenté TuxMake, un utilitaire pour faciliter la (cross-)compilation du noyau Linux supportant une grande (...)


Retour d’expérience sur l’utilisation de GrapheneOS (ROM Android libre)

 -  18 mars - 

Suite à la dépêche Comparatif : GrapheneOS vs LineageOS, je souhaitais faire part d’un retour d’expérience sur l’utilisation de GrapheneOS sur un (...)


Ubix Linux, le datalab de poche

 -  16 mars - 

Ubix Linux est une distribution Linux libre et open-source dérivée de Debian.Le nom « Ubix » est la forme contractée de « Ubics », acronyme issu de (...)


Open Food Facts : récit d’un contributeur

 -  15 mars - 

Récit de mon aventure en tant que contributeur pour le projet Open Food Facts, la base de donnée alimentaire ouverte et collaborative, où je suis (...)