Macros and Conditionals/fr

From Free Pascal wiki

English (en) français (fr)

Généralité

Des macros peuvent être utilisées dans les chemins de recherche et les noms de fichier pour laisser l'EDI les adapter à la plate-forme cible. Les macros de construction sont des macros spécifiques au projet/paquet. Elles ne sont pas passées au compilateur. Un exemple important est la LCLWidgetType, laquelle est définie dans le paquet LCL et permet de choisir le jeu de widgets (carbon, gtk, qt, win32, wince, ...).

Les conditionnelles sont des règles permettant de mettre des macros dépendantes de la palte-forme cible et/ou d'autres macros. Par exemple, vous pouvez les utiliser pour définir des options spéciales de l'éditeur de lien pour Mac OS X. Elle utilisent un langage de script comme Pascal pour définir des règles complexes.

Vous pouvez définir les macros de construction via Project / Project Options / Compiler Options / Additions and Overrides (en)

Vous pouvez faire des conditionnelles via Projet / Options du projet / Options du compilateur / Options personnalisées.

Les macros de construction et les conditionnelles existent depuis Lazarus 0.9.29.

CompilerAdditionsAndOverrides1.png

Conditionnelles

Les expressions conditionnelles utilisent un langage de scripting simple.

Changement des options du compilateur avec les expressions conditionnelles

Le script de conditionnelles peut définir certaines variables dont les valeurs sont utilisées par l'EDI pour les options du compilateur :

  • UnitPath: ajouté en fin de Autres fichiers sources (-Fu). Les caractères / et \ sont automatiquement convertis vers le séparateur de chemin courant. Après avoir ajouté le(s) chemin(s) de recherche) avec un point-virgule, les macros sont remplacées et les chemins relatifs sont expansés par le chemin d'accès du projet/paquet.
  • IncPath: ajouté en fin de Fichiers d'inclusion (-Fi).
  • LibraryPath: ajouté en fin de Bibliothèques (-Fl).
  • SrcPath: ajouté en fin de Autres sources (non utilisé par le compilateur, uniquement par l'EDI).
  • DebugPath: ajouté en fin de Ajout de chemin du débogueur (non utilisé par le compilateur ni par les outils de code, seulement par le débogueur)
  • LinkerOptions: ajouté en fin des options de l'éditeur de liens (-k). Les délimiteurs de chemin ne sont pas changés. Les chemins relatifs ne sont pas expansés. Les macros sont remplacées.
  • CustomOptions: ajouté en fin des paramètres du compilateur. Les délimiteurs de chemin ne sont pas changés. Les chemins relatifs ne sont pas expansés. Les macros sont remplacées.
  • OutputDir: si défini, il remplacera le dossier de sortie courant. Les délimiteurs de chemin sont changés. Les chemins relatifs sont expansés. Les macros sont remplacées.

Pour les paquets, il y a plus de variables pour les options d'usage. Ces chemins sont hérités, cela signifie qu'ils sont ajoutés à tous les paquets/projets utilisant ce paquet, directement ou non :

  • UsageUnitPath : ajouté en fin du chemin d'usage Unité (-Fu). Les caractères / et \ sont automatiquement convertis dans le séparateur de chemin actuel. Après avoir ajouté le(s) chemin(s) de recherche) avec un point-virgule, les macros sont remplacées et les chemins relatifs sont expansés par le chemin d'accès du projet/paquet.
  • UsageIncPath : ajouté en fin du chemin d'usage Inclusion (-Fi).
  • UsageLibraryPath : ajouté en fin du chemin d'usage Bibliothèque (-Fl).
  • UsageSrcPath  : ajouté en fin du chemin d'usage Source (pas utilisé par le compilateur, seulement l'EDI).
  • UsageDebugPath : ajouté en fin du chemin d'usage Débogueur (pas utilisé par le compilateur, ni par les outils de code, utilisé seulement par le débogueur).
  • UsageLinkerOptions : ajouté en fin des options de l'éditeur de liens (-k). Les délimiteurs de chemin ne sont pas changés. Les chemins relatifs ne sont pas expansés. Les macros sont remplacées.
  • UsageCustomOptions : ajouté en fin des paramètres d'usage du compilateur. Les délimiteurs de chemin ne sont pas changés. Les chemins relatifs ne sont pas expansés.

