Concepteurs de composants, simplifiez leur installation

Sylvain James

Simplifier l'installation des concepteurs de composants avec Delphi

- Titre : Concepteurs de composants, simplifiez leur installation

- Auteur : Sylvain James

- Parution : 9 mars 2002

- Mise à jour : 31 décembre 2019

- Licence : Copyright ® 2002 Sylvain James. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Introduction

- I. Packages et composants

- II. Fichiers Packages

- III. Préparation de l'installation

- III-A. Rassembler les fichiers à installer

- III-B. Identifier les chemins de destination

- III-C. Intégration dans la palette de composants

- IV. Exemple d'installation (RxLib)

- IV-A. Rassembler les fichiers à installer

- IV-B. Construire le script InnoSetup

- IV-B-1. S'assurer que Delphi 6 est installé

- IV-B-2. Récupérer les dossiers où installer la RXLib

- IV-B-3. Réalisation du script

- V. Conclusion

- VI. Références

Introduction

Le grand nombre de composants Delphi disponibles sur la toile n'est sans doute pas étranger au succès de Delphi. L'installation d'un composant au sein de l'IDE est donc une opération importante, simple en général, mais qui repoussera encore pas mal d'utilisateurs débutants tant que cette dernière ne sera pas automatique.

Prenons l'incontournable RXLibrary : des tas de composants très utiles, mais une installation où seuls les méticuleux et les patients arrivent au bout… ça a dû coûter cher en espace disque sur les forums :-) (Pour la petite histoire et ceux qui n'y sont pas encore arrivés, la solution réside dans la lecture attentive du ReadMe.txt…)

Maintenant, regardez les GExperts qui s'installent automatiquement dans l'IDE avec un simple Setup. Même si les GExperts ne sont pas des composants au sens où ils ne s'intègrent pas dans la palette, on retiendra l'idée.

Nous apprendrons ici à concevoir un programme exécutable qui va installer vos composants directement dans la palette IDE, et ce sans même avoir besoin que Delphi soit lancé. Nous y trouverons deux avantages :

- une distribution propre de vos composants et facile pour vos utilisateurs (développeurs utilisateurs de vos composants…) ;

- la possibilité de concevoir pour soi une installation globale de tous les composants tiers qu'on utilise généralement, pour chaque réinstallation de Delphi, ou pour les installations de chaque poste d'une même équipe de développement.

I - Packages et composants

Vos composants peuvent être fournis sous forme de fichiers source et/ou compilés (*.pas et *.dcu) ou alors de packages. Un package est un conteneur de composants et va permettre à ces composants d'apparaître dans la palette de Delphi. Soit vous distribuez un paquet déjà prêt à être pris en compte par Delphi (un *.bpl) soit vous ne souhaitez pas préparer de paquet, mais alors votre programme d'installation devra prendre en charge la compilation de vos composants dans des paquets déjà existants de la station sur laquelle l'installation s'effectue.

Comment procède globalement Delphi pour afficher la palette de composants ?

Au démarrage, Delphi parcoure la clé de registre HKEY_CURRENT_USER\Software\Borland\Delphi\6.0\Known Packages\ (en rouge selon la version de Delphi). Dans cette clé nous trouverons une liste de sous-clés représentant les packages qui contiennent les composants à afficher dans la palette. Chaque nom de clé est composé du chemin suivi du nom du paquet compilé (*.bpl). La valeur de la clé est la description du paquet (fig. 1), celle que l'on retrouve lorsque l'on clique sur le menu Composants|Installer des paquets.

Figure 1

Pour chaque clé, Delphi charge le paquet compilé et en extrait les éventuels composants grâce à des fonctionnalités incluses dans le paquet bpl (qui en fait est une DLL).

II - Fichiers Packages

Delphi charge des paquets dont l'extension est *.bpl, mais la compilation d'un paquet produit aussi d'autres fichiers avec des extensions différentes.

À la base un paquet est un fichier source qui indique quels sont les fichiers source et autres paquets nécessaires pour compiler l'ensemble. Ce fichier porte l'extension *.dpk.

Les fichiers pascal objet à compiler sont des unités portant l'extension *.pas. La compilation produit un *.dcu par unité.

La compilation du paquet va engendrer une compilation si nécessaire de tous les *.pas, donc on va obtenir un ensemble de *.dcu.

L'ensemble des *.dcu sera encapsulé en une seule image binaire accompagnée des entêtes et des symboles : le fichier *.dcp.

