Découverte de Tclkit

 

Kroc - 08 Juin 2004


Tclkit est un ensemble d'applications inventées par Jean-claude Wippler dont le but principal est de faciliter la distribution, l'installation et l'utilisation d'une application écrite en Tcl/Tk en regroupant les éléments qui la compose en un seul fichier. Ce fichier peut être un starkit directement exécutable par tclsh ou wish, ou un starpack exécutable sur une machine où Tcl/Tk n'est même pas installé.

Mais Tclkit permet de faire beaucoup plus, comme je me propose de vous le faire découvrir dans cet article. Comme le dit mon ami Steve Landers, Tclkit c'est tout simplement une autre façon d'aborder la programmation.

Télécharger Tclkit

Créez un nouveau répertoire Tclkit dans lequel vous enregistrerez les fichiers que vous allez télécharger.

Vous devez dans un premier temps récupérer les versions de tclkit qui vous intéresse ici : http://code.google.com/p/tclkit/downloads/list Comme nous le verrons plus loin, vous aurez besoin des tclkits pour d'autres plate-formes que linux si vous désirez créer des starpacks pour ces plate-formes depuis linux.

Récupérez ensuite l'utilitaire sdx.kit (Starkit Developer eXtension) au même endroit (http://tclkit.googlecode.com/files/sdx-20110317.kit au 02/08/2012)

Installation

Allez dans le répertoire Tclkit et décompressez tous les tclkit-*.gz que vous avez téléchargés. Ensuite, renommez le tclkit pour linux en tclkit#ver-linux (exemple : tclkit844-linux pour la version 8.4.4). Faites ensuite une copie de ce fichier en tclkit puis rendez ce fichier exécutable (chmod +x tclkit).

Si vous avez téléchargé des tclkits pour d'autres plate-formes, renommez-les de la même manière (exemples : tclkit844-freebsd, tclkit844-hpux, tclkit844-solaris, tclkit844-darwin, tclkit844-win32.exe, tclkit844sh-win32.exe, etc..). Notez que seul Windows nécessite deux tclkits différents pour tclsh et wish.

Enfin, renommez sdx.kit sdx et rendez-le exécutable (mv sdx.kit sdx ; chmod +x sdx).

Pour tester votre installation, ouvrez une fenêtre de commande, placez-vous dans le répertoire Tclkit puis tapez :

 ./tclkit

Une fois le prompt % disponible, tapez :

 package require Tk

Si tout est installé correctement, une fenêtre intitulée tclkit doit s'afficher. Tapez exit pour fermer tclkit : vous êtes prêt à passer à la suite.

Transformation d'un script tcl en starkit

Nous allons commencer par créer un petit script tcl coucou.tcl très simple avec le contenu suivant :

 package require Tk
 pack [button .b -text "Coucou !" -command "bell"]

Et nous allons enregistrer ce fichier dans notre répertoire Tclkit.

Pour transformer ce script tcl en starkit, ouvrez une console ou un xterm, placez vous dans le répertoire Tclkit et tapez :

 sdx qwrap coucou.tcl

Ce qui va créer le fichier coucou.kit dans le même répertoire. Comme vous le voyez, la création d'un starkit est très simple ! Pour plus d'informations sur l'utilitaire sdx, vous pouvez consulter sdx.

Exécuter un starkit

Pour lancer un starkit vous avez plusieurs solutions, la plus évidente étant d'utiliser tclkit : tclkit coucou.kit. Mais si vous avez une version récente de Tcl/Tk installée (au moins 8.4), vous pouvez également lancer un starkit directement avec tclsh ou wish ! Enfin, si vous ajoutez le répertoire Tclkit à votre PATH vous pouvez directement exécuter ./coucou.kit.

Contenu d'un starkit

Pour l'instant notre coucou.kit n'offre aucun intérêt par rapport à un script Tcl/Tk traditionnel. Par contre, dès lors que nous allons regrouper plusieurs fichiers à l'intérieur d'un starkit, la flexibilité de ce système par rapport aux scripts Tcl devient évidente. Pour ce faire, nous allons commencer par "dégrouper" coucou.kit avec la commande suivante :

 sdx unwrap coucou.kit

Ce qui va créer un répertoire coucou.vfs avec le contenu suivant :

      coucou.vfs/main.tcl

      coucou.vfs/lib/app-coucou/pkgIndex.tcl

      coucou.vfs/lib/app-coucou/coucou.tcl

