Débuter avec le langage D

Sébastien Tahier

Vous désirez apprendre le Langage D ? Vous ne savez pas comment préparer votre environnement ? Ce guide va vous aider à configurer un environnement de développement, vous permettant ainsi de vous concentrer sur le langage.

Commentez

- Titre : Débuter avec le langage D

- Auteur : Sébastien Tahier

- Parution : 15 mai 2010

- Mise à jour : 15 mars 2020

- Licence : Copyright ® 2010 Sébastien Tahier. 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

- I. Le langage D

- I-A. Langage de haut niveau

- I-B. Langage de bas niveau

- I-C. Autres particularités

- I-D. Le langage

- I-D-1. Les types

- I-D-1-a. Les types simples

- I-D-1-b. Les autres types

- I-D-2. Commencer en D

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

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

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

- I-D-2-d. Les tableaux

- I-D-2-e. Les boucles

- I-D-2-f. Structure du if

- I-D-2-g. Structure du switch

- I-D-2-h. Les exceptions

- I-D-2-i. Les templates

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

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

- II. Installation de l'environnement

- II-A. Configuration de l'environnement de compilation

- II-A-1. Installation du compilateur

- II-A-2. Installation du débogueur

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

- II-B. Installation des bibliothèques

- II-B-1. Installation de la bibliothèque graphique (DWT)

- II-B-2. Installation de la bibliothèque base de données (DDBI)

- II-C. Installation de l'éditeur

- II-C-1. Installation d'Eclipse

- II-C-2. Installation du plugin Eclipse Descent

- II-C-3. Configuration de Descent

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

- II-C-3-b. Le débogueur

- III. Mon premier projet

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

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

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

- III-B-2. Compilation d'un module

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

- III-C. Test des bibliothèques DWT et DDBI

- III-C-1. DWT - bibliothèque graphique

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

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

- IV. Conclusion

- IV-A. Quelques liens utiles

- IV-B. Remerciements

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étaprogrammation 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 :

- Le point d'entrée d'un programme

- La classe

- Les modules

- Les tableaux

- Les boucles

- Structure du if

- Structure du switch

- Les exceptions

- Les templates

- Insertion de code assembleur

- Appel de fonctions C

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 :

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 :

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 :

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 :

module MonModule;

S'il se trouve dans un package :

module MonPackage.MonModule;

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

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

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 :

// 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 « .. » :

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.

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 :

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 :

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, par exemple un tableau.

Le for :

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

Le while :

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

Le do :

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

Le foreach :

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 :

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 :

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 :

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 :

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 :

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

Exemple d'utilisation du template :

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 :

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 :

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

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

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 bibliothèques ;

- 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 tutoriel.
Dans l'environnement cible, nous allons utiliser la bibliothèque Tango (cette bibliothèque 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 bibliothèques.

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\) :

[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 débogueur

L'éditeur, qui sera installé dans ce document, peut fonctionner avec deux débogueurs 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 tutoriel, 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 bibliothèques.

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 bibliothèques

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

II-B-1 - Installation de la bibliothèque 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 bibliothèques 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 bibliothèques 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 :

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 bibliothèque base de données (DDBI)

DDBI est une bibliothèque 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 bibliothèque (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 voici 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 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 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… »

Cliquez ensuite sur le bouton « Add… » pour ajouter le site de Descent

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 »

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

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

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

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

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 ».

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

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 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 débogueur.

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 bibliothèques 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 bibliothèque, 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… ».
Finalement, vous devez obtenir le résultat ci-dessous :

II-C-3-b - Le débogueur

La configuration du débogueur 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.

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 bibliothèques 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 > ».

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

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 bibliothèques nécessaires au bon fonctionnement du projet.

Sélectionnez les bibliothèques 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 bibliothèques à ajouter.

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 ».

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 ».

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

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

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

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 :

# 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 ».

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

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 ».

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 ».

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

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 ».

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 ».

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 ».

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.

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

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

III-C - Test des bibliothèques DWT et DDBI

Le but de cette section est de vérifier que les bibliothèques 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 - bibliothèque 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 :

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 :

# 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
# Nécéssaire pour le thème windows (dwt.res)
buildflags += -L/rc:dwt;

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

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 »

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 :

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 :

[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 déboguer 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 apparaitre un « petit rond bleu ».

Votre module doit bien sûr être compilé en mode debug.
Tout 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.

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

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'outils 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

Voici une liste de liens qui pourraient vous être utiles, si vous souhaitez approfondir certains sujets :

- Le site officiel : Digital Mars

- Communauté open source du langage D

- Le site officiel de la communauté

- La bibliothèque Tango

- Portage de SWT pour le D (DWT)

- API d'accès aux données (DDBI)

- DSSS

- Plugin Eclipse pour le D

- Passage de Java à D

- Tutorials de DSource

- Tutorials de dProgramming

IV-B - Remerciements

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