I. Le langage D

D'après le site officiel Digital Mars , le D est un langage de programmation système. Walter Bright a créé ce langage afin d'allier la puissance du C et C++ à la simplicité et à la productivité de langage comme le C# et le Java.
Selon ses propos : "Si un langage peut récupérer 90 % de la puissance du C++ mais seulement 10 % de sa complexité, cela vaut largement le coup".
Le D est à la fois un langage de haut niveau et de bas niveau.

I-A. Langage de haut niveau

C'est un langage de haut niveau par le fait de la simplification du code par rapport au C++, des frameworks Phobos et Tango qui permettent un niveau d'abstraction important, et surtout parce que le langage intègre nativement un ramasse-miettes.
Le ramasse-miettes, comme en Java, permet de ne pas se préoccuper de la gestion de la mémoire et donc de simplifier les tâches d'écriture de code.

I-B. Langage de bas niveau

Cependant, le langage D est aussi considéré comme un langage de bas niveau car il autorise :

  • l'intégration de code assembleur, ce qui permettra de faire des optimisations importantes par rapport à l'architecture matérielle, mais rendra le code plus difficilement portable ;
  • la désactivation partielle ou totale du ramasse-miettes, ce qui autorise une gestion plus précise de la mémoire.

I-C. Autres particularités

Le D est un langage système compilé. Il supporte de nombreux styles de programmation : impératif, orienté objet, méta-programmation et la programmation par contrat. Sa syntaxe est très similaire à celle de C++.

Le D intègre aussi :

  • la gestion de test unitaire en natif ;
  • les modules ;
  • les fonctions anonymes ;
  • les structures de tableau ;
  • la surcharge d'opérateurs ;
  • la gestion des exceptions ;
  • la documentation style javadoc ;
  • les templates ;
  • l'interfaçage avec des bibliothèques écrites en C.

I-D. Le langage

I-D-1. Les types

I-D-1-a. Les types simples

Type Description Min Max
byte Valeur entière sur 1 octet (8 bits) -128 127
ubyte Valeur entière positive sur 1 octet (8 bits) 0 255
short Valeur entière sur 2 octets (16 bits) -32768 32767
ushort Valeur entière positive sur 2 octets (16 bits) 0 65535
int Valeur entière sur 4 octets (32 bits) -2147483648 2147483647
uint Valeur entière positive sur 4 octets (32 bits) 0 4294967296
long Valeur entière sur 8 octets (64 bits) -9223372036854775808 9223372036854775807
ulong Valeur entière positive sur 8 octets (64 bits) 0 18446744073709551616
float Valeur numérique sur 4 octets (32 bits) environ -3.4e38 environ 3.4e38
ifloat Valeur numérique imaginaire pure sur 4 octets (32 bits) environ -3.4e38i environ 3.4e38i
double Valeur numérique sur 8 octets (64 bits) -1.8e308 1.8e308
idouble Valeur numérique imaginaire pure sur 8 octets (64 bits) -1.8e308i 1.8e308i
real Le plus grand numérique supporté par le processeur soit 10 octets (80 bits) pour une architecture x86 environ -5.9e4436 (x86) environ 5.9e4436 (x86)
ireal Le plus grand numérique imaginaire supporté par le processeur soit 10 octets (80 bits) pour une architecture x86 environ -5.9e4436i (x86) environ 5.9e4436i (x86)
char Un caractère imprimable encodé en UTF-8 sur 1 octet (8 bits) 0 255
wchar Un caractère encodé en UTF-16 sur 2 octets (16 bits) 0 65535
dchar Un caractère encodé en UTF-32 sur 4 octets (32 bits) 0 4294967296

I-D-1-b. Les autres types

  • void : signifie aucun type.
  • bool : valeur booléenne true ou false.
  • pointer : c'est une variable qui contient l'adresse d'une autre variable.
  • tableaux : conteneur d'objets d'un même type.
  • tableaux associatifs : c'est un tableau particulier qui associe une clé (pas forcément un int) avec une valeur.
  • function : permet de définir un pointeur sur une fonction.
  • delegate : permet de déléguer l'appel à une fonction sur un objet.
  • alias : permet de définir un nom simple pour remplacer un type, un appel de fonction, la définition d'un pointeur de fonction...
  • enum : permet de définir un groupe de constantes.
  • struct/union : tout comme en C, les structures permettent de regrouper des variables au sein d'une même entité référencée par un seul nom de variable.
  • les génériques : permet l'écriture de codes dans lesquels certaines variables n'ont pas de type défini, utilisé dans le cadre des templates.

I-D-2. Commencer en D

Cette section expose quelques éléments de la structure du langage. L'objectif n'est pas de décrire toutes les particularités du langage car ce n'est pas le but de ce document.
Nous allons donc voir :

 

I-D-2-a. Point d'entrée