Syntaxe des expressions conditionnelles

Constructions de syntaxe supportées

  • If expression then instruction;
  • If expression then instruction else instruction;
  • begin instruction; ... instruction; end;
  • Variable:=expression;
  • Variable+=expression;
  • Commentaires //, { }, (* *)
  • Espaces, tabulations et saut de ligne sont les mêmes. Comme en Pascal, ils ne sont requis que pour séparer deux identificateurs/mots-clés.

Variables

Les variables sont définies simplement en assignant une valeur. Il y a des variables prédéfinies. Voir ci-dessous pour une liste.

Les variables peuvent être définies ou indéfinies :

if defined(Name) then ...
if undefined(Name) then ...
undefine(Name);

Si une variables est définie, elle peut avoir l'un de ces trois types :

  • aucun
  • chaîne de caractères
  • numérique (int64)

Une variable est false si elle prend la valeur numérique 0 ou chaîne '0'. Sinon, elle vaut true. Cela signifie qu'une variable sans valeur est vraie tout comme une variable indéfinie.

Vous pouvez changer le type d'une variable avec :

a:='1'; // string
a:=integer(a); // convertit vers un nombre en utilisant StrToInt(), en cas d'échec, la variable demeure une chaîne
a:=int64(a); // convertit vers un nombre en utilisant StrToInt64(), en cas d'échec, la variable demeure une chaîne
a:=string(a); // convertit vers une chaîne

Constantes

a:=1234; // decimal
a:=$A1B; // hexadecimal
a:=&127; // octal
a:=%101; // binary
a:='10'; // string
a:=#123; // character