Ce fichier sera utile au compilateur lorsqu'à la compilation d'un paquet il est fait référence à un autre (le compilo recherchera le DCP respectif) ou lorsque dans la clause uses d'une unité ou d'un projet, un paquet est référencé.

Enfin le compilateur génère également un fichier exécutable : le paquet final *.bpl qui en fait est une DLL. Des fonctions utilitaires intégrées dans cette DLL sont exportées en vue de leur utilisation par l'EDI de Delphi, notamment la fonction GetPackageInfoTable qui va retourner un pointeur sur une structure qui liste toutes les unités présentes dans le package, les pointeurs sur leur section initialization et finalization, etc.

Quand vous distribuez vos composants vous devrez livrer au minimum les *.bpl (plus les *.dcp si les paquets sont utilisés dans un environnement Delphi). Libre à vous ensuite d'ajouter les *.pas (et *.res le cas échéant), *.dpk, *.dcu.

Pour plus d'infos sur l'art et la manière de packager vos composants, allez lire le tutoriel qui a rassuré toute une génération de concepteurs… ;-) : https://merlin.developpez.com/packages/.

III - Préparation de l'installation

Il nous reste à définir les opérations nécessaires à l'installation d'un package de composants dans l'IDE. Voici les étapes nécessaires.

III-A - Rassembler les fichiers à installer

Il faut déterminer si vous distribuez le paquet avec ou sans les sources. Si vous distribuez le paquet sans les sources, le fichier bpl du paquet suffira sinon vous devrez ajouter le *.dpk et les *.pas (ainsi que le *.bdsproj si vous avez Delphi 2005 ou supérieur). Notons que dans la documentation de Delphi, il est recommandé de fournir le fichier dcp et les fichiers dcu lorsque les paquets sont transmis à d'autres développeurs (on comprend que c'est pour une utilisation dans l'EDI), utiles à de futures recompilations.

Fichiers de distribution du paquet de composants

Sans sources

Avec sources

*.bpl ; *.dcp ; *.dcu

*.bpl ; *.dcp ; *.dcu ; *.dpk (source du paquet) ; *.pas (sources des unités) ; *.res (le cas échéant) ; *.bdsproj (Delphi 2005 et supérieurs)

III-B - Identifier les chemins de destination

Les fichiers *.bpl, *.dcp et *.dcu doivent être installés dans un dossier accessible à Delphi, donc identifié dans ses options d'environnement (menu Outils|Options d'environnement) :

Les chemins pour les fichiers BPL et DCP sont clairement modifiables. Concernant les DCU on s'attachera à ce qu'ils figurent dans un dossier listé dans le chemin de bibliothèque si vous voulez que le compilateur les retrouve automatiquement, quel que soit le projet. Sinon vous pouvez indiquer leur emplacement dans les options du projet courant.

Les préférences sont modifiables hors IDE dans la base de registre aux clés suivante :

Chemin de bibliothèque

HKEY_CURRENT_USER\Software\Borland\Delphi\6.0\Library\Search Path\

Destination BPL

HKEY_CURRENT_USER\Software\Borland\Delphi\6.0\Library\Package DPL Output\

Destination DCP

HKEY_CURRENT_USER\Software\Borland\Delphi\6.0\Library\Package DCP Output\

Soit vous installerez les fichiers dans un des chemins listés, soit vous devrez ajouter le dossier d'installation dans les clés respectives.

Concernant les fichiers *.dpk et *.pas, vous pouvez les installer dans un dossier au choix de l'utilisateur. En vue d'une future compilation du dpk, il faudra juste s'assurer dans les options que les chemins de recherche permettent d'accéder aux éventuels autres paquets requis (vcl60, etc.), mais ils n'interviennent pas dans l'intégration de la palette de composants.

III-C - Intégration dans la palette de composants

Là aussi, il suffit d'un ajout dans une clé du registre comme indiqué en première partie de ce tutoriel.

Liste des packages de la palette de composants

HKEY_CURRENT_USER\Software\Borland\Delphi\6.0\Known Packages\

Chaque sous clé de la clé …\Known Packages\ sera de la forme : [Chemin du paquet bpl | Description du paquet].

Si vous avez bien suivi jusqu'à maintenant, vous êtes désormais capable de créer vos « setup » de composants. Nous allons construire un script d'installation dans la section suivante avec InnoSetup, bien connu des Delphinautes.

IV - Exemple d'installation (RxLib)

Allez pour le finish, on va se faire un petit plaisir : créer un exe d'installation pour la RXLibrary. Même pas peur :-)))