Pour pouvoir exécuter un programme il faut un point d'entrée. C'est le rôle de la méthode "main".
Exemple :

 
Sélectionnez

void main() {
  // le code ce trouve ici
}
						

Cette méthode peut s'écrire de plusieurs manières. Par exemple, elle peut prendre des paramètres et retourner une valeur :

 
Sélectionnez

int main(char[][] args) {
  // le code ce trouve ici
  return 0;
}
						
 

I-D-2-b. Déclaration d'une classe

L'exemple ci-dessous montre la déclaration d'une classe dont le nom est "MaClasse" et qui contient une méthode "unInt" qui retourne la valeur 3 :

 
Sélectionnez

class MaClasse {
  int unInt() { return 3; }
}

						
 

I-D-2-c. La notion de module

Un module correspond à un seul fichier source. Le nom du module est composé du chemin et du nom du fichier mais sans l'extension. Les modules peuvent être regroupés dans une même structure appelée "package". La déclaration se fait de la façon suivante :

 
Sélectionnez

module MonModule;
						

S'il se trouve dans un package :

 
Sélectionnez

module MonPackage.MonModule;
						

Pour utiliser un module dans un autre, il suffit d'utiliser le mot clé "import" comme suit :

 
Sélectionnez

module ModAinclure;
void methodeInc() {
  // Mon code
}
					
 
Sélectionnez

module ModQuiContient;
import ModAinclure;

void test() {
  methodeInc(); // appel de la méthode du module ModAinclure
}
					
 

I-D-2-d. Les tableaux

Les tableaux peuvent être déclarés et utilisés de la manière suivante :

 
Sélectionnez

// Déclaration dynamique de tableau
int[] tab1;
int tab1[];

// Déclaration static de tableaux
int[4][3] tab2;
int[4] tab2[3];
int tab2[3][4];

int* pointer; // déclaration d'un pointer
int[5] tab2;
int[] tab3

// Pointer pointe vers le premier élément de tab2
pointer = tab2;
// tab3 est initialisé pour pointer vers tab2
tab3 = tab2
						

Il est possible de découper un tableau pour pointer vers une tranche (Slicing) de celui-ci. Pour cela, il suffit d'utiliser le slice ".." :

 
Sélectionnez

int[10] tab1;
int[] tab2;

// tab2 va pointer vers les trois éléments tab1[1],tab1[2] et tab1[3]
tab2 = tab1[1..4];

int val;
tab1[3] = 5;
val = tab2[2] // val contient la valeur 5 
						

Si l'on souhaite tout simplement copier les éléments d'un tableau, il suffit d'utiliser "[]" ou le slice du côté droit de l'expression d'assignement.

 
Sélectionnez

char[6] str = "coucou";
char[6] cop;

// Copie tous les caractères (6) de str dans cop
cop[] = str;
cop[] = str[];

// Copie l'élément 0 ("c") du tableau str vers l'élément 1 du tableau cop. 
cop[1..2] = str[0..1]; // équivalant à la ligne suivante :
cop[1] = str[0];
// Copie les éléments 2 et 3 ("uc") du tableau str vers les éléments 0 et 1 du tableau cop.
cop[0..2] = str[2..4];	// équivalent aux deux lignes suivantes :
cop[0] = str[1];
cop[1] = str[2];
						

L'affectation dans un tableau peut se faire de plusieurs façons :

 
Sélectionnez

char[3] tab1;
char[6] tab2;

// Affectation de la valeur "a" dans tout le tableau tab1
tab1[] = 'a';
// ou 
tab1[0] = 'a';
tab1[1] = 'a';
tab1[2] = 'a';

//Affectation d'une partie du tableau
tab2[2..4] = 3; // en utilisant le slice 
// ou 
tab2[2] = 'a';
tab2[3] = 'a';
						

L'opérateur binaire ~ permet de concaténer deux tableaux. Il s'utilise comme suit :

 
Sélectionnez

char[] tab1 = "hello";
char[] tab2 = " world";
char[] conca;

conca = tab1 ~ tab2;
						
 

I-D-2-e. Les boucles

En D, il existe quatre types de boucles : le for, le while, le do et le foreach.
Dans le cadre des boucles for, while et do, il est possible d'utiliser les mots clés "break" et "continue". Ceux-ci permettent respectivement de sortir de la boucle et de passer directement à l'itération suivante. L'expression qui permet de boucler est de nature booléenne.
Le foreach quant à lui va boucler sur le contenu d'un agrégat, comme par exemple un tableau.

Le for :

 
Sélectionnez

for (int i = 0; i < 5; i++) {
  // mon traitement
}
						

Le while :

 
Sélectionnez

int i = 0;
while (i < 5) {
  // mon traitement
  i++;
}
						

Le do :

 
Sélectionnez

int i = 0;
do {
  // mon traitement
} while (++i < 5);
					

