4
Introduction
WebAssembly, abrégé Wasm,est un standard du World Wide Web pour le développement
d’applications. Il est conçu pour remplacer JavaScript avec des performances supérieures. Le standard
consiste en un bytecode, sa représentation textuelle et un environnement d'exécution dans un bac à
sable compatible avec JavaScript. Il peut être exécuté dans un navigateur Web et en dehors.
WebAssembly est standardisé dans le cadre du World Wide Web Consortium (w3c).
Comme WebAssembly ne spécifie qu'un langage de bas niveau, le bytecode est généralement produit
en compilant un langage de plus haut niveau.
Parmi les premiers langages pris en charge figurent Rust avec le projet/module (crate) wasm-bindgen
ainsi que le C et C++, compilés avec Emscripten (basé sur LLVM). De nombreux autres langages de
programmation possèdent aujourd'hui un compilateur WebAssembly, parmi lesquels : Ada, C#, Go,
Java, Lua, OCaml, PHP, Python, Ruby, Fortran ou FreePascal(fpc+pas2js).
Les navigateurs Web compilent le bytecode wasm dans le langage machine de l'hôte sur lequel ils sont
utilisés avant de l'exécuter.
5.
5
LOGO
Le nouveau logoa été sélectionné en février 2017 lors d’un concours de design :
https://github.com/WebAssembly/design/issues/980
INSPIRATION DU LOGO WASM
Circuit intégré (IC)
Encoche supérieure comme l’orientation d’un IC.
Niveau bas : structures de données, mémoire et efficacité CPU, etc.
WASM complète JS
Logo en boîte similaire qui met en avant la relation entre JS et WASM
Couleur principale : couleur complémentaire de JS
6.
6
Webassembly
WebAssembly est unformat de code binaire portable qui est devenu disponible
sur les principaux navigateurs tels que Google, Microsoft, Mozilla et Apple :
7.
7
Historique
Juin 2015 –WebAssembly a été annoncé pour la première fois.
Mars 2016 – Google, Microsoft, Mozilla présentent une préversion de WebAssembly
dans leurs navigateurs.
Octobre 2016 – WebAssembly devient une version candidate binaire.
Mars 2017 – Commence à être livré par défaut dans les navigateurs.
Liens d’intérêt :
http://webassembly.org/
https://github.com/WebAssembly
https://www.w3.org/community/webassembly/
9
A quoi sertWebAssembly?
Le comité qui définit le langage wasm nous a donné une liste des utilisations possibles du langage. Noter que même s'il est prévu que de nombreux
langages de programmation seront compilés en Wasm à l'avenir, le remplacement dans le navigateur de JavaScript par un autre langage compilé en
Wasm n'est pas envisagé...
On peut cependant réaliser entièrement une application en Wasm dans certains cas, pour un jeu par exemple, si elle a sa propre interface, sinon le
cas de figure le plus fréquent est une interface HTML et JavaScript avec une bibliothèque en wasm.
Dans le navigateur :
Edition de vidéos et musique.
Jeux, même en 3D avec OpenGL.
Applications collaboratives et décentralisées.
Réalité augmentée.
Reconnaissance d'images.
Applications vectorielles.
Logiciels interactifs et éventuellement éducatifs.
Visualisation et simulation scientifique.
Interpréteur de langage de programmation.
Outils de développement (éditeurs, débogueurs).
Création d'un OS dans le navigateur.
Cryptographie.
Serveur Web local.
Client de base de donnée.
Etc...
10.
10
A quoi sertWebAssembly?
Hors navigateur :
Traitement coté serveur, pour le compte d'une application en ligne.
Application coté serveur.
Applications natives sur mobile securisées.
Remplacer les DLL par des modules Wasm.
Appareils sans système d'exploitaton.
11.
11
Vous êtes-vous déjàdemandé ce qu’est WebAssembly? A quoi sert-il, comment
fonctionne-t-il ou encore quels sont ses avantages par rapport aux autres
systèmes de programmation ?
La technologie WebAssembly, également connue sous le nom de WASM, est
largement répandue parmi les programmeurs. Bien que WebAssembly soit
relativement nouveau, dès 2015 son nom commençait à s’immiscer dans les
conversations.
Les performances élevées de WebAssembly avec de petits fichiers ou ses
fonctionnalités élevées pour la navigation mobile ont fait exploser sa popularité
dans la création d’applications mobiles et de jeux vidéo.
Quelques questions
12.
12
Definition
Les progrès dela technologie et la sophistication des navigateurs et des
technologies de communication client-serveur font de nos navigateurs des
outils de plus en plus complexes avec d’énormes fonctionnalités.
Cela est dû en grande partie à WebAssembly (WASM). Un langage de
programmation de bas niveau, intuitif et similaire à l’assembleur original conçu
pour le développement web.
Totalement indépendant de l’architecture système (ARM, x86, x64, etc.),
WebAssembly permet de développer des applications autonomes avec des
langages plus puissants (WebAssembly est compatible avec Rust, C ou C++)
et de distribuer le bytecodede afin de l’exécuter librement.
16
Qu’est-ce que celasignifie ?
Eh bien, en gros, WebAssembly transforme notre navigateur en une “machine virtuelle”
ayant la capacité d’exécuter des programmes puissants sans recourir à
des Développeurs JavaScript.
Cela ne veut pas dire que WebAssembly n’est pas compatible avec Javascript! Au
contraire! WebAssembly s’appuie sur ce langage, mais en intégrant une API dans le but
d’intégrer des modules WASM dans des sites Web sans avoir besoin de savoir
comment ils sont implémentés.
Pour les développeurs, est synonyme de liberté car ils peuvent créer leur travail dans le
langage souhaité puis “le transmettre” à un autre pour un usage commun via un
système modulaire.
Cela améliore considérablement le développement créatif des jeux vidéo, réalité
virtuelle, réalité augmentée ou intelligence artificielle. De plus, cela permet aux
communautés de programmation elles-mêmes, tant indépendantes que grandes
entreprises, de modifier et développer l’environnement WASM.
18
Quelle utilite duwebassembly
Pour ceux d’entre vous qui cherchent à obtenir une prise en charge au niveau binaire
sur l’ensemble de la plateforme web, WebAssembly est la solution.
WebAssembly est en réalité un format AST binaire par défaut. Le format AST binaire
désigne la représentation compacte de WebAssembly, dans laquelle le code source
écrit dans divers langages (comme C, C++, Rust ou autres) est compilé en un format
binaire basé sur un arbre syntaxique abstrait (AST) qui peut être exécuté efficacement
par le navigateur. Ce format est conçu pour offrir des performances proches du code
natif, réduire le temps de parsing et permettre la prise en charge de grandes
applications sur le web. Il est produit lors de la compilation, où l'AST du langage source
est transformé en instructions binaires optimisées pour l'environnement WebAssembly.
C’est un changement notable par rapport aux limitations de charge utile de JavaScript.
20
Format binaire basesur AST
AST - Arbre de syntaxe abstraite.
Dans un compilateur, l'AST garde les informations de localisation source et des informations de typage.
Le code WebAssembly est essentiellement compilé en AST binaire à partir de langages comme C, Haskell ou C++ dans le navigateur.
21.
21
Avantages
La puissance résidedans la possibilité d'utiliser d'autres langages pour compiler un
fichier binaire à gérer dans le navigateur.
En WASM, il est possible d'écrire et de déboguer dans un format texte lisible. Il s'agit
d'un nouveau langage bas niveau dans l'esprit d'un langage d'assemblage.
22.
22
...mais, asm.js nele fait-il pas déjà aujourd'hui ?
Un extrait de code asm.js :
asm.js est un sous-ensemble bas niveau de JavaScript. Il permet un accès direct aux
registres mémoire, mais continue d’être analysé par JavaScript.
C’est donc une surcharge liée à la charge utile.
WebAssembly contourne tout cela en utilisant directement l’AST sous un format binaire.
23.
23
Goulots d’étranglements deJavaScript
JavaScript a pas mal de restrictions dans sa flexibilité (ex: charge utile, etc… )
WASM fonctionne au niveau mémoire et bas niveau dans le navigateur.
Pensez à exprimer les choses directement aux threads et SIMD.
WASM comble les lacunes laissées par JavaScript en termes de contrôle des registres
mémoire au niveau bit/octet.
Vous ne pouvez tout simplement pas atteindre ce bas niveau avec JavaScript ou avec
des bibliothèques/cadres populaires en JavaScript avec les frameworks habituels
comme REACT, Angular, Vue, etc...
24.
24
D'autres langages s'exécutentdans le navigateur !
"Un utilisateur peut compiler un programme écrit dans un langage de haut niveau en
WebAssembly et l'exécuter dans un navigateur. Comme première étape, dans un produit
viable minimal, l'objectif était de s'assurer qu'un programme C/C++ puisse être compilé en
WebAssembly et exécuté dans le navigateur."
B. Abhijith Chatra,
Ingénieur logiciel senior chez Microsoft
Co-président du groupe communautaire WASM
25.
25
Compilateurs de navigateurset machines virtuelles dans le navigateur
Cela permet à d'autres langages de programmation d’etre compilé efficacement pour le
Web.
Encore une fois, WASM vous offre un format exécutable binaire
pour y parvenir.
WebAssembly offrira un environnement d'exécution sécurisé
en mémoire, isolé (sandboxé). Il accédera aux fonctionnalités
du navigateur via les mêmes API Web accessibles depuis
JavaScript.
26.
26
Les transpilers
Une ciblede transpilation (transpiler) pour JavaScript (*)
Un remplaçant de JS
Un langage de programmation
Un transpiler c’est un programme permettant de traduire un langage (de haut
niveau) dans un autre. Un transpiler JS comme pas2js convertit du FreePascal en
31
Pour que WebAssemblyréussisse, nous avons besoin de deux choses
Que les navigateurs prennent en charge WebAssembly de manière native
Des compilateurs qui produisent du WebAssembly. Il en existe déjà plusieurs :
LLVM
ilwasm
Binaryen (écrit en C++)
Asm2wasm
Emscripten
32.
32
Comment fonctionne WebAssembly?
WebAssembly est un format d’instruction binaire et une machine virtuelle qui apporte des performances quasi natives aux
applications de navigateur Web.
Définition technique : sa naissance est due à des problèmes strictement fonctionnels : la “mort” des plug-ins binaires tiers a
exclu d’autres langages comme Java y ActionScript de Flash pour le développement web, favorisant la recherche d’une
alternative pour la compilation de n’importe quel langage.
Quel est son processus : la première chose à savoir est que WebAssembly n’a pas vocation à remplacer les applications
JavaScript, mais à améliorer leurs performances. Concernant son fonctionnement, les programmeurs écrivent dans un langage
plus récent qui par la suite se compile en bytecode WebAssembly. Ce bytecode est exécuté dans un navigateur Web, où il est
traduit au code machine natif à grande vitesse. WebAssembly fournit un modèle d’exécution en bac à sable (ou “sandboxing”),
basé sur les mêmes systèmes de sécurité qui utilisaient jusqu’à présent JavaScript. WebAssembly System Interface (WASI)
garantit un accès contrôlé aux fichiers, au réseau, à l’horloge système et à d’autres services nécessaires à l’exécution des
programmes.
Le fonctionnement de WebAssembly peut être résumé parmi les 4 étapes suivantes :
Compilation.
Téléchargement et interprétation.
Exécution rapide et efficace.
Interopérabilité avec Java
34
Avantages de WebAssembly?
WebAssembly est une véritable révolution pour les projets web, améliorant la vitesse et fournissant des améliorations
infinies.
Parmi ses avantages figurent :
Large adoption : webAssembly est en passe de devenir un standard de support pour les principaux
navigateurs, garantissant ainsi une compatibilité à long terme.
Amélioration des performances : WebAssembly a une conception «bas niveau» et une exécution très efficace,
et permet la création d’applications Web rapides et fluides.
Aucune limitation d’utilisateur : il fonctionne sur un environnement bac à sable “sandboxing”, au sein du
navigateur lui-même, et non sur un serveur. De plus, il est isolé du système d’exploitation sous-jacent. Vos
utilisateurs pourront profiter d’applications web puissantes, créatives et innovantes, avec sécurité et sans
limite en raison d’une surcharge du système.
Aucun nouveau langage de programmation requis : les modules WASM sont autonomes et peuvent être
exécutés dans n’importe quel navigateur Web moderne sans apporter de modifications supplémentaires et sans
apprendre de nouvelles langues. Vous pourrez programmer dans le langage de votre choix et votre travail
sera compatible avec plusieurs plates-formes.
35.
35
Les 3 clésde WebAssembly
Après avoir expliqué ce qu’est WebAssembly, son fonctionnement ainsi que les avantages pour
exécuter du code dans des langages plus proches de la machine, comme C, C++, C# ou Rush,
découvrons désormais les caractéristiques qui définissent cette technologie.
Sécurité : WebAssembly fonctionne dans le cadre de sécurité offert par les navigateurs,
implantant naturellement des mesures comme :
Vérification de l’origine du code.
Restrictions d’accès au contenu provenant d’autres sources.
La demande d’autorisation pour accéder au matériel
Vitesse : WebAssembly garantit le déploiement d’applications avec du code de vitesse native, ce
qui représente un avantage dans le matériel des appareils.
Open source : Le code est complètement ouvert et les programmeurs peuvent le visualiser
pour vérifier son exécution ou le déboguer si nécessaire.
36.
36
L’avenir de WebAssembly
dansle développement Web
L’objectif est qu’à l’avenir, WebAssembly puisse également exécuter des applications côté
serveur, de la même manière que Node.js exécute JavaScript en dehors du navigateur.
Certains des changements de l’utilisation de WebAssembly nous permettent déjà d’entrevoir
dans le domaine du divertissement, la création de contenu ou l’entreprise sont :
Développement de jeux mobiles et les jeux vidéo avec plus de capacité à traiter des
données, des informations, des images, etc.
Génération de contenu multimédia à partir de vidéos et d’images haute
résolution/HD.
Création de simulateurs scientifiques.
Solution de visio-conference.
Utiliser le Big Data sans travailler côté serveur.
38
Emscripten
Emscripten est unechaîne d’outils complète open source permettant de compiler du code C et C++ (ou tout autre
langage compatible LLVM) vers WebAssembly (WASM), afin de faire tourner des programmes natifs dans les
navigateurs web ou d’autres environnements compatibles comme Node.js.
Emscripten repose sur LLVM, un compilateur intermédiaire qui transforme le code source en bytecode LLVM. Ce
bytecode est ensuite converti par Emscripten en WebAssembly (ou en asm.js pour compatibilité avec d’anciens
navigateurs). Le résultat est généralement un trio de fichiers :
un module binaire .wasm,
un fichier JavaScript « glue» (pont entre le C++ et le Web),
et un fichier .html de démonstration pour exécuter le code.
Exemple de compilation basique :
$ emcc hello.c -s WASM=1 -o hello.html
Cette commande génère les trois fichiers nécessaires pour exécuter un programme C comme
une application web.
39.
39
Installation
Téléchargez le àcette adresse : https://emscripten.org/docs/getting_started/downloads.html
ou téléchargez le zip directement sur github : https://github.com/emscripten-core/emsdk
La mauvaise nouvelle est que maintenant il faut utiliser Python pour installer Emscriptem, pour une raison
quelconque, ce qui n'était pas le cas auparavant.
Ouvrez la fenêtre de ligne de commande et allez dans le répertoire emsdk-master :
$ ./emsdk update
$ ./emsdk install latest
$ ./emsdk activate latest
L'archive d'Emscriptem inclut le compilateur CLang, Python, et l'interpréteur
JavaScript Node.js entre autres.
Si vous avez déjà installé une version plus récente de Node.js, supprimez l'entrée
EMSDK_NODE dans la variable d'environnement PATH.
40.
40
Tester la config
Unprogramme minimal C++ à compiler en wasm :
#include <stdio.h>
int main() {
printf("Hello, world!n");
return 0;
}
Enregistrez ce progamme dans un fichier nommé hello.cpp
Tapez:
$ emcc hello.cpp
Puis exécutez le programme qui vient d'être généré:
$ node a.out.js
Cela affichera: Hello, World!
Pour utiliser un script dans le navigateur, utilisez cette commande:
$ emcc hello.cpp -o hello.html
Un fichier HTML est également généré qui contient le code nécessaire pour faire appel au code wasm en ligne...
41.
41
Emscripten
Emscripten intègre plusieurscomposants essentiels :
LLVM/Clang : pour produire le bytecode intermédiaire.
Binaryen : pour optimiser et transformer ce bytecode vers WebAssembly.
Embind et EM_JS : pour faciliter les interactions entre les fonctions C++ et le code
JavaScript.
Système de fichiers virtuel : permettant d’émuler un environnement POSIX (pour
fopen, read, etc.) dans le navigateur.
Cette architecture rend possible le portage de bibliothèques telles que SDL2, OpenGL ou
même Qt vers le Web sans réécriture majeure.
Emscripten est largement utilisé pour les portages de moteurs de jeux (Unity, Unreal
Engine), d’outils scientifiques (Gnuplot, SQLite) et de bibliothèques multimédias.
Sa performance est proche du natif, grâce à la vitesse d’exécution du WebAssembly et à
42.
42
Emscripten
Exemple d’intégration avecembind :
#include <emscripten/bind.h>
using namespace emscripten;
int add(int a, int b) { return a + b; }
EMSCRIPTEN_BINDINGS(my_module) {
function("add", &add);
}
Compilation :
$ emcc --bind -O3 add.cpp -o add.js
Le module WebAssembly obtenu expose ensuite la fonction add directement à JavaScript.
Environnement et compatibilité
Emscripten est multiplateforme (Windows, Linux, macOS), publié sous licence MIT/NCSA, et prend en charge les API OpenGL,
POSIX, SDL2 et WebGL. Il permet l’exécution transparente d’applications C/C++ dans des environnements web modernes.
En résumé, Emscripten est un outil clé pour exécuter du code natif haute performance dans un navigateur, tout en
maintenant la compatibilité et la sécurité offertes par l’écosystème WebAssembly.
44
Compiler un programmeWASM 1/2
Étape n°1 : Obtenir le compilateur Emscripten et le SDK Emscripten
$ git clone https://github.com/juj/emsdk.git
$ cd emsdk
$ ./emsdk install sdk-incoming-64bit binaryen-master-64bit
$ ./emsdk activate sdk-incoming-64bit binaryen-master-64bit
Étape n°2 : Entrez dans l'environnement du compilateur Emscripten dans le terminal
courant avec la commande suivante
$ source ./emsdk_env.sh
45.
45
Compiler un programmeWASM 2/2
Étape n°3 : Créez un programme “hello world” simple et compilez-le. La compilation correspond à la dernière
commande
$ mkdir hello
$ cd hello
$ echo '#include <stdio.h>' > hello.c
$ echo 'int main(int argc, char ** argv) { ' >> hello.c
$ echo 'printf("Hello, world!n");' >> hello.c
$ echo '}' >> hello.c
$ emcc hello.c -s WASM=1 -o hello.html
Étape n°4 : Nous pouvons utiliser le serveur web emrun fourni avec le SDK Emscripten :
46.
46
Démos en ligne
Démoen ligne d’un compilateur WASM : https://kripken.github.io/talks/wasm.html#/11
Démo multi-navigateurs de Tanks : http://webassembly.org/demo/
47.
47
Compiler en Wasmun projet de plusieurs sources C++
L'exemple est une petite bibliothèque de calculs arithmétique que l'on peut inclure dans plusieurs projets.
Ces fonctions sont volontairement simplistes pour que l'on se concentre sur la méthode de compilation et non sur le contenu.
/* Bibliothèque de fonctions */
#include <stdio.h>
int add(int x, int y) {
return x + y;
}
int mul(int x, int y) {
return x * y;
}
Sauvegardez le programme sous le nom demolib.cpp
int fibonacci(int n) {
if(n < 2) {
return 1;
}
else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
48.
48
Compiler en Wasmun projet de plusieurs sources C++
Ecrivez aussi un fichier d'en-tête :
int add(int, int);
int mul(int, int);
int fibonacci(int);
Le fichier d'en-tête sera sauvegardé sous le nom de demolib.hpp dans le même répertoire
que le source principal..
49.
49
Compiler en Wasmun projet de plusieurs sources C++
Code source demo.cpp principal de la démonstration contenant la fonction main, et qui utilise les fonctions de la bibliothèque :
#include <iostream>
#include "demolib.hpp"
int main() {
int a = add(10, 20);
std::cout << "10 + 20 = " << a << std::endl;
int m = mul(10, 20);
std::cout << "10 x 20 = " << m << std::endl;
std::cout << "Fibonacci(16):" << fibonacci(16) << std::endl;
}
50.
50
Compiler en Wasmun projet de plusieurs sources C++
Cette fois la commande de compilation contient une liste de plusieurs fichiers à compiler :
$ emcc demolib.cpp demo.cpp -o demo.wasm
Cela produit le fichier suivant:
demo.wasm
Exécutez le programme avec la commande suivante:
$ wasmer hello.wasm
Ce qui affichera:
10 + 20 = 30
10 x 20 = 200
Fibonacci(16):1597
51.
51
Générer une bibliothèquepour un projet Wasm
Des fichiers sources C++ sont compilés en fichiers objets réunis dans un seul fichier bibliothèque.
Pour que cela fonctionne, les fichiers objets ne doivent pas être produits par un compilateur classique comme GCC ou même CLang, il doivent être générés par Emcc.
L'exemple de bibliothèque est composé de deux fichiers, l'un contient des fonctions arithmétiques simples et l'autre l'algorithme de Fibonacci.
Premier fichier source arithm.cpp :
int add(int x, int y) {
return x + y;
}
int mul(int x, int y) {
return x * y;
}
float divide(float x, float y) {
if(y == 0) return 0;
return x / y;
}
52.
52
Générer une bibliothèquepour un projet Wasm
Second fichier source fibonacci.cpp :
int fibonacci(int n) {
if(n < 2) {
return 1;
}
else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
53.
53
Générer une bibliothèquepour un projet Wasm
Les fichier d'en-tête seront sauvegardé sous le nom de arithm.hpp:
int add(int, int);
int mul(int, int);
float divide(float, float)
Et fibonacci.hpp:
int fibonacci(int);
54.
54
Générer une bibliothèquepour un projet Wasm
Code source demoprj.cpp du programme de démonstration utilisant les fonctions de la bibliothèque :
/* Démonstration */
#include <iostream>
#include "arithm.hpp"
#include "fibonacci.hpp"
int main() {
int a = add(10, 20);
std::cout << "10 + 20 = " << a << std::endl;
int m = mul(10, 20);
std::cout << "10 x 20 = " << m << std::endl;
float d = divide(30, 10);
std::cout << "30 / 10 = " << d << std::endl;
std::cout << "Fibonacci(16):" << fibonacci(16) << std::endl;
}
55.
55
Générer une bibliothèquepour un projet Wasm
Générer la bibliothèque :
Premier fichier:
$ em++ arithm.cpp -c -o arithm.o -Oz -s SIDE_MODULE=1 -s WASM=1
Second fichier:
$ em++ fibonacci.cpp -c -o fibonacci.o -Oz -s SIDE_MODULE=1 -s WASM=1
Vous pouvez inclure éventuellement dans la commande des fichiers d'en-tête externes avec l'option -I
Les fichiers objets sont réunis dans un fichier bibliothèque avec la commande emar incluse dans emscriptem.
$ emar rcs demolib.a arithm.o fibonacci.o
Cela produit le fichier suivant:
demolib.a
56.
56
Générer une bibliothèquepour un projet Wasm
Utiliser la bibliothèque
Le fichier bibliothèque peut alors être inclus dans la commande de compilation du programme principal.
$ emcc demolib.a demoprj.cpp -o demoprj.wasm -s WASM=1
Exécution du programme
$ wasmer demoprj.wasm
Ce qui affichera:
10 + 20 = 30
10 x 20 = 200
30 / 10 = 3
Fibonacci(16):1597
57.
57
Utiliser des fonctionsWasm avec Node.js
Le meilleur moyen d'inclure du code C dans une application JavaScript et rester portable.
Même si WebAssembly a originellement été conçu pour les applications Web, ce n'est pas le domaine où il excelle le plus. L'utilisation trop fréquente
de code Wasm sur des sites malicieux à conduit à rendre son utilisation plus stricte dans les pages web, et donc le rendre plus difficile à utiliser. On
contraire sur le poste local, il est extrêmement simple à utiliser et ouvre un nouvel horizon et de vastes possibilités aux programmeurs.
Il est aussi plus facile de compiler un fichier source C en Wasm qu'un fichier C++, car le compilateur emcc dérivé de CLang modifie le nom des
fonctions C++ dans le code généré ce qu'il ne fait pas avec C, et il est ainsi plus compliqué d'appeler les fonction C++ dans le code JavaScript.
On utilisera dans cet exemple une bibliothèque de fonctions similaire à celle que l'on a utilisé précedemment :
int fnadd(int x, int y) {
return x + y;
}
int fnmul(int x, int y) {
return x * y;
}
On sauvera ce code dans le fichier demolib.c.
int fibonacci(int n) {
int z;
if(n < 2) {
z= n;
}
else {
z= fibonacci(n-1) + fibonacci(n-2);
}
return z;
}
58.
58
Utiliser des fonctionsWasm avec Node.js
Il est compilé en wasm avec cette commande:
$ emcc demolib.c -Oz -s WASM=1 -s SIDE_MODULE=1 -o demolib.wasm
Le programme JavaScript charge le code Wasm avec la fonction readFileSync, crée des références utilisables en JavaScript
avec la méthode instantiate de WebAssembly.
const fs = require("fs");
async function demo() {
let wasm = fs.readFileSync("demolib.wasm");
let lib = await WebAssembly.instantiate(wasm);
let arith = lib.instance.exports
console.log(arith.fnadd(10,20));
console.log(arith.fnmul(100,9));
let fmax = 20
for(var i=0; i <= fmax; i++) {
console.log("fib(" + i + ")=" + arith.fibonacci(i));
}
};
demo().then();
On sauvera le code dans le fichier demo.js.
59.
59
Utiliser des fonctionsWasm avec Node.js
On peut alors exécuter le script avec cette commande:
$ node demo.js
Cela doit afficher 30 puis 900 puis une suite de Fibonacci.
Noter que les fonctions WebAssembly sont normalement appelées avec le format
lib.instance.exports.nom_fonction() et pour simplifier les appels on a assigné
lib.instance.exports à la variable arith.
Ce programme est particulièrement simple parce que la bibliothèque wasm n'utilise pas
la librairie standard C. Si c'était le cas il faudrait déclarer la liste des fonctions
C utilisées dans la déclaration d'instantiation wasm.
Elle n'utilise pas non plus le système de fichiers, ce qui compliquerait encore le
code. Ce n'est pas vraiment nécessaire en fait, car les accès aux fichiers ne profitent
pas de la vitesse d'exécution de wasm, on réalise ces appels dans le code JavaScript
incluant le modules fs et éventuellement on passe les données comme arguments aux
fonctions wasm.
60.
60
Convertir C++ enWebAssembly
Développer un vrai programme C++ exécutable localement.
Vous trouverez de nombreux exemples sur le Web qui prétendent montrer comment réaliser une application wasm à partir d'un fichier
source C++. Mais à y mieux regarder, ce sont toujours des codes sources C. Pour avoir ic un exemple de vrai code C++, nous allons
ajouter une fonction qui ne peut exister en C puisqu'elle utilise le type string pour stocker une chaîne de caractère à la place de char * du
langage C.
Notre exemple de bibliothèque C++ inclut une fonction concat dont l'intérêt est purement démonstratif :
#include <string>
using namespace std;
int add(int x, int y) {
return x + y;
}
int mul(int x, int y) {
return x * y;
float divide(int x, int y) {
if(y == 0) return 0;
return x / y;
}
string concat(string a, string b) {
return a + b;
}
61.
61
Convertir C++ enWebAssembly
On crée aussi un en-tête dans lib.hpp pour pouvoir inclure ce code dans un projet. Voici son contenu :
int add(int, int);
int mul(int, int);
float divide(int, int);
string concat(string, string);
62.
62
Convertir C++ enWebAssembly
Maintenant, un exemple d'application utilisant cette bibliothèque C++:
/* Demo C++ */
#include <iostream>
#include <string>
using namespace std;
#include "lib.hpp"
int main() {
int a = add(10, 20);
cout << "10 + 20 = " << a << endl;
int m = mul(10, 20);
cout << "10 x 20 = " << m << endl;
float d = divide(30, 10);
cout << "30 / 10 = " << d << endl;
string s = concat("Hello", " World!");
cout << "Concat: " << s << endl;
}
La déclaration de l'espace de nom std doit précéder l'inclusion de l'en-tête
arithm.hpp, car il fait référence au type string.
Le source est sauvegardé dans le fichier demo.cpp.
63.
63
Convertir C++ enWebAssembly
L'application wasm est générée avec la commande suivante:
$ emcc lib.cpp demo.cpp -o demo.wasm
On exécute le programme avec cette commande:
$ wasmer demo.wasm
Cela doit afficher les lignes suivantes dans la console:
10 + 20 = 30
10 x 20 = 200
30 / 10 = 3
Concat: Hello World!
L'avantage avec une application locale exécutée par wasmer ou wasmtime est qu'ils savent comment inclure le
runtime WASI qui contient la bibliothèque standard C++.
Mais si on veut utiliser une bibliothèque wasm dans une application HTML ou avec node.js, il faudra relier soi-
même WASI au code wasm et ce sera plus compliqué, c'est pourquoi une pseudo application C++ qui est en réalité
un code C dans un fichier C++ est insuffisante comme exemple. Elle devrait contenir du code propre à C++.
65
Wasmer
Pour exécuter unfichier WebAssembly (WASM) en ligne de commande sans le navigateur ni serveur web, il faut utiliser un runtime
WebAssembly CLI. Les plus utilisés sont Wasmer, Wasmtime et WasmEdge, qui permettent d’exécuter du bytecode .wasm directement
en console sous Linux, macOS ou Windows.
Exécution avec Wasmer :
Wasmer est un environnement d’exécution multi-backend pour WebAssembly compatible WASI (WebAssembly System Interface).
Installation rapide sous Linux :
$ curl https://get.wasmer.io -sSfL | sh
$ source /home/tgayet/.wasmer/wasmer.sh
Exécution d’un module compilé :
$ wasmer run hello.wasm
Pour passer des arguments au programme :
$ wasmer run hello.wasm -- arg1 arg2
Si votre module utilise WASI (accès console, fichiers, etc.) :
$ wasmer run hello.wasm --dir=. --env MYVAR=123
66.
66
Wasmtime
Exécution avec Wasmtime:
Wasmtime est le runtime officiel du projet Bytecode Alliance, très performant et sécurisé.
Installation:
$ curl https://wasmtime.dev/install.sh -sSf | bash
Lancement :
$ wasmtime hello.wasm
Comme Wasmer, il supporte aussi WASI :
$ wasmtime run hello.wasm --dir=. -- arg1 arg2
Wasmtime est souvent utilisé pour des exécutions serveur ou embarquées.
At the end, open a new terminal to start using Wasmtime!
67.
67
WasmEdge
Exécution avec WasmEdge
WasmEdgevise la performance et l’intégration Cloud/IA.
Installation :
$ curl -sSf
https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh
| bash
Puis :
$ wasmedge hello.wasm
Il est aussi compatible avec les modules WASI et offre des extensions
réseau, TensorFlow et OpenVINO.
68.
68
Emscripten
Générer un moduleWASI compatible avec Emscripten :
Pour que votre .wasm soit exécutable par ces runtimes CLI, compilez avec les options suivantes:
$ emcc hello.c -s WASM=1 -s STANDALONE_WASM -o hello.wasm
L’option -s STANDALONE_WASM produit un module autonome compatible WASI.
Ensuite, le programme peut être lancé avec n’importe quel runtime CLI compatible (Wasmer, Wasmtime, ou WasmEdge).
En résumé, après la compilation avec Emscripten, la méthode la plus simple pour exécuter le .wasm en ligne de commande
est :
$ wasmer run hello.wasm
ou, pour les builds avec support WASI :
$ wasmtime run hello.wasm --dir=.
Ces outils permettent d’exécuter votre code WebAssembly sans dépendre du navigateur, directement depuis le terminal.
69.
69
Exemple hello.c
Exemple decode hello.c :
#include <stdio.h>
int main(int argc, char **argv) {
printf("Hello, world!n");
return 0;
}
Compilation avec Emscripten
Pour compiler ce programme en WebAssembly, placez le fichier dans votre répertoire de travail et exécutez :
$ emcc hello.c -s WASM=1 -o hello.html
Cette commande génère trois fichiers :
hello.html : page permettant d’exécuter le module WebAssembly dans un navigateur
hello.js : script JavaScript de support créé par Emscripten
hello.wasm : le bytecode WebAssembly lui-même
70.
70
Exemple hello.c
Variante pourexécution en ligne de commande :
Si vous souhaitez exécuter le fichier .wasm dans un runtime CLI (Wasmer, Wasmtime, ou
WasmEdge), compilez avec l’option :
$ emcc hello.c -s STANDALONE_WASM -o hello.wasm
Puis lancez-le directement :
$ wasmer run hello.wasm
Compiling to WebAssembly
⠁
Hello, world!
ou
$ wasmtime hello.wasm
Hello, world!
Ce petit exemple sert de base pour vérifier que votre environnement Emscripten et votre
runtime WebAssembly fonctionnent correctement.
72
Quelle est l’avenirde WASM ?
« Plutôt que de vouloir tuer JavaScript, ce qui n’est pas faisable, ce que nous essayons de
faire, c’est de répondre à de vrais problèmes d’ingénierie rencontrés avec ASM.js. Le
chargement d’un gros jeu Epic ou Unity peut prendre 20 à 30 secondes. C’est trop long.
Avec un arbre syntaxique abstrait compressé 20 fois plus rapide, il ne faudrait que quelques
secondes, c’est ce que l’on recherche. Il y a donc une vraie raison pour WASM, et c’est une
raison valable. »
Brendan Eich
Auteur de JavaScript
77
Listing des fichiers
❯cd helloworld/
❯ tree
├── hello.c
├── Makefile
└── Makefile.old
1 directory, 3 files
78.
78
Premier programme WebAssembly: Hello World
Commençons donc avec un traditionnel « Hello world » afin de se faire la main.
Installation du compilateur
Étant donné que l'on va devoir compiler un programme C vers WebAssembly, on va devoir installer un
compilateur qui, dans notre cas, sera Emscripten.
Pour Linux, un paquet est disponible sur la plupart des distributions. Par exemple, il est possible
de l'installer sous Ubuntu (à partir de la 22.04) à l'aide de la commande suivante : sudo apt install
emscripten (cela installera les packages lld et llvm).
Pour macOS, il y a un paquet Homebrew.
Pour Windows, le plus simple est soit de passer par WSL afin d'utiliser
le paquet pour Linux, soit de passer par Chocolatey pour une installation
native.
Pour les autres systèmes ou si vous souhaitez utiliser d'autres méthodes
d'installation, vous pouvez consulter la documentation officielle
79.
79
Écriture de notreprogramme
Passons maintenant à l'écriture de notre premier programme.
Nous allons coder les parties WebAssembly en C en commencant par créer un fichier
nommé "hello.c" et y placer le code suivant :
#include <stdio.h>
int main() {
puts("Hello LinuX Maine");
return 0;
}
80.
80
Compilation du programme
Sion voulait compiler ce programme de manière classique pour notre système, on pourrait le faire avec la
commande suivante :
$ gcc hello.c -o hello
Eh bien pour le compiler pour WebAssembly, la commande n'est pas très
différente :
$ emcc hello.c -o hello.html
Une fois compilé, on se retrouve avec les trois fichiers suivants :
hello.html : une page HTML générée par Emscripten et qui fera tourner notre
application,
hello.js : du code JavaScript faisant la liaison entre notre application
WebAssembly et la page Web,
hello.wasm : le fichier binaire contenant le code de notre application
WebAssembly.
81.
81
Lancer l'application dansle navigateur
Si vous ouvrez le fichier "hello.html" directement avec votre navigateur, vous vous apercevrez
rapidement que rien ne fonctionne. Si vous avez la curiosité d'ouvrir la console JavaScript, vous pourrez
y voir une erreur similaire à celle-ci :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at
file:///.../hello.wasm. (Reason: CORS request not http).
failed to asynchronously prepare wasm: [object ProgressEvent]
warning: Loading from a file URI (file:///.../hello.wasm) is not supported in most browsers. See
https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-do
es-my-program-stall-in-downloading-or-preparing
82.
82
Lancer l'application dansle navigateur
Le script de "hello.js" essaye en effet de télécharger "hello.wasm" mais il ne peut bien évidemment pas accéder aux fichiers sur le disque dur pour des raisons de
sécurité.
Pour résoudre ce problème, il va falloir servir les fichiers à l'aide d'un serveur HTTP. Le plus simple pour le moment c'est d'ouvrir une console dans le dossier
contenant nos fichiers puis de lancer le serveur HTTP intégré à Python :
$ cd dossier/de/mon/projet/
$ python3 -m http.server
On peut ensuite se rendre à l'adresse
"http://localhost:8000/hello.html"
à l'aide de votre navigateur :
83.
83
Plus d'options decompilation
Il existe une option de compilation qui peut nous éviter d'avoir à lancer un serveur HTTP : -
sSINGLE_FILE.
Cette option fait en sorte que tout se retrouve dans un unique fichier et résout donc nos problèmes de
téléchargement lorsque l'on ouvre la page HTML directement avec le navigateur.
La commande de compilation devient donc :
$ emcc -sSINGLE_FILE hello.c -o hello.singlefile.html
C'est tout de suite beaucoup plus pratique ! 😁️
96
But
Chargement d’une imagejpeg depuis une page html et effectue une
fonction de seuillage implémenté en C++ (threshold) sur les
composantes rgb de l’image et envoie le rendu dans un canvas.
97.
97
Listing des fichiers
❯cd array-and-tab/
❯ tree
├── image.jpg
├── index.html
├── Makefile
├── script.js
└── threshold.c
101
BINARYEN
Binaryen est unebibliothèque d’infrastructure de compilation et d’outillage pour
WebAssembly, écrite en C++. Elle vise à rendre la compilation vers WebAssembly
simple, rapide et efficace :
Site officiel (github) : https://github.com/WebAssembly/binaryen/releases/
Example avec wasm-opt qui peut servir a compresser un binaire wasm de façon a
réduire la taille de la partie en bytecode :
$ wasm-opt -O3 --all-features "${WASM_FILE}" -o "$
{WASM_COMPRESSED_PATH}"
104
WasmLinux
Démo : https://wasmlinux-demo.pages.dev/
Cliquezsur le terminal ci-dessus, puis tapez « ls », puis appuyez
deux fois sur Entrée.
La seule application disponible actuellement est BusyBox. Vous
pouvez également exécuter d'autres commandes, comme vi,
dmesg, ifconfig, lo up, ping 127.0.0.1 ou même top. Pour obtenir
la liste des commandes disponibles, tapez « busybox ».
Projet :
https://github.com/lkl/linux
https://wasmlinux-demo.pages.dev/
https://github.com/okuoku/wasmlinux-project
106
WasmLinux
Le protocole d'appelsystème provisoire est intégré aux correctifs Musl et implémenté dans le code
source du runner. Il s'agit simplement d'un export Wasm, dont les noms définitifs seront obtenus
ailleurs. Le code utilisateur ne doit pas appeler l'export directement et il est recommandé d'utiliser
la bibliothèque libc.
Lors de l'appel système de l'utilisateur, le runner appelle le noyau via son export Wasm, lui-même
exporté depuis le noyau. Actuellement, wasm2c est le seul moteur Wasm pris en charge par le
runner. Le runner connaît le nombre d'arguments des appels système et l'ajuste si nécessaire.
L'appel d'une fonction C avec un nombre d'arguments correct est une exigence stricte de Wasm.
Le runner dispose de la fonctionnalité « pseudo inetd » qui invoque un processus lors d'une
connexion entrante et relaie les E/S des paires de sockets vers le système hôte. Le backend d'E/S
de l'hôte est intégré à la bibliothèque miniio et, sur PC, utilise libuv. Sur navigateur, il dispose d'un
stub dédié, réservé à l'hôte local, implémenté sur le pthread de l'hôte. Pour communiquer avec le
système WasmLinux, BusyBox telnetd sera utilisé. Sur PC, un client Telnet classique (par exemple,
PuTTY) fonctionnera. Sur navigateur, notre propre client Telnet minitelnet, implémenté sur miniio,
sera utilisé. Minitelnet suppose que l'environnement hôte prend en charge le protocole PTY de type
Linux et est implémenté avec xterm-pty sur cette page.
107.
107
WasmLinux
WasmLinux possède plusieursfonctionnalités non implémentées.
À savoir :
L'envoi asynchrone de signaux. Nous devons donc interrompre read(2)
manuellement. C'est pourquoi une touche Entrée supplémentaire est requise pour
chaque commande.
Il s'agit toujours d'un noyau NOMMU(uClinux) ; sans mmap(2), nous n'avons donc
pas non plus fork(2).
En fait, le noyau WasmLinux est simplement un exécutable Wasm contenant LKL
(bibliothèque du noyau Linux – bibliothèque du noyau Linux en mode utilisateur). Il
n'y a donc pas de code « en mode noyau » à proprement parler. Nous
implémenterons éventuellement des émulations de signaux mmap ou POSIX, mais
je ne pense pas que WasmLinux deviendra une véritable architecture Linux.
108.
108
Lkl / linux
LKL(Linux Kernel Library) vise à permettre la réutilisation maximale du code du
noyau Linux, avec un minimum d'efforts et une maintenance réduite.
Parmi les exemples d'utilisation de LKL, on peut citer : la création d'applications en
espace utilisateur (exécutées sous Linux et d'autres systèmes d'exploitation) capables
de lire ou d'écrire sur les systèmes de fichiers Linux ou d'utiliser la pile réseau Linux ; la
création de pilotes noyau pour d'autres systèmes d'exploitation capables de lire les
systèmes de fichiers Linux ; la prise en charge des chargeurs de démarrage pour la
lecture et l'écriture des systèmes de fichiers Linux ; etc.
Avec LKL, le code du noyau est compilé dans un fichier objet directement lié par les
applications. L'API proposée par LKL repose sur l'interface d'appel système Linux.
LKL est implémenté comme un port d'architecture dans arch/lkl. Il utilise les opérations
hôtes définies par l'application ou une bibliothèque hôte (tools/lkl/lib).
109.
109
CERVUS
Cervus implémente un« mode utilisateur » WebAssembly sur le
noyau Linux (qui tente de suivre la spécification CommonWA),
permettant aux applications wasm de s'exécuter directement dans
l'anneau 0, tout en garantissant la sécurité.
112
bareDOOM is apatchset for the barebox bootloader that integrates DOOM with
the available barebox frameworks for framebuffer, input, file system and so
on ... etc. This allows it to run everywhere where barebox is running, be it on a
x86 laptop under UEFI, on industrial machinery or even a RISC-V emulator
compiled to WebAssembly.
https://github.com/a3f/bareDOOM
https://engineering.linecorp.com/en/blog/liff-tic-80
114
Glossaire
Binaryen
Compilateur de bytecodesou représentations textuelles en code wasm binaire exécutable. Asm2wasm utilise binaryen pour compiler Asm.js en wasm. s2wasm l'utilise
pour compiler le bitcode LLVM en wasm. Wasm-as compile une s-expression en binaire wasm. Binaryen dispose aussi d'un interpréteur de code wasm
Liste des outils de Binaryen.
Emscriptem
Outil conçu par Mozilla pour compiler C++ ou autre langage en JavaScript, Asm.js ou WebAssembly selon les directives de compilation.
S-Expression (Symbolic Expression)
Format de code textuel organisé comme un programme Lisp. WebAssembly dispose de deux représentations textuelle, l'une en s-expression, l'autre procédurale dite
linéaire.
Exemple d'une s-expression: (module
(func $addTwo (param i32 i32) (result i32)
get_local 0
get_local 1
i32.add)
(export "addTwo" (func $addTwo)))
115.
115
Glossaire
Wasm
Abbréviation pour WebAssembly.S'écrit en minuscules avec la première lettre capitalisée.
MVP (Minimal Viable Product)
Produit minimum viable pour que wasm soit utilisable par une application. Vous rencontrerez souvent ce terme dans la
documentation et il désigne l'implémentation actuelle dans les navigateurs en attendant un produit plus complet. MVP à des
possibilités équivalentes à celles d'Asm.js.
WABT (WebAssembly Binary Toolkit)
Suite d'outils pour wasm qui comprend: wast2wasm, wasmdump, wasm-interp, wastr-desugar, wasm-link.
Liste des outils de WABT.
Wast
Abbréviation pour "WebAssembly Text Format", format textuel de wasm. Ce n'est pas un acronyme et ne s'écrit pas en
majuscule. Le fichier wast contient une s-expression et a l'extension .wast.
De nombreux outils produisent du code binaire à partir de code wast: wast2wasm qui peut aussi l'afficher au fomat
linéaire, wasm-interp qui l'interprète, binaryen, le backend LLVM.
WAVM ( WebAssembly Virtual Machine)
Cet outil est la machine virtuelle de wasm telle qu'incluse dans les navigateurs, mais détachée pour être utilisée de
façon indépendante. On peut aussi utiliser Node si le code wasm est préparé pour s'exécuter avec JavaScript comme c'est le
cas quand il est généré par Emscriptem.