Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.
Dans ce didacticiel, vous allez apprendre à ajouter des fichiers et des modifications aux fichiers générés pour une extension.
Le temps de lecture de ce didacticiel est estimé à 25 minutes.
Pour commencer, créez le canevas de l'extension dans le fichier fichiers.svm_plugin en utilisant ce code :
PLUGIN files
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
std::string r("<");
r += RAW_STRING(s) + ">";
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Dans des extensions contenant beaucoup de code, il peut être intéressant d'organiser le code en dehors du fichier source produit par le générateur d'extension.
Modifiez le code de l'extension :
PLUGIN files
includes:
%{
#include <src/business.h>
%}
file: "src/business.h"
%{
#pragma once
#include <string>
struct Business
{
static std::string compute(const std::string& s)
{
return std::string("<")+s+">";
}
};
%}
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
auto r = Business::compute(RAW_STRING(s));
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Générez l'extension. Vous pouvez la compiler, mais cela n'est pas nécessaire.
Au lieu de la compilation, entrez dans le répertoire des fichiers de l'extension : un fichier src/business.h a été créé et il contient le code donné dans le bloc de la directive file
.
Plusieurs directives file
peuvent être ajoutées dans la partie générale de l'extension.
Le fichier précédemment généré a une particularité dans l'extension : il se retrouve copié tel quel, sans adjonction de la licence d'utilisation.
Il est possible d'indiquer que le fichier contient un certain type de contenu dans la directive file
, et cela active l'ajout de la licence au début du fichier.
Modifiez le code de l'extension :
PLUGIN files
includes:
%{
#include <src/business.h>
%}
file source: "src/business.h"
%{
#pragma once
#include <string>
struct Business
{
static std::string compute(const std::string& s)
{
return std::string("<")+s+">";
}
};
%}
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
auto r = Business::compute(RAW_STRING(s));
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Générez l'extension. Vous pouvez la compiler, mais cela n'est toujours pas nécessaire.
Ouvrez le fichier src/business.h : il contient maintenant un commentaire au début contenant la licence d'utilisation.
Ici, le type de contenu est noté comme étant source
, ce qui active les commentaires en mode C/C++. En réalité, d'autres types sont disponibles par défaut :
Il est également possible de personnaliser les commentaires produits pour ces types de fichiers, ainsi que de créer des types de contenus personnalisés.
Modifiez le code de l'extension :
PLUGIN files
includes:
%{
#include <src/business.h>
%}
file source: "src/business.h"
%{
#pragma once
#include <string>
struct Business
{
static std::string compute(const std::string& s)
{
return std::string("<")+s+">";
}
};
%}
comment source: "// ==========" "// " "// =========="
comment xml: "<!--" " " "-->"
file xml: "example.xml"
%{
<a>
<b>text</b>
</a>
%}
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
auto r = Business::compute(RAW_STRING(s));
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Générez l'extension. Vous pouvez la compiler, mais cela n'est toujours pas nécessaire.
Ouvrez les fichiers example.xml et src/business.h :
file type_facultatif: "chemin_complet_fichier"
suivi d'un bloc de texte.comment type: "premiere_ligne_commentaire" "debut_ligne_intermediaire_commentaire" "derniere_ligne_commentaire"
.En plus d'ajouter des fichiers, il peut être également intéressant de modifier les fichiers produits par le générateur d'extension.
Modifiez le code de l'extension :
PLUGIN files
includes:
%{
#include <src/business.h>
%}
file source: "src/business.h"
%{
#pragma once
#include <string>
struct Business
{
static std::string compute(const std::string& s);
};
%}
file source: "src/business.cpp"
%{
#include <src/business.h>
std::string Business::compute(const std::string& s)
{
return std::string("<")+s+">";
}
%}
patch: "Makefile.local"
%{
--- Makefile.local.orig 2023-01-01 00:00:00.000000000 +0200
+++ Makefile.local 2023-01-01 00:00:00.000000000 +0200
@@ -20,7 +20,7 @@
OPTIONS=
-DEPENDENCIES=
+DEPENDENCIES=src/business.o
GENERATED=
all: libsvmfiles.so
%}
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
auto r = Business::compute(RAW_STRING(s));
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Générez l'extension. Vous pouvez la compiler, mais cela n'est toujours pas nécessaire.
La directive patch
va automatiquement modifier le fichier Makefile.local après génération pour ajouter la compilation du fichier src/business.o, maintenant devenu nécessaire à la compilation de l'extension.
Vous pouvez noter que la directive demande :
diff -u
.Un fichier source d'extension peut contenir jusqu'à un patch à appliquer par fichier généré.
Maintenir les patchs n'est pas une chose simple, car cela demande certaines précautions, comme conserver le fichier d'origine et réaliser la différence depuis le répertoire généré.
Pour simplifier la rédaction et la maintenance des patchs, il est conseillé :
%{}
.-p
. Dans ce cas, le générateur va :
patch
par le résultat du script update_patches. Le script s'assure que la différence est calculée depuis le bon répertoire, en prenant comme référence les fichiers d'origine.Appliquez cette méthode sur le fichier source de l'extension jusqu'à obtenir (aux dates et heures près) :
PLUGIN files
includes:
%{
#include <src/business.h>
%}
file source: "src/business.h"
%{
#pragma once
#include <string>
struct Business
{
static std::string compute(const std::string& s);
};
%}
file source: "src/business.cpp"
%{
#include <src/business.h>
std::string Business::compute(const std::string& s)
{
return std::string("<")+s+">";
}
%}
patch: "Makefile.local"
%{
--- Makefile.local.orig 2023-01-01 00:00:00.000000000 +0200
+++ Makefile.local 2023-01-01 00:00:00.000000000 +0200
@@ -20,7 +20,7 @@
OPTIONS=
-DEPENDENCIES=
+DEPENDENCIES=src/business.o
GENERATED=
all: libsvmfiles.so
%}
patch: "src/Makefile.am"
%{
--- src/Makefile.am.orig 2023-01-01 00:00:00.000000000 +0200
+++ src/Makefile.am 2023-01-01 00:00:00.000000000 +0200
@@ -22,6 +22,6 @@
noinst_LTLIBRARIES=libplugin.la
-libplugin_la_SOURCES=plugin.cpp plugin.h
+libplugin_la_SOURCES=plugin.cpp plugin.h business.cpp business.h
libplugin_la_LIBADD=
libplugin_la_LDFLAGS=-no-undefined
%}
DEFINE
INSTRUCTION files.instruction STR -> STR
%{
auto s = ARGV_VALUE(0,string);
auto r = Business::compute(RAW_STRING(s));
return ::svm_value_string_new__buffer(svm,r.c_str(),r.size());
%}
Vous pouvez alors générer une dernière fois l'extension et la compiler. La compilation fonctionne également en utilisant autotools.
patch: "chemin_complet_fichier"
suivi d'un bloc permet de modifier un fichier produit par le générateur d'extension. Le bloc doit contenir la différence à appliquer comme produite par l'utilitaire diff -u
depuis le répertoire de génération.-p
du générateur d'extension permet d'automatiser la création et la maintenance des modifications de fichiers.Vous venez de voir comment ajouter des fichiers et modifier des fichiers des extensions.
Ces outils permettent d'écrire des extensions ayant un code fonctionnel beaucoup plus important et déporté du fichier de base qui devient juste l'interface de l'extension. Et cela tout en conservant l'atomicité du fichier de génération des extensions.