Le foreach :

 
Sélectionnez

char[] a;

foreach (int i, char c; a) {
  // mon traitement
}
					
 

I-D-2-f. Structure du if

L'instruction if permet de tester une condition et d'exécuter un traitement en fonction du résultat vrai ou faux.
Sa syntaxe est la suivante :

 
Sélectionnez

int val = 0;
...

if (val > 0) {
  // mon traitement si vrai
} else {
  // mon traitement si faux
}
					
 

I-D-2-g. Structure du switch

L'instruction switch permet de tester une condition et d'exécuter un ou plusieurs traitements en fonction du résultat et donc des cas correspondants.
Sa syntaxe est la suivante :

 
Sélectionnez

char[] nom;
...
switch (nom) {
 case "seb":
   // traitement
   break;
 case "laurence":
   // traitement
   break;
 ...
 default :
   // traitement
}
					
 

I-D-2-h. Les exceptions

Le mécanisme des exceptions en D est similaire à celui qui existe en Java. Il consiste à encadrer les instructions susceptibles de lancer des erreurs dans un bloc "try". Lorsqu'une erreur est lancée elle est captée par un bloc "catch" si elle correspond au type d'objet traité par celui-ci.
Sa syntaxe est la suivante :

 
Sélectionnez


try {
  // Traitement susceptible de lancer une exception;
} catch(Exception e) {
  // Traitement de l'erreur
}
					

Pour lancer ses propres exceptions, il suffit d'utiliser l'instruction throw :

 
Sélectionnez

throw new Exception("Problème de traitement");
					
 

I-D-2-i. Les templates

Les templates permettent la mise en place de codes génériques. Un template ressemble à une classe qui possède un ou plusieurs types génériques.
Par convention, on utilise généralement une lettre en majuscule pour définir le type générique.
Exemple de template :

 
Sélectionnez

template TCopy(T)
{
    void copy(out T to, T from)
    {
      to = from;
    }
}
					

Exemple d'utilisation du template :

 
Sélectionnez

int i;
TCopy!(int).copy(i, 3); // Notre type générique sera donc un int
					
 

I-D-2-j. Insertion de code assembleur

En D, il est en effet possible d'insérer du code assembleur grâce au bloc "asm".
Sa syntaxe est la suivante :

 
Sélectionnez


int foo(int x) {
  asm {
    mov EAX,x;
  }
}
					
 

I-D-2-k. Appel de fonctions C

Des fonctions C peuvent être appelées directement à partir du code écrit en D. Aucun wrapper n'est nécessaire et les fonctions n'ont pas besoin de se trouver dans une dll.
Il faut tout simplement déclarer et donner la convention d'appel de la fonction :

 
Sélectionnez

extern (C) int strcmp (char * str1, char * str2 );
					

Ensuite, il suffit de l'appeler de la façon suivante :

 
Sélectionnez

import std.string;

int comparer(char[] maChaine) {
  return strcmp(std.string.toStringz(maChaine), "Une chaîne");
}
					

Pour information, voici les équivalences entre les types D et les types C (pour les compilateurs 32 bits) :

Type D Type C
void void
byte signed char
ubyte unsigned char
char char
wchar wchar_t (quand sizeof(wchar_t) est 2)
dchar wchar_t (quand sizeof(wchar_t) est 4)
short short
ushort unsigned short
int int
uint unsigned
long long long
ulong unsigned long long
float float
double double
real long double
ifloat float _Imaginary
idouble double _Imaginary
ireal long double _Imaginary
cfloat float _Complex
cdouble double _Complex
creal long double _Complex
struct struct
union union
enum enum
class pas d'équivalent
type* type *
type[dim] type[dim]
type[dim]* type(*)[dim]
type[] pas d'équivalent
type[type] pas d'équivalent
type function(parameters) type(*)(parameters)
type delegate(parameters) pas d'équivalent

II. Installation de l'environnement

Dans le cas précis de ce document, l'installation se fera sur un Windows XP, mais la procédure est facilement adaptable à un Linux.
L'installation de notre environnement se divise en trois parties :

  • configuration de l'environnement de compilation ;
  • l'installation des librairies ;
  • l'installation de l'éditeur.

II-A. Configuration de l'environnement de compilation

II-A-1. Installation du compilateur

La version stable actuelle du compilateur est la 1.x, et c'est cette version qui sera installée dans ce tutorial.
Dans l'environnement cible, nous allons utiliser la librairie Tango (cette librairie est très utilisée dans les différents projets), même s'il en existe une autre qui est Phobos (livrée directement avec le compilateur dmd).
Tango est livrée avec le compilateur dmd et le linker, dans notre cas, les versions sont 0.99.7 pour Tango et 1.033 pour dmd. C'est cette version qui sera utilisée afin de garantir la compatibilité entre les différentes librairies.