Opérateurs

  • + : Deux nombres sont ajoutés, sinon ils sont traités comme une chaîne et concaténés.
  • <, >, <=, >=, =, <> : Deux nombres sont comparés mathématiquement, sinon ils sont traités comme des chaînes et comparés lexicographiquement (sensible à la casse).
  • not : opérateur booléen unaire.
  • and, or, xor : Opérateurs booléens.
  • (,) : operations de groupe.
  • := : Affectation. Pas permis dans les expressions (désolé, c'est pas du langage C).
  • += : Ajout et affectation. Pas permis dans les expressions.

Niveaux de précédence:

  • 1 Not et - (moins unaire)
  • 1 And
  • 2 Or
  • 2 XOr
  • 2 +
  • 4 =
  • 4 <>
  • 4 <
  • 4 <=
  • 4 >
  • 4 >=

Variables prédéfinies

Avant que le script d'expressions conditionnelles ne soit exécuté, l'EDI initialise quelques variables :

  • TargetOS : le système d'exploitation cible comme défini par fpc p.ex. 'linux', 'win32', 'darwin', 'freebsd', 'wince'.
  • TargetCPU: le processeur cible du projet comme défini par fpc p.exe. 'i386', 'x86_64', 'arm'.
  • SrcOS: la valeur 'win' pour toute plate-forme MS Windows et 'unix' pour toutes les plate-formes unixiennes. La valeur dépend de TargetOS.
  • SrcOS2: la valeur 'bsd' pour toutes les plates-formes BSD-iennes. La valeur dépend de TargetOS.
  • True : valeur 1
  • False : valeur 0
  • toutes les macros de construction définies par le projet en cours.
  • Toutes les macros de construction définies par les paquets utilisés. Cela signifie que si le projet n'a pas défini une valeur pour une macro du paquet, la valeur de la conditionnelle du paquet utilisé sera utilisée.

Fonction prédéfinies

  • Defined(Variable) : retourne 1 (vrai) si la variable est définie et 0 (faux) sinon. Exemple if Defined(Macro1) then ;
  • Undefine(Variable) : annule la définition de la variable. Exemple: Undefine(A);
  • Int64(expression) : Retourne la valeur Int64 de l'expression. Exemple: i:=int64('3');
  • Integer(expression) : Retourne la valeur entière d'une expression. Exemple: i:=integer('3');
  • String(expression) : Retourne la valeur chaîne d'une expression. Exemple: s:=string(3);
  • GetIDEValue(string) : Voir Macros EDI (en).
    • GetIDEValue('OS') : Retourne le système d'exploitation dans lequel l'EDI a été compilé. Depuis la version 1.0.
    • GetIDEValue('CPU') : Retourne le processeur avec lequel l'EDI a été compilé. Depuis la version 1.0.
    • GetIDEValue('SrcOS') : SrcOS de l'EDI. Depuis la version 1.0.
    • GetIDEValue('SrcOS2') : SrcOS2 de l'EDI. Depuis la version 1.0.
    • GetIDEValue('LCLWidgeType') : Plate-forme LCL de l'EDI, qui peut être différente du projet. lazbuild retourne win32, carbon ou gtk2 selon son système d'exploitation. Depuis la version 1.0.
  • GetEnv(string) : Retourne la valeur de la variable d'environnement. Par exemple, GetEnv('HOME') retourne sous Linux le répertoire d'acceuil de l'utilisateur. Depuis la version 1.0.
  • GetProjValue(string) : Retourne une valeur de projet.
    • GetProjValue('FPC_FULLVERSION'): Retourne la FPC_FULLVERSION rapportée du compilateur. La version est un entier p.ex. 20701. Depuis la version 1.3.

Ordre de calcul des macros

  1. Les valeurs du projet courant sont reprises.
  2. si le projet ne définit pas les valeurs pour TargetOS, TargetCPU, l'EDI prend les valeurs par défaut.
  3. SrcOS et SrcOS2 sont calculées à partir de TargetOS.
  4. Les expressions des paquets utilisés sont calculées. Si un paquet A utilise un paquet B, alors les conditionnelles du paquet B sont calculées avant les conditionnelles de A.
  5. Chaque script de conditionnelles démarre avec les valeurs du projets.
    • Si le projet ne définit pas une valeur pour une macro de paquet, le résultat du paquet utilise est utilisé.
    • Un script peut modifier toute macro quand il s'exécute , mais seules les macros de construction et les macros prédéfinies sont utilisées. Par exemple, vous pouvez définir TargetOS à une autre valeur mais cela n'a pas d'effet sur un autre script, ni sur aucun chemin de recherche utilisant $(TargetOS), ni même sur les chemins de recherche du paquet lui-même.
    • Si deux paquets définissent la même macro de construction alors les deux peuvent modifier la valeur (à moins que le projet définisse une valeur). L'effet exact dépend de l'ordre des dépendances.
  6. les macros par défaut de l'EDI sont définies en dernier.

Exemples

Ajout d'un drapeau de compilateur pour la cible Unix

if TargetOS = 'linux' then 
  CustomOptions := '-dUseCThreads';

Notes :

  • TargetOS est une macro prédéfinie par l'EDI.
  • CustomOptions est une variable de resultat utilisée par l'EDI.
  • Les identificateurs sont sensibles à la casse, mais l'opérateur = ne l'est pas. La macro TargetOS utilise la même que le compilateur, qui est actuellement la bas-de-casse (minuscules)
  • L'EDI ajoute le premier espace automatiquement lors de l'ajout d'options personnalisées.
  • Lorsqu'il est utilisé dans un paquet, ce qui précède sera uniquement appliqué aux options utilisées pour la compilation du paquet et non au projet utilisant le paquet.

Ajout de quelques options de l'éditeur de liens pour la cible Mac OS X

Le compilateur utilise pour Mac OS X la valeur darwin pour TargetOS.

if TargetOS = 'darwin' then begin
  LinkerOptions += ' -framework Cocoa';
  if TargetCPU = 'i386' then 
    LinkerOptions += ' -framework OpenGL';
end;

Notes:

  • TargetOS et TargetCPU sont des macros prédéfinies par l'EDI.
  • L'opérateur += ajoute une chaîne ou ajoute un nombre.
  • En ajoutant plusieurs options, vous devez ajouter une espace entre les options.
  • L'EDI ajoute la première espace automatiquement lors de l'ajout des options de l'éditeur de liens.
  • Vous pouvez imbriquer begin..end comme en Pascal.
  • Si les deux conditions sont vérifiées ensemble, LinkerOptions contiendra la valeur ' -framework Cocoa -framework OpenGL'.
  • L'EDI fait précéder l'option -k quand sont passées au compilateur des options de l'éditeur de liens.
  • Ce qu'il y a en haut ne marche que pour les conditionnelles de projet.

Ajout de quelques options de l'éditeur de liens pour Mac OS X pour tous les projets utilisant un paquet

Les paquets ont deux jeux différents d'options. Le jeu utilisé pour la compilation du paquet lui-même et les options ajoutées à tous les projets/paquets utilisant le paquet. Vous devez changer les options d'usage du paquet :

if TargetOS = 'darwin' then begin
  UsageLinkerOptions += ' -framework Cocoa';
  if TargetCPU = 'i386' then 
    UsageLinkerOptions += ' -framework OpenGL';
end;

Ajout d'une option à un paquet

Si votre paquet fournit des parties optionnelles, par exemple la capacité d'utiliser OpenGL vous pouvez définir une macro de construction. Ce qui suit explique comment définir ceci pas à pas :

Disons que votre paquet est appelé Pkg1 et permet de basculer sur le support d'OpenGL en le compilant avec le drapeau -dEnableOpenGL. Le paquet devrait fournir une option booléenne Pkg1_UseOpenGL avec la valeur 'True' and 'False'.

Ouvrez l'éditeur de paquet de votre paquet 'pkg1', cliquez sur Options du compilateur et sélectionnez la page Macros de l'EDI.

Cliquez sur bouton + de gauche pour ajouter une nouvelle macro. Elle sera appelée 'Pkg1_Macro1'. Cliquez sur le noeud de l'arbre pour le renommer 'Pkg1_UseOpenGL'.

Cliquez sur le bouton + du milieu pour ajouter une nouvelle valeur de macro. Elle sera appelée 'Value1'. Cliquez sur le noeud de l'arbre pour le renommer en 'True'. Recommencez ceci pour ajouter 'False'.

Ajoutez le code suivant dans la boîte de texte des conditionnelles (Options du compilateur / Options personnalisées)

if Pkg1_UseOpenGL='True' then 
  CustomOptions := '-dEnableOpenGL';

Compileroptions buildmacro example1.png

Notes:

  • La valeur 'True' est sensible à la casse. Comme la valeur est en général choisie à partir d'une combobox, il y a peu de chance d'erreur typographique.
  • Si l'utilisateur n'a pas défini de valeur pour la macro, la variable 'Pkg1_UseOpenGL' est indéfinie et l'expression est évaluée en 'False'.

Ajouter un mode release/debug

Un mode release/debug pour votre projet et tous vos paquets

Note: Ceci nécessite Lazarus Lazarus 0.9.31 ou supérieur.

Dans les options du compilateur (Projet / Options du projet / Options du compilateur / Modes de construction) ajoutez un mode Release. Ajouter ce mode de construction l'activera automatiquement, ainsi tous les changements des options du compilateur porteront maintenant uniquement sur ce mode.

Dans "Définir les valeurs de macro", cliquez sur la colonne de gauche sur la dernière ligne "(none)". Mettez-la à "MyPackageOptions". Note : elle n'est pas listée dans la combo box.

Mettez comme valeur les options, par exemple "-O3".

Build mode release macro1.png

Cette macro est utilisable dans les options du compilateur du projet et tous les paquets.

Pour chaque paquet, faites : ouvrir les options du compilateur du paquet, aller à la page Autres. Ajoutez aux Options personnalisée le texte $(MyPackageOptions).

Un mode release/debug spécial pour un paquet

Admettons que le mode normal est le mode Debug et que vous voulez un autre mode pour les releases.

Ouvrez l'éditeur de paquet de votre paquet 'pkg1', cliquez sur Options du compilateur", sélectionnez la page Macros de contruction.

Sous Macros de construction cliquez sur le bouton + de gauche pour ajouter une nouvelle macro. Elle sera appelée 'Pkg1_Macro1'. Cliquez sur le noeud de l'arbre pour le renommer en 'Pkg1_Release'.

Cliquer sur le bouton '+' du milieu pour ajouter une nouvelle valeur de macro. Elle sera appelée 'Value1'. Cliquez sur le noeud de l'arbre pour le renommer en 'True'. Répéter la dernière opération pour la valeur 'False'.

Ajoutez le code suivant dans la boîte de texte des expressions conditionnelles :

if Pkg1_Release='True' then 
  // release mode
  CustomOptions := '-O3'
else
  // debug mode
  CustomOptions := '-Sa Ctroi';

Notes:

  • La valeur 'True' est sensible à la casse. Parce que la valeur est en général sélectionnée depuis une combo box, il y a peu de chance d'erreur de saisie.
  • Si l'utilisateur n'a pas défini de valeur de la macro, la variable 'Pkg1_Release' est indéfinie et le résultat de l'expression est 'False'.

Ajout d'une macro pour les chemins de recherche pour gérer plusieurs plates-formes

Disons que votre paquet est appelé Pkg1 et qu'il utilise le GDI dans MS Windows et X11 dans Linux et BSD. Les unités indépendantes de la plate-forme sont dans le dossier principal du paquet et vous avez créé deux sous-dossiers 'gdi' et 'x11' contenant les unités dépendantes de la plate-forme :

/path/of/your/package/pkg1/
  pkg1.lpk
  pkg1.pas
  generalunit.pas
  gdi/
    backend.pas
  x11/
    backend.pas

L'unité backend dans gdi devrait être utiliser dans Win32, Win64 et WinCE, alors que sous Linux et FreeBSD l'unité backend devrait être utilisée dans le x11. Ceci signifie que le chemin de recherche Autres fichiers d'unité (-Fu) doit être adapté selon le système cible. Ce qui suit décrit comment régler ceci pas à pas :

Ouvrez l'éditeur de paquet de votre paquet 'pkg1', cliquez sur les options de compilateur, sélectionnez la page Macros de construction.

Cliquez sur le bouton + de gauche pour ajouter une nouvelle macro. Elle sera appelée 'Pkg1_Macro1'. Cliquez sur le nœud de l'arbre pour le renommer en 'Pkg1_Backend'.

Cliquez sur le bouton + du milieu pour ajouter une nouvelle valeur de macro. Elle sera appelée 'Value1'. Cliquez sur le nœud de l'arbre pour le renommer en 'gdi'. Répéter l'opération pour la valeur 'x11'.

Ajoutez le code suivant dans la boîte de texte des conditionnelles :

// choisissez le valeur de Pkg1_Backend selon le système cible
if undefined(Pkg1_Backend) then begin
  if SrcOS='win' then
    Pkg1_Backend:='gdi'
  else
    Pkg1_Backend:='x11';
end;

La macro $(Pkg1_Backend) deviendra utilisable une fois que vous aurez cliquer sur 'Ok' pour fermer les options du compilateur et l'avoir réouvert pour l'utiliser dans les chemins de recherche Autres fichiers d'unité (-Fu).

Compileroptions buildmacro example2.png

Notes:

  • L'utilisateur peut surcharger la valeur de Pkg1_Backend. C'est donc une bonne pratique d'entourer les réglages (settings) dans un bloc if undefined(Pkg1_Backend).
  • A la place de la macro SrcOS, vous pourriez utiliser if (TargetOS='win32') or (TargetOS='win64') or (TargetOS='wince') then.
Directives, Définitions et conditionnelles:
Conditionnelle de compilation | Options conditionnelles du compilateur | Directives globales du compilateur | Directives locales du compilateur | $IF | Macros et conditionnelles | Définitions pour les plateformes