Ce répertoire est en fait une réplique du système de fichier virtuel (d'où le .vfs) tel qu'il est organisé à l'intérieur de coucou.kit. Le fichier main.tcl est celui qui est automatiquement chargé lors de l'exécution du starkit. Pour l'instant, il contient ça :

 package require starkit
 starkit::startup
 package require app-coucou

Les deux premières lignes initialisent le starkit en chargeant toutes les bibliothèques nécessaires à son bon fonctionnement, la troisième charge notre application principale comme si elle était elle aussi une bibliothèque.

Effectivement, comme /lib/app-coucou/pkgIndex.tcl nous le montre, sdx a transformé notre coucou.tcl en "package" app-coucou 1.0 et, il a rajouté package provide app-coucou 1.0 au début de /app-coucou/coucou.tcl.

Ce principe sera toujours le même, quel que soit la complexité de ce que vous allez mettre dans votre starkit.

Ajouter une image dans un starkit

Nous allons commencer par rajouter l'image exemple.gif que nous utiliserons pour notre bouton. "La science, c'est classer" comme dit mon copain Dominique, donc nous allons placer cette image dans un nouveau sous-répertoire images créé dans coucou.vfs.

À l'intérieur d'un starkit, les fichiers sont accessibles relativement par rapport au répertoire racine (coucou.vfs dans notre exemple). Nous pouvons nous positionner par rapport à ce répertoire en utilisant la variable spéciale starkit::topdir. Ainsi, le chemin pour accéder à notre image sera : $starkit::topdir/images/exemple.gif.

Modifiez le fichier coucou.vfs/lib/app-coucou/coucou.tcl comme suit :

 package provide app-coucou 1.0
 package require Tk
 image create photo exemple -file $starkit::topdir/images/exemple.gif
 pack [button .b -image exemple -command "bell"]

Puis mettez votre starkit à jour avec la commande :

 sdx wrap coucou.kit

La réponse 7 updates applied vous indique que coucou.kit a été modifié, ce que vous pouvez constater en l'exécutant.

Ajouter un script tcl dans un starkit

Pour ajouter un script tcl, le principe est exactement le même. "La science, c'est classer" (bis) donc nous rajouterons tous les scripts tcl dans le répertoire app-coucou déjà existant. Ces scripts, qui seront chargés avec la commande source, sont accessibles avec le chemin $starkit::topdir/lib/app-coucou/nom_du_script.tcl.

Attention ! source nom_du_script.tcl ou ./source nom_du_script.tcl ne marcheront ni l'un ni l'autre ! Le chemin qui est indiqué dans ces commandes ne correspond pas à un répertoire à l'intérieur du sytème de fichier virtuel, mais au répertoire dans lequel est enregistré le starkit quand il est exécuté.

Ajouter une bibliothèque tcl dans un starkit

Attention ! par bibliothèque tcl j'entend une bibliothèque (ou package) qui n'est composée que de scripts tcl par opposition aux bibliothèques binaires (avec des .dll / .so etc..) dont il est question dans le paragraphe suivant.

Nous allons prendre comme premier exemple la bibliothèque base64 de la tcllib. Elle est composée d'un répertoire base64 comprenant 4 fichiers : pkgIndex.tcl, base64.tcl, uuencode.tcl et yencode.tcl.

Copiez ce répertoire et tous les fichiers qu'il contient dans coucou.vfs/lib/ et ... c'est tout ! En effet, dès lors que le fichier pkgIndex.tcl est écrit correctement (c'est à dire qu'il utilise la variable $dir pour indiquer les chemins d'accès), votre starkit pourra utiliser cette librairie avec un simple package require base64.

En copiant dans coucou.vfs/lib/ le répertoire tclib et tous ses sous-répertoires, nous aurons donc accès à toutes les bibliothèques qu'il contient : base64, calendar, cmdline, comm, control, etc..

L'immense avantage de cette technique c'est qu'elle vous permet de distribuer votre application en un seul fichier sans avoir à vous soucier de la présence et / ou de la version des bibliothèques qu'elle requiert. En outre, tant que vous n'utiliserez que des bibliothèques tcl, votre starkit fonctionnera sur toutes les plate-formes où tcl fonctionne sans avoir à changer la moindre ligne !

Ajouter une bibliothèque binaire dans un starkit

En principe, vous pouvez ajouter une bibliothèque binaire à votre starkit exactement de la même manière qu'on ajoute une bibliothèque tcl : on copie le répertoire contenant la bibliothèque dans lib et elle est disponible. Le problème, c'est que votre starkit ne fonctionnera maintenant que sur la plate-forme pour laquelle le binaire a été compilé.

Il est néanmoins possible de contourner partiellement ce problème avec l'astuce suivante :

Postulat :

Imaginons que vous ayez besoin de la librairie bidule 1.9 dans votre application. Cette librairie binaire existe pour linux et windows, dans le premier cas le répertoire bidule comprend les deux fichiers pkgIndex.tcl et bidule19.so et dans l'autre pkgIndex.tcl et bidule19.dll. Le contenu du fichier pkgIndex.tcl pour linux étant :

 # Tcl package index file, version 1.1
 # This file is generated by the "pkg_mkIndex" command
 # and sourced either when an application starts up or
 # by a "package unknown" script.  It invokes the
 # "package ifneeded" command to set up package-related
 # information so that packages will be loaded automatically
 # in response to "package require" commands.  When this
 # script is sourced, the variable $dir must contain the
 # full path name of this file's directory.
 package ifneeded bibule 1.9 [list load [file join $dir bidule19.so]]

Première étape :

Copiez le répertoire bidule de la version linux et tout ce qu'il contient dans lib. Copiez ensuite le fichier bidule19.dll de la version windows dans lib/bidule : vous avez donc maintenant trois fichiers : pkgIndex.tcl, bidule19.so et bidule19.dll.

Deuxième étape :

Éditez le fichier pkgIndex.tcl pour remplacer la dernière ligne par :

 package ifneeded bibule 1.9 [list load [file join $dir bidule19[info sharedlibextension]]]

Qu'est-ce qui va se passer ? La commande [info sharedlibextension] va systématiquement être remplacée par .so si vous êtes sous unix / linux et par .dll si vous êtes sous Windows. Ainsi, nous sommes certain que le bon binaire sera chargé par notre starkit quand il sera exécuté. Faites bien attention : tout ce qui précède le point doit être identique pour que cette astuce marche !

Bien entendu, même avec cette astuce votre starkit ne fonctionnera que sur les plate-formes pour lesquelles vous aurez ajouté la librairie binaire, mais c'est déjà mieux qu'une seule.

Du starkit au starpack

Un starpack est un starkit auquel on ajoute un interpréteur Tcl/Tk pour en faire une application autonome. De ce fait, à la différence du starkit, le starpack ne fonctionne que sur une plate-forme. Son grand avantage : il fonctionnera toujours partout puisqu'il contient tous les fichiers dont il dépend.

Un starpack est construit à partir du répertoire vfs créé par la commande sdx unwrap .... Pour créé un starpack, vous devez avoir le tclkit pour la plate-forme de destination (exemple : tclkit844-win32.exe pour fabriquer un starpack pour windows). Notez que vous pouvez créer un starpack pour n'importe quelle plate-forme, à partir de n'importe quelle plate-forme. Dans l'exemple ci-dessous, nous allons créer depuis linux (d'où le prompt host:~$) un starpack coucou pour linux :

 host:~$ sdx wrap coucou -runtime tclkit844-linux

et, toujours depuis linux, coucou.exe pour windows :

 host:~$ sdx wrap coucou.exe -runtime tclkit844-win32.exe

Une fois encore, la commande est très simple.

Personnaliser l'icone d'un starpack windows

Nous allons maintenant modifier l'icone de coucou.exe, histoire de personnaliser un peu notre création. Attention : sdx attend un icone avec les tailles 16x16, 32x32, 48x48 en 16 et 256 couleurs, soit 6 vues au total. Je vous conseille d'utiliser la méthode que j'explique ici : Gestion des icones pour fabriquer ces vues (en fait, je n'ai rien trouvé d'autre qui fonctionne). Une fois vos six vues créées, enregistrez votre icone en tclkit.ico à la racine du vfs (coucou.vfs/tclkit.ico dans notre exemple). On relance la commande de création du starpack (qui sert également pour le mettre à jour), ce qui doit donner la réponse suivante :

 host:~$ sdx wrap coucou.exe -runtime tclkit844-win32.exe
 customizing tclkit.ico in executable
 icon 32x32/16: replaced
 icon 16x16/16: replaced
 icon 32x32/256: replaced
 icon 48x48/256: replaced
 icon 48x48/16: replaced
 icon 16x16/256: replaced
 8 updates applied

Vous noterez avec joie que cet icone est utilisé pour votre exécutable dans l'explorateur, mais également dans la barre de titre, la barre de tâche, etc..

Une bibliothèque en starkit

Dans cet exemple nous n'allons pas créer un starkit à partir d'une application mais à partir d'une bibliothèque (package). Une fois ce starkit créé, il nous servira de "brique" pour développer d'autres applications sans avoir à nous préocuper de ce qui est installé sur l'ordinateur sur lequel nous travaillons.

Postulat

J'ai choisi comme exemple la librairie Tktable 2.7 que vous pouvez télécharger ici : http://sourceforge.net/project/showfiles.php?group_id=11464&release_id=116633 Vous aurez besoin de la version compilée pour linux (Tktable2.7-Linux-x86.tar.gz), de la version compilée pour mac (Tktable27.shlb.sit.bin) et de la version compilée pour windows (Tktable2.7-win32-x86.zip).

Chez moi, les binaires tclkit sont installés dans /usr/share/tclkit/ (c'est l'équivalent du répertoire Tclkit décrit au premier exercice) sdx et tclkit sont dans mon PATH et Tcl/Tk n'est pas installé. Pensez à adapter les commandes données en exemple en fonction de votre propre système.

Préparation des données

Commencez par créer un répertoire tktable.vfs contenant un sous-répertoire lib. Ce n'est pas une obligation mais je préfère suivre l'arborescence par défaut des starkits. Décompressez d'abord Tktable2.7-Linux-x86.tar.gz et déplacez Tktable.so.2.7 dans un nouveau sous-répertoire tktable.vfs/lib/Tktable, décompressez Tktable2.7-win32-x86.zip et déplacez Tktable.dll dans le même répertoire, enfin, décompressez Tktable27.shlb.sit.bin et déplacez aussi Tktable.shlb dans lib/Tktable.

Nous allons ensuite créer le fichier tktable.vfs/lib/Tktable/pkgIndex.tcl avec le contenu suivant :

 # Tcl package index file - handcrafted
 #
 global tcl_platform
 switch $tcl_platform(platform) {
     unix {
         package ifneeded Tktable 2.7 [list load [file join $dir Tktable.so.2.7] Tktable]
     }
     windows {
         package ifneeded Tktable 2.7 [list load [file join $dir Tktable.dll] Tktable]
     }
     macintosh {
         package ifneeded Tktable 2.7 [list load [file join $dir Tktable.shlb] Tktable]
     }
 }

Notez que cette fois je n'utilise pas [info sharedlibextension] mais il aurait été possible de la faire en adaptant les noms des fichiers librairies binaires.

Le dernier élément de notre starkit est le fichier tktable.vfs/main.tcl, pour ce que nous voulons faire, il est très sommaire :

 package require starkit
 starkit::startup

Construction du starkit

Nous utilisons la commande habituelle : sdx wrap tktable.kit. Le résultat est le fichier tktable.kit qui doit faire environ 206 ko.

Utilisation

La méthode la plus simple pour utiliser notre bibliothèque en kit consiste à la charger avec la commande tcl source :

source tktable.kit.

Il ne se passe rien puisque main.tcl ne contient aucune commande, mais maintenant notre librairie est accessible avec la commande :

package require Tktable

Nous pouvons le vérifier en rajoutant source tktable.kit au début du fichier demos/basic.tcl (livré avec tktable). Notre librairie se charge correctement, comme le prouve la capture d'écran ci-dessous :

L'autre manière consiste à éclater le kit avec sdx unwrap pour copier le contenu du répertoire lib dans le vfs de votre application.

Logiquement, il convient d'utiliser la première méthode pendant la phase de développement de votre application, et la deuxième lors de la phase de diffusion.

Avantages

Tout d'abord, cette méthode permet de n'avoir à gérer qu'un seul fichier pour trois plate-formes, ce qui rendra vos applications plus portables sans ré-écrire la moindre ligne, même quand elles utiliseront cette bibliothèque binaire. Mais c'est aussi un moyen bien pratique pour développer avec différentes versions d'un même package sans avoir à tout installer / désinstaller à chaque test (surtout quand vous n'êtes pas l'administrateur du système).


Quelques références :

Le site officiel de Tclkit : http://www.equi4.com/tclkit.html

Starkits et starpacks à essayer : http://www.tcl.tk/starkits/