Il faut donc :

  • récupérer le zip de Tango ;
  • décompresser le contenu dans un répertoire (par exemple : D:/compile) ;
  • pour plus de simplicité, renommer le répertoire tango-0.99.7-bin-win32-dmd.1.033 en « dmdt » ;
  • mettre le répertoire bin dans la variable d'environnement « path ».

Comme je l'ai précisé plus haut, le compilateur est livré dans l'archive de Tango. Par conséquent, le fichier de configuration du compilateur ("répertoire d'installation"/bin/sc.ini) est préconfiguré pour fonctionner avec la bibliothèque Tango.
Ce fichier de configuration contient :

  • LIB : la référence au répertoire contenant les bibliothèques qui seront recherchées par le linker ;
  • DFLAGS : les arguments qui seront envoyés au compilateur (dmd.exe) ;
  • LINKCMD : le linker utilisé par le compilateur.

Le %@P% que l'on peut voir dans les chemins sera remplacé par le compilateur avec le chemin du sc.ini. Si vous n'avez rien changé, ce chemin est : "répertoire d'installation"/bin.

Concernant le répertoire d'installation, il est conseillé d'avoir un chemin sans espace. Cependant, il semblerait que cela fonctionne si l'on utilise le nom DOS sur 8 caractères.
Notre fichier sc.ini pourrait s'écrire de la façon suivante (dans le cas d'une installation dans c:\program files\dmdt\) :

 
Sélectionnez

[Version] 
version=7.51 Build 020

[Environment] 
LIB="c:\progra~1\dmdt\lib" 
DFLAGS="-Ic:\progra~1\dmdt\import" -version=Tango -defaultlib=tango-base-dmd.lib -debuglib=tango-base-dmd.lib -L+tango-user-dmd.lib 
LINKCMD=c:\progra~1\dmdt\link.exe
					

Une petite précision est toutefois nécessaire sur l'installation du compilateur. D'après le site de digitalmars :

  • l'utilisation de la commande unzip de Cygwin peut être la cause de problèmes étranges ;
  • le lancement du compilateur en ligne de commande dans le shell Cygwin peut être la cause de problèmes ;
  • l'installation de dmd et dmc dans des répertoires contenant des espaces peut être la cause de problèmes.

Pour ceux que cela intéresse, le compilateur et le linker se trouvent sur le site de Digital Mars. Attention : la version doit être compatible avec le reste de l'installation.

II-A-2. Installation du debugger

L'éditeur, qui sera installé dans ce document, peut fonctionner avec deux debugger DDBG et GDB , il est possible que d'autres fonctionnent aussi mais l'auteur (de Descent) n'a testé que ces deux là.
Dans le cadre de ce tutorial, c'est DDBG qui a été retenu. L'installation de celui-ci se fait de la façon suivante :

  • récupérer les binaires sur le site du projet DDBG ;
  • décompresser le contenu ;
  • Copier le fichier ddbg.exe dans le répertoire dmdt/bin/.

II-A-3. Installation de l'outil DSSS

DSSS est un outil qui est destiné à créer un système normalisé pour la compilation, l'installation, la configuration, l'acquisition et l'utilisation de logiciels D.
Dans le cadre de ce document, il sera utilisé pour la compilation et pour l'installation de librairies.

L'installation de cet outil se fait de la façon suivante :

  • récupérer les binaires sur le site du projet DSSS ;
  • décompresser le contenu ;
  • ouvrir le fichier dsss/etc/rebuild/default et remplacer dmd-win par dmd-win-tango ;
  • ouvrir le fichier dsss/etc/rebuild/dmd-win-tango, rechercher "oneatatime" et remplacer sa valeur par "no". Attention, il y en a deux à changer ;
  • placer le répertoire bin dans la variable d'environnement « path ».

II-B. Installation des librairies

L'objectif ici n'est pas d'installer un environnement très complet, mais le minimum pour pouvoir travailler, soit une libraire graphique et une librairie d'accès aux bases de données.

II-B-1. Installation de la librairie graphique (DWT)

DWT est en fait un portage en D de la boite à outils SWT bien connue dans le monde Java.

La première étape est l'installation des librairies additionnelles :

  • récupérer le zip importlibs ;
  • décompresser le contenu dans le répertoire dmdt/lib créé lors de l'installation du compilateur.

Certaines librairies existent déjà dans le répertoire de destination dans une version plus récente. Il n'est donc pas nécessaire de remplacer toutes celles qui s'y trouvent.
En revanche, il est absolument obligatoire d'écraser les versions de user32.lib et kernel32.lib avec celle du zip. Sinon l'on s'expose à un message du genre :

 
Sélectionnez

