Présentation du support des packages dynamiques

Le compilateur Free Pascal (FPC) et l’IDE Lazarus offrent désormais une implémentation fonctionnelle des packages dynamiques. Ces paquets sont distribués sous forme de bibliothèques partagées standard (.so, .dll, .dylib) pour Linux, Windows et macOS. Le principal avantage annoncé est la possibilité d’ajouter ou de mettre à jour des composants, contrôles et extensions sans recompilation globale de l’IDE, ce qui réduit le temps de développement de plusieurs minutes à quelques secondes.

Architecture et mécanismes d’exécution

Chaque package dynamique intègre un métadata map généré par le compilateur. Ce map décrit l’ensemble des unités, types et symboles contenus, permettant au runtime de charger, d’énumérer et de décharger les paquets à la volée. Le nouveau module RTL DynPkgTypes.pas expose la structure suivante :

type
  TPackageType = record
    { The unit that declares the type }
    UnitName: string;
    { The name of the type }
    Name: string;
    { The kind of the type }
    Kind: TTypeKind;
    { The RTTI of the type }
    Info: PTypeInfo;
    { The class if Kind is tkClass, otherwise nil }
    ClassType: TClass;
  end;

Cette description repose sur le RTTI existant, ce qui évite d’introduire de nouveaux formats de réflexion. Le runtime assure la préservation sécurisée des variables de thread et la gestion correcte des types dynamiques (chaînes, tableaux) entre le programme hôte et les packages chargés. La présence du map rend les packages plus volumineux que des bibliothèques partagées classiques ; le processus de stripping supprime les métadonnées, mais rend alors le package inutilisable comme module dynamique.

Restrictions et implications de conception

Le système impose deux contraintes de nommage. Premièrement, le nom d’une unité ne peut pas être identique au nom du package ; le compilateur ajoute automatiquement le suffixe Package au fichier source listant les unités (ex. ElectroTools.lpk → ElectroToolsPackage.pas). Deuxièmement, les noms d’unités doivent être uniques à l’échelle de tous les packages installés. En cas de conflit, l’utilisateur doit choisir le package à conserver ou renommer l’unité conflictuelle, ce qui impose une discipline de nommage stricte dans les écosystèmes partagés.

Ces restrictions limitent la capacité à publier des bibliothèques tierces contenant des unités génériques (par ex. Widgets) sans coordination préalable. Elles sont cependant nécessaires pour éviter les collisions de symboles au moment du chargement dynamique, ce qui pourrait entraîner des erreurs d’accès mémoire ou des incohérences de type.

Améliorations de l’IDE Lazarus

Lazarus intègre plusieurs mécanismes d’accompagnement. Un fenêtre de progression apparaît lorsqu’une unité d’un package est modifiée ; le système détecte le changement, reconstruit le package et notifie l’utilisateur du temps restant avant le redémarrage de l’IDE. La même fenêtre gère les reconstructions massives, l’ajout ou la suppression de plusieurs packages simultanément.

Un nouveau panneau Packages, ancré à droite, conserve la liste des packages récemment ouverts entre les sessions. Il autorise la navigation dans le contenu d’un package et l’ouverture directe d’un fichier source. Le menu des packages a été révisé : l’ajout ou le retrait d’un package met à jour l’IDE sans recompilation globale.

Enfin, l’IDE propose une option d’intégration plateforme/widgetset. Un package peut être limité à Windows, macOS ou à un widgetset spécifique, ce qui empêche son affichage ou son chargement sur des environnements non compatibles. Cette fonctionnalité est illustrée par un package implémentant TWinControl pour l’interface COM IShellView, disponible uniquement sous Windows.