Nous allons nous conformer aux prescriptions de la page précédente de ce document et suivre les étapes indiquées.

IV-A - Rassembler les fichiers à installer

La RXLib pour Delphi 6 une fois décompressée est décomposée en dossiers Help et Units :

Le dossier Units contient tous les sources des unités et des packages ainsi que les dcu. Notre installation devra reconstituer cette arborescence sur le poste d'installation. Nous aurons également besoin d'intégrer les fichiers bpl de la RX dans le pack d'install. Si la RX n'est pas encore installée dans votre environnement, il ne reste plus qu'à la compiler pour obtenir les fichiers *.bpl. Dans un premier temps il faut compiler les paquets d'exécution nommés :

- rxctl6.dpk ;

- rxdb6.dpk ;

- rxbde6.dpk.

Ensuite, il faut compiler les paquets de conception (design-time) nécessaires à l'intégration dans l'EDI Delphi - sachant que ces paquets requièrent ceux précédemment compilés :

- dclrx6.dpk ;

- dclrxbd6.dpk ;

- dcldxdb6.dpk.

Si la compilation s'est bien passée, nous obtenons les fichiers dcp et bpl dans le dossier $(Delphi)\Projects\bpl\ (dossier par défaut des fichiers dcp et bpl). Ces fichiers font partie de la future installation. On les installera dans les dossiers spécifiés dans les clés de registre respectives (cf. page précédente du présent tutoriel).

IV-B - Construire le script InnoSetup

Contrairement à une installation classique, l'installation des composants comporte quelques spécificités.

IV-B-1 - S'assurer que Delphi 6 est installé

On passera par InnoSetup Extensions qui nous permet de paramétrer l'installation en pascal scripting. Dans la section code, fonction InitializeSetup, on vérifiera l'existence de Delphi 6 puis on initialisera des variables globales avec les chemins des BPL et des DCP, le tout grâce à des clés lues dans la base de registre :

var
DelphiRoot: string;
BPLPath: string;
DCPPath: string;

function InitializeSetup : Boolean;
begin
if GetDelphiRoot = '?' then
begin
MsgBox('Delphi 6 n''est pas installé sur votre PC');
Result := False;
end else
begin
//On récupère les chemins de destination des paquets compilés
GetDPLOutput;
GetDCPOutput;
Result := True;
end;
end;

IV-B-2 - Récupérer les dossiers où installer la RXLib

Tous les chemins d'installation ne sont pas connus à l'avance, il faut parfois les définir après lecture de certaines clés de la base de registre. C'est pourquoi nous avons ajouté des fonctions qui récupèrent ces chemins.

Rappelons que les fonctions présentées ici (comme RegQueryStringValue) sont propres à InnoSetup Extensions et non pas à Delphi.

function GetDelphiRoot : string;
begin
if not RegQueryStringValue(HKCU, 'Software\Borland\Delphi\6.0', 'RootDir', DelphiRoot) then
Result := '?'
else
Result := DelphiRoot;
end;

function GetDPLOutput : string;
var p : integer;
begin
RegQueryStringValue(HKCU, 'Software\Borland\Delphi\6.0\Library', 'Package DPL Output', BPLPath);
p := Pos('$(DELPHI)', BPLPath);
if p > 0 then BPLPath := DelphiRoot + Copy(BPLPath, 10, Length(BPLPath) - 9);
Result := BPLPath;
end;

function GetDCPOutput : string;
var p : integer;
begin
RegQueryStringValue(HKCU, 'Software\Borland\Delphi\6.0\Library', 'Package DCP Output', DCPPath);
p := Pos('$(DELPHI)', DCPPath);
if p > 0 then DCPPath := DelphiRoot + Copy(DCPPath, 10, Length(DCPPath) - 9);
Result := DCPPath;
end;

IV-B-3 - Réalisation du script

Maintenant que nous avons à notre disposition des fonctions utilitaires pour l'installation, il nous reste à énumérer la liste des fichiers à installer et leur emplacement :

...
Source: c:\Rx Library\Units\ICOLEDIT.PAS; DestDir: {app}\Units
Source: c:\Rx Library\Units\ICOLIST.dcu ; DestDir: {app}\Units
Source: c:\Rx Library\Units\ICOLIST.PAS ; DestDir: {app}\Units
Source: c:\Rx Library\Units\IMAGPRVW.dfm; DestDir: {app}\Units
Source: c:\Rx Library\Units\IMAGPRVW.PAS; DestDir: {app}\Units
...