OPTLINK (R) for Win32  Release 8.00.1
Copyright (C) Digital Mars 1989-2004  All rights reserved.
dsss_objs\D\dwt-widgets-Display.obj(dwt-widgets-Display)
 Error 42: Symbol Undefined _IsHungAppWindow@4
dsss_objs\D\dwt-internal-win32-OS.obj(dwt-internal-win32-OS)
 Error 42: Symbol Undefined _GetSystemDefaultUILanguage@0


La deuxième étape est la compilation et l'installation de DWT :

  • récupérer la dernière version de DWT ;
  • décompresser le contenu ;
  • lancer une console DOS ;
  • se positionner dans le répertoire dwt-win ;
  • lancer la commande "dsss build" (pas d'inquiétude, c'est très long) ;
  • lancer la commande "dsss install".

II-B-2. Installation de la librairie base de données (DDBI)

DDBI est une librairie qui permet d'effectuer des accès à quelques bases de données et aussi d'utiliser ODBC.
Pour le moment, elle permet l'accès aux bases suivantes :

  • MS SQL Server et Sybase ;
  • MySQL ;
  • PostgreSQL ;
  • SQLite 3.

Pour notre installation, nous utiliserons sqlite 3 comme base de données.

Les préparatifs pour sqlite 3 :

  • récupérer la librairie (sqlitedll-x.zip) SQLite 3 ;
  • décompresser le contenu ;
  • récupérer le Basic Utilities ;
  • décompresser le contenu ;
  • transformer la dll sqlite 3 avec implib.exe : "implib /s sqlite.lib sqlite3.dll" ;
  • copier la dll obtenue dans le répertoire dmdt/lib créé lors de l'installation du compilateur.

Il ne reste plus qu'à compiler et installer DDBI :

  • récupérer les sources de DDBI ;
  • décompresser le contenu ;
  • lancer une console DOS ;
  • se positionner dans le répertoire 0.2.9 ;
  • lancer la commande "dsss build -version=dbi_sqlite" ;
  • lancer la commande "dsss install".


Une information qui peut être utile : il existe une extension firefox " SQLite Manager " pour manager les bases sqlite

II-C. Installation de l'éditeur

Venant du monde Java, je me suis tout naturellement tourné vers l'éditeur Eclipse et le plugin Descent dédié au D.
Cependant il existe plusieurs autres éditeurs dont voila quelques exemples :

  • poseidon : éditeur écrit en D (Windows) ;
  • D-IDE : Windows seulement ;
  • DCode : éditeur simple avec la coloration syntaxique ;
  • Vim : propose la coloration syntaxique avec d.vim ;
  • SciTE : en ajoutant le plugin seatd ;
  • Kate : en ajoutant le plugin seatd ;
  • zeus : uniquement pour Windows ;
  • Visual D : une intégration de D dans Visual Studio.

Pour ceux qui ne souhaitent pas installer Eclipse et Descent, votre parcours peut s'arrêter ici.

Nous allons maintenant voir comment installer notre environnement.
L'installation de Descent se fait en deux temps :

  • installation d'Eclipse ;
  • installation du plugin Descent.

Pour ceux qui possèdent déjà une installation d'Eclipse, vous pouvez directement passer à l'installation de Descent .

II-C-1. Installation d'Eclipse

Je ne vais pas m'attarder sur l'installation d'Eclipse, car il existe des tutoriels sur le forum qui vous expliqueront bien mieux que moi comment le faire.
Vous devez donc installer, si vous souhaitez faire du Java et du D, le JDK (Java Development Kit) sinon le JRE (Java Runtime Environment) et un environnement Eclipse.

Le JRE est peut être déjà installé sur votre environnement. Pour le vérifier, il suffit d'exécuter la commande DOS suivante : "java -version".
L'installation est automatique, il suffit simplement de suivre les instructions de l'installeur.
Pour Eclipse, pas la peine de prendre une distribution super complète, les suivantes suffiront amplement :

  • Eclipse IDE for Java Developers ;
  • Eclipse for PHP Developers ;
  • Eclipse IDE for C/C++ Developers.


Pour son installation, il suffit simplement de décompresser le fichier téléchargé.
Pour le démarrer, il suffit de lancer eclipse.exe.

 

II-C-2. Installation du plugin Eclipse Descent

Il faut commencer par lancer Eclipse. Lancer l'installation d'un nouveau plugin via le menu "Help / Install new software..."

Image non disponible


Cliquez ensuite sur le bouton "Add..." pour ajouter le site de Descent

Image non disponible


Donnez un nom, celui-ci vous permettra de retrouver facilement le site en cas de besoin. Saisissez l'URL (http://downloads.dsource.org/projects/descent/update-site) du site et terminez par un clic sur le bouton "Ok"

Image non disponible


Maintenant que le site est saisi, sélectionnez la version de Descent à installer et validez en cliquant sur "Next".

Image non disponible


L'installeur recherche alors les dépendances nécessaires (cela peut prendre quelques minutes). Ensuite un récapitulatif apparait, valider en cliquant sur "Next".

Image non disponible


Un récapitulatif des plugins nécessitant une licence d'utilisation apparait, vous devez accepter la licence afin de pouvoir continuer. Valider ensuite en cliquant sur "Finish".

Image non disponible


L'installeur va ensuite télécharger tous les paquets et les installer. Cette action peut être très longue.

Image non disponible


L'installation est enfin terminée. L'installeur vous demande si vous souhaitez redémarrer Eclipse afin de prendre en compte les modifications apportées. Validez en cliquant sur "yes".

Image non disponible


Avant d'aller plus loin, quelques explications sur la structure de l'interface d'Eclipse sont nécessaires.

Image non disponible
  1. Permet de changer de perspective. La perspective regroupe un ensemble d'éléments visuels (par exemple les différentes vues) ou non (exemple : le compilateur de la perspective java).
    Le bouton Image non disponible ouvre un menu donnant accès à toutes les perspectives.
  2. Bouton permettant d'ouvrir d'autres vues (le 3,5 et 6 sont des vues).
  3. La vue projet, qui permet de voir les fichiers des projets en cours.
  4. L'éditeur de fichier, un onglet est ouvert pour chaque fichier en cours d'édition.
  5. La vue outline, elle montre la structure du fichier en cours d'édition. Un clic sur un élément permet de se positionner sur cet élément dans l'éditeur.
  6. La console de sortie, elle affiche les informations de compilation ou lors de l'exécution d'un programme (sortie standard et erreur).

II-C-3. Configuration de Descent

Ce chapitre explique comment mettre en place la configuration générale de Descent qui sera donc identique pour tous les projets.
L'objectif n'est pas de vous expliquer toutes les options de paramétrage de Descent, mais de configurer ce qui est nécessaire au bon fonctionnement de celui-ci.

Il faut donc configurer :

  • le chemin de compilation ;
  • le debugger.

II-C-3-a. Le chemin de compilation

Pour configurer le chemin de compilation, il faut ouvrir la fenêtre des préférences via le menu "Window / Preferences".
Il faut ajouter les références de nos différentes libraires et plus précisément le ou les répertoires où se trouvent les fichiers ".di". Cela permettra à l'éditeur de faire des propositions pour la complétion.

Pour ajouter une librairie, vous définissez le nœud racine (un nom quelconque, par exemple "standardLibs") en cliquant sur "New...". Ensuite vous ajoutez le répertoire en cliquant sur "Add Directory...".
Au final, vous devez obtenir le résultat ci-dessous :

Image non disponible

II-C-3-b. Le debugger

La configuration du debugger est relativement simple puisqu'il suffit de donner le chemin vers l'exécutable dans la section "debug" des préférences pour le langage D.

Image non disponible

III. Mon premier projet

Votre environnement est totalement configuré et vous allez donc pouvoir vous lancer pleinement dans votre premier programme écrit en D. Nous allons commencer par créer et configurer un projet, ensuite nous pourrons créer, compiler et exécuter un programme et nous ajouterons deux modules afin de tester les librairies DWT et DDBI. Pour finir, nous lancerons un programme en mode debug.

III-A. La création et la configuration d'un projet

Le menu "File / New / Project..." permet de choisir quel type de projet vous souhaitez créer. Il suffit d'étendre le nœud "D", de sélectionner "D project" et de valider avec le bouton "Next >".

Image non disponible

Vous pouvez alors saisir le nom de votre projet et validez en cliquant sur le bouton "Next >".

Image non disponible

La boite de dialogue ci-dessous est composée de trois onglets :

  • Source : permet l'ajout des répertoires de source en cliquant sur "Create new source folder" ou sur l'icône correspondante et aussi définir le répertoire de sortie de la compilation (Default Output Folder) ;
  • Projects : permet d'adjoindre les projets dont dépend votre projet ;
  • Include Path : permet de définir les librairies nécessaires au bon fonctionnement du projet.
Image non disponible

Sélectionnez les librairies que l'on a ajoutées dans les préférences afin qu'elles soient disponibles dans votre projet.
Un clic sur le bouton "Add Library...", l'éditeur vous propose alors de choisir les librairies à ajouter.

Image non disponible

Vous validez la configuration en cliquant sur le bouton "Finish", si toutefois vous n'avez pas déjà activé la perspective D, l'éditeur vous le propose. Acceptez en cliquant sur yes.
Votre projet est maintenant créé, vous allez pouvoir mettre en place votre premier module.

III-B. La création, compilation et exécution d'un programme

III-B-1. Création d'un module

Avant de créer votre module, vous pouvez créer un package qui va permettre de mieux organiser les sources. Un clic droit dans la vue "Project", puis sélectionnez dans le menu popup "New / Package".

Image non disponible