Les bpl et dcp sont à installer dans le chemin indiqué respectivement dans les clés de registre HKCU\Software\Borland\Delphi\6.0\Library\Package DPL Output\ et …\Library\Package DCP Output\.

Au lieu d'exprimer un chemin de destination en dur, on délègue à InnoSetup la recherche de ce chemin en spécifiant la directive {code:function|parameter}, voici la liste des bibliothèques à installer (on les aura placées initialement dans un sous dossier \Lib du dossier source de la RX) :

Source: C:\Rx Library\Lib\rxdb6.bpl   ; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\dclrx6.bpl  ; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\dclrxbd6.bpl; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\dclrxdb6.bpl; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\rxbde6.bpl  ; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\rxctl6.bpl  ; DestDir: {code:ReadBPL|}
Source: C:\Rx Library\Lib\rxdb6.dcp   ; DestDir: {code:ReadDCP|}
Source: C:\Rx Library\Lib\dclrx6.dcp  ; DestDir: {code:ReadDCP|}
Source: C:\Rx Library\Lib\dclrxbd6.dcp; DestDir: {code:ReadDCP|}
Source: C:\Rx Library\Lib\dclrxdb6.dcp; DestDir: {code:ReadDCP|}
Source: C:\Rx Library\Lib\rxbde6.dcp  ; DestDir: {code:ReadDCP|}
Source: C:\Rx Library\Lib\rxctl6.dcp  ; DestDir: {code:ReadDCP|}

Les fonctions ReadBPL et ReadDCP (auxquelles on passe un paramètre vide) lisent simplement les variables globales qui ont été initialisées lors du InitializeSetup :

function ReadBPL(S : string) : string;
begin
Result := BPLPath + S;
end;

function ReadDCP(S : string) : string;
begin
Result := DCPPath + S;
end;

Enfin il reste à écrire des clés dans le registre indiquant à Delphi la présence des nouveaux paquets à prendre en compte pour la palette de composants. Il suffit d'ajouter dans la clé $(DELPHI)\Known Packages\ les chemins des paquets de conception bpl :

[Registry]
Root: HKCU; Subkey: Software\Borland\Delphi\6.0\Known Packages; ValueType: string; ValueName: {code:ReadBPL|\dclrxdb6.bpl}; ValueData: Rx Library Database Components    ; Flags: uninsdeletevalue
Root: HKCU; Subkey: Software\Borland\Delphi\6.0\Known Packages; ValueType: string; ValueName: {code:ReadBPL|\dclrx6.bpl}  ; ValueData: Rx Library Controls and Tools     ; Flags: uninsdeletevalue
Root: HKCU; Subkey: Software\Borland\Delphi\6.0\Known Packages; ValueType: string; ValueName: {code:ReadBPL|\dclrxbd6.bpl}; ValueData: Rx Library BDE Database Components; Flags: uninsdeletevalue

Voilà, il ne vous reste plus qu'à compiler le setup et… le tour est joué !

Et pour vous remercier d'avoir lu le tutoriel jusqu'ici et vous encourager à suivre cette philosophie d'installation de composants sont disponibles en téléchargement :

[22 ko] les sources RXLibInstall.iss du script d'installation InnoSetup Extensions ;
[5,4 Mo] l'exécutable final d'installation de la RXLib 2.75 (Setup_RX275.exe).

Voir aussi la bibliothèque de composants RxLib.

V - Conclusion

Finalement l'intégration automatique des librairies de composants dans Delphi n'est pas très compliquée puisqu'il suffit de les placer dans les bons dossiers et de renseigner en adéquation la base de registre. La désinstallation avec InnoSetup est automatique. Que ce soit pour constituer une installation personnelle de son environnement de composants ou pour distribuer vos créations, cette méthode séduira sans aucun doute les utilisateurs et encore plus ceux qui s'étaient préalablement confrontés à l'installation de la RX…

Reste un domaine non abordé, le cas où l'installation de vos composants doit s'effectuer dans un package déjà existant de l'environnement Delphi, par exemple le dclusr60.dpk. Une recompilation dans ce cas serait obligatoire, donc on devrait soit lancer cette compilation en appelant le compilateur DCC32.exe via un fichier batch, ou pourquoi pas passer par les API OpenTools : OTA et INTA services. On dépasse déjà l'objectif initial de ce tutoriel, mais c'est une méthode à creuser. Reste à débattre de l'intérêt d'intégrer vos nouveaux composants dans un paquet existant ou systématiquement dans des nouveaux paquets…

VI - Références

InnoSetup
InnoSetup Extensions
Merlin et les packages