Vous pouvez alors saisir le nom ou la hiérarchie (cas avec un ou plusieurs sous répertoires, exemple : "com.prog") de votre package. Ensuite validez avec le bouton "Finish".

Image non disponible

Ajoutez un nouveau module via le menu popup "New / Module" en effectuant un clic droit dans la vue "Project".

Image non disponible

Donnez le nom de module et sélectionnez le package où doit être ajouté votre module. Ensuite validez avec le bouton "Finish".

Image non disponible

Votre module est maintenant créé, l'éditeur l'a ouvert dans un nouvel onglet. Ajoutez le code suivant au contenu déjà existant :

 
Sélectionnez

import tango.io.Stdout;

void main() {
    Stdout("Hello world !");
}

Bravo ! Vous avez écrit votre premier programme en D.

III-B-2. Compilation d'un module

Vous avez écrit votre module, il faut maintenant le compiler. L'éditeur Descent ne contient pas un "builder" valide (il est en cours de développement), c'est pourquoi vous allez utiliser DSSS.
Vous devez créer un nouveau fichier (dans la vue projet, popup menu "New / File") dans le répertoire source (src). Nommez le fichier dsss.conf puis validez en cliquant sur le bouton "Finish".

L'éditeur ouvre alors le fichier dans un nouvel onglet. Il suffit d'y placer le texte suivant :

 
Sélectionnez

# Section de compilation
[com/prog/MonPremProg.d]
# nom du fichier exe cible
target=../bin/hello

Votre fichier de compilation est prêt. Pour pouvoir utiliser DSSS au sein d'Eclipse (ce qui est tout de même plus pratique que de lancer une console DOS), vous devez configurer un "external tools". Exécutez la commande "external tools configuration" soit par la barre de boutons, soit par le menu "Run / External tools".

Image non disponible

Demandez la création d'une nouvelle configuration via un clic droit sur "Program" dans l'arbre à gauche puis sur "New".

Image non disponible

Vous devez donner un nom, l'exécutable à lancer (dans notre cas c'est DSSS), le répertoire d'exécution (le répertoire src du projet "${project_loc}/src") et les arguments "build --debug -g".
Les arguments indiquent à DSSS qu'il faut lancer la compilation en mode debug. Si toutefois vous souhaitez compiler sans le mode debug, il vous suffira de créer une nouvelle configuration en remplaçant "build --debug -g" par "build".

Image non disponible

Afin que vous puissiez voir votre exécutable dans le dossier "bin", vous devez aller dans l'onglet "Refresh". Il faut cocher la case "Refresh resources upon completion" puis sélectionner "The project containing the selected resource". Vous pouvez alors tester la compilation en cliquant sur le bouton "Run".

Image non disponible


Dans votre console, vous pouvez constater que l'exécution s'est bien passée :

Image non disponible

Pour faciliter la compilation, vous allez ajouter votre "external tool" en tant que "builder" de votre projet.
Pour cela, ouvrez les propriétés de votre projet en faisant un clic droit sur la racine du projet, puis cliquez sur "Properties".

Image non disponible

Dans la section "Builders" décochez "D Builder", ensuite cliquez sur le bouton "Import...", sélectionnez votre "External tool" et validez en cliquant sur "OK". Pour finir, validez les propriétés en cliquant sur le bouton "OK".

Image non disponible

Par défaut, l'éditeur lance la sauvegarde lors de l'enregistrement d'un fichier source. Étant donné que DSSS est un outil externe, il ne fait pas de la compilation incrémentale. Conclusion : à chaque enregistrement, il compilera l'ensemble de votre projet et cela peut vite devenir coûteux.

Je vous conseille donc de désactiver la compilation automatique en décochant l'action "Build Automatically". Vous pourrez compiler via le menu "Project / Build All" ou en faisant un "CTRL + B".

Image non disponible

III-B-3. Exécution d'un programme

Votre programme est maintenant créé et compilé, vous voulez donc l'exécuter... mais où est donc l'exécutable ?
La vue projet ne permet pas de le voir. Le plus simple est d'aller dans la vue "Navigator" ou vous pourrez voir votre répertoire bin.

Image non disponible

Sélectionnez votre fichier exe et lancez l'exécution via la barre de boutons à l'aide du menu "Run As / D Application".

Image non disponible

En regardant la console, vous pourrez constater l'exécution du programme.

Image non disponible

III-C. Test des librairies DWT et DDBI

Le but de cette section est de vérifier que les librairies sont bien installées et utilisables. Nous commencerons par écrire un module avec DWT et nous finirons par un exemple d'accès à une base Sqlite.

III-C-1. DWT - librairie graphique

Pour votre première application DWT, vous allez faire l'équivalent graphique de ce bon vieux "Hello World".

Commencez par créer un nouveau module "HelloWin.d" dans le même package que "MonPremProg.d" et collez le code suivant :

 
Sélectionnez

module com.prog.HelloWin;

import dwt.DWT;
import dwt.widgets.Shell;
import dwt.widgets.Text;
import dwt.widgets.Display;

void main() {
	Display display = new Display ();
	Shell shell = new Shell(display);
	
	Text hellotxt = new Text(shell, DWT.NONE);
	hellotxt.setText("Hello World !");
	hellotxt.pack();
	
	shell.pack();
	shell.open ();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}
	display.dispose ();
}

Dans le répertoire des sources de dwt, copiez le fichier dwt.res et placez-le dans le répertoire src du projet (le répertoire de compilation).
Modifiez le fichier dsss.conf de la manière suivante :

 
Sélectionnez

# Section de compilation
[com/prog/MonPremProg.d]
# nom du fichier exe cible
target=../bin/hello

[com/prog/HelloWin.d]
target=../bin/helloWin
# permet de masquer la console DOS lors de l'exécution du programme compilé
buildflags += -L/SUBSYSTEM:windows:5
# Necéssaire pour le theme windows (dwt.res)
buildflags += -L/rc:dwt;

Dans le cas où vous omettriez de rajouter les "buildFlags" vous seriez confronté à l'erreur suivante :

 
Sélectionnez

CreateActCtx failed, hence theme support will not be available
Please check for:
 - missing link option -L/su:windows:5 or -L/su:console:5
 - missing link option -L/rc:dwt
 - resource file 'dwt.res' was not accessible by linker
: Le fichier image spécifié ne contenait pas de section ressource.

Vous remarquerez que nous avons dans notre dsss.conf plusieurs sections, ce qui nous permettra d'avoir plusieurs exécutables. Si nous avions un module référençant plusieurs autres modules, il suffirait de mettre notre module racine pour que tous soient compilés.

Maintenant, lancez la compilation et l'exécution du programme, vous obtenez alors votre nouveau "Hello World"

Image non disponible

III-C-2. DDBI - Accès aux données

Pour votre dernier test, vous allez créer un nouveau module "DbProg.d" et y coller le code suivant :

 
Sélectionnez

module com.prog.DbProg;

import tango.io.Stdout;
import dbi.Row;
import dbi.sqlite.SqliteDatabase;

void main() {
    SqliteDatabase db = new SqliteDatabase();
    db.connect("test.db");

    Row[] rows = db.queryFetchAll("SELECT * FROM sqlite_master");
    foreach (Row row; rows) {
        Stdout("name:")(row["name"]).newline();
    }

    db.close();
}

Complétez ensuite votre dsss.conf :

 
Sélectionnez

[com/prog/MonPremProg.d]
target=../bin/hello

[com/prog/HelloWin.d]
target=../bin/helloWin
buildflags += -L/SUBSYSTEM:windows:5
buildflags += -L/rc:dwt;

[com/prog/DbProg.d]
target=../bin/DbAcc
# Permet de compiler avec un accès pour sqlite
buildflags += -Lsqlite -version=dbi_sqlite

Compilez le nouveau module et exécutez-le. Vous n'obtenez rien dans la console ? C'est que le test a fonctionné.
Lors du test, la base "test.db" a été créée (à la racine du projet), mais comme elle ne contient aucune table, la table "sqlite_master" est vide.

III-D. Le débogage d'un programme

Nous approchons bientôt de la fin de ce document, mais avant cela, certains aimeraient sûrement savoir comment debugger un module dans cet environnement.

Vous devez commencer par mettre un point d'arrêt dans le module souhaité, pour cela double cliquez dans la marge de gauche. Vous devez voir apparaître un "petit rond bleu".

Image non disponible

Votre module doit bien sûr être compilé en mode debug.
Tous est prêt, vous pouvez lancer votre module en debug, pour cela ouvrez le menu debug de la barre de boutons et cliquez sur l'exécutable.

Image non disponible

L'éditeur vous demande alors si vous souhaitez changer pour la perspective debug, confirmez en cliquant sur le bouton "Yes".

Image non disponible
  1. Dans la vue debug, vous pouvez voir la pile d'exécution.
  2. D'autres vues permettent de voir les variables, les points d'arrêts, les registres et de monitorer la mémoire.
  3. Dans l'éditeur, vous pouvez visualiser l'endroit où vous êtes en pause.
  4. La barre d'outil de la vue debug permet de faire du pas à pas, de relâcher l'exécution, d'arrêter le programme...

IV. Conclusion

Ce document est maintenant terminé, j'espère qu'il vous aura apporté une aide précieuse dans la mise en place de votre environnement.

IV-A. Quelques liens utiles

IV-B. Remerciements

Merci à spiceguid , Ricky81 , Hédhili Jaïdane , jacques_jean et à gorgonite pour leur relecture attentive de cet article.