Outils pour utilisateurs

Outils du site


prog:emscripten

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
prog:emscripten [2021/07/24 11:38] – Ajout de "WebAssembly.instantiateStreaming" rootprog:emscripten [2022/07/18 12:49] (Version actuelle) – [Compilation] : ajout de "Pour le debug" root
Ligne 1: Ligne 1:
-=====Téléchargement et installation=====+=====Téléchargement et installation et mise à jour=====
 <code bash> <code bash>
 git clone --depth 1 https://github.com/emscripten-core/emsdk.git git clone --depth 1 https://github.com/emscripten-core/emsdk.git
Ligne 17: Ligne 17:
 C'est donc un outil plutôt adapté pour créer des librairies, même s'il est possible de créer des programmes entiers avec. C'est donc un outil plutôt adapté pour créer des librairies, même s'il est possible de créer des programmes entiers avec.
  
-[[https://pascalpares.appspot.ovh/webassembly-for-javascript-developers/|https://pascalpares.appspot.ovh/webassembly-for-javascript-developers/]] {{ :prog:emscripten:an_introduction_to_webassembly_for_javascript_developers_2021-07-24_11_04_06_.html |Archive du 21/04/2021 le 24/07/2021}}+[[https://pascalpares.appspot.ovh/webassembly-for-javascript-developers/|An Introduction to WebAssembly for JavaScript Developers]] {{ :prog:emscripten:an_introduction_to_webassembly_for_javascript_developers_2021-07-24_11_04_06_.html |Archive du 21/04/2021 le 24/07/2021}} 
 + 
 +[[https://developers.google.com/web/updates/2018/03/emscripting-a-c-library|Emscripting a C library to Wasm]] {{ :prog:emscripten:emscripting_a_c_library_to_wasm_web_google_developers_8_4_2021_10_04_21_am_.html |Archive du 31/07/2020 le 04/08/2021}} 
 +====Compilation==== 
 + 
 +[[https://emscripten.org/docs/tools_reference/emcc.html|Options de compilation]] 
 + 
 +Liste des [[https://github.com/emscripten-core/emscripten/blob/main/src/settings.js|settings]] (''-s''). 
 + 
 +Pour réduire la taille du wrapper: 
 + 
 +  * ''-s ENVIRONMENT=web,worker'' : réduire les fonctionnalités en supprimant le support de node.js. Réduit très légèrement la taille du wrapper mais enlève des dépendances externes. Utile pour la mise en production dans un projet Angular. Ne doit pas être enlevé si les tests exécutés par node.js, 
 +  * ''%%--%%closure 1 -s MODULARIZE=1'' : ''closure'' fait de la minification. Afin d'éviter les effets de bord avec d'autres variables globales en Javascript, il est forcement recommandé d'encapsuler le code dans un module, 
 +  * ''%%--no-entry%%'' : désactive la fonction ''main'' qui est inutile si la sortie Javascript est une librairie et non une application indépendante, 
 +  * ''-s ASSERTIONS=0'' : désactive des sécurités. 
 + 
 +Pour réduire la taille du wasm: 
 + 
 +  * ''-flto'' : active l'optimisation globale du lieur, 
 +  * ''-DNDEBUG'' : désactive le debug. N'impacte pas le code emscripten mais uniquement le code utilisateur, 
 +  * ''-Oz'' : le bytecode est optimisé pour réduire la taille. 
 +  * ''-s MALLOC=%%'emmalloc'%%'' : utilise une version de malloc réduite en fonctionnalité mais spécifique à emscripten. 
 + 
 +Pour le debug: 
 +  * ''-O0'' : aucune optimisation. 
 +  * ''-g'' : toutes les informations de débogage, 
 +  * ''-s ASSERTIONS=2'' : toutes les assertions à l'exécution, 
 +  * ''-s DEMANGLE_SUPPORT=1'' : affichage des symboles en cas d'affichage de la trace par le compilateur, 
 +  * ''%%--%%emit-symbol-map'' : génère un fichier ''.map'', 
 +  * ''-gsource-map'' : génère un ''.map'' compatible LLVM pour déboguer avec Chrome, 
 +  * ''%%--source-map-base http://localhost:4200/assets/%%'' : codage en dur du chemin vers le fichier ''.wasm'' uploadé et non du chemin dans l'ordinateur. 
 + 
 +Pour mémo, le tableau des résultats. La comparaison des options ''-Ox'' se fait par rapport à ''-O0''. Puis, les options suivantes s'accumulent avec l'option -Oz. Dans mon cas, ''-O2'' réduit mieux la taille que ''-Oz''. A confirmer sur de plus gros projets. 
 + 
 +^Option^gros js^gros wasm^petit js^petit wasm^gros js^gros wasm^petit js^petit wasm^ 
 +|''-O0''|349801|888030|217442|59279|-|-|-|-| 
 +|''-O2''|349801|841160|214892|26971|0%/0o|-5,3%/-46870o|-1,2%/-2550o|-54,5%/-32308o| 
 +|''-O3''|349801|841966|214892|26971|0%/0o|-5,2%/-46064o|-1,2%/-2550o|-54,5%/-32308o| 
 +|''-Os''|349801|842814|217442|34746|0%/0o|-5,1%/-45216o|0%/0o|-41,4%/-24533o| 
 +|''-Oz''|349801|842838|217442|34739|0%/0o|-5,1%/-45192o|0%/0o|-41,4%/-24540o| 
 +|''-s ENVIRONMENT=web,worker''|N/A|N/A|214984|34739|N/A|N/A|-1,1%/-2458o|0%/0o| 
 +|''%%--%%closure 1''|158780|842838|118137|34739|-54,6%/-191021o|0%/0o|-45%/-96847o|0%/0o| 
 +|''%%--%%no-entry''|158223|842838|117580|34739|-0,4%/-557o|0%/0o|-0,5%/-557o|0%/0o| 
 +|''-flto''|158223|835253|117580|31867|0%/0o|-0,9%/-7585o|0%/0o|-8,3%/-2872o| 
 +|''-s ASSERTIONS=0''|67927|835110|34944|31510|-57,1%/-90296o|0%/-143o|-70,3%/-82636o|-1,1%/-357o| 
 +|''-DNDEBUG''|67927|835110|34944|31510|0%/0o|0%/0o|0%/0o|0%/0o| 
 +|''-s INVOKE_RUN=0''|67927|835110|34944|31510|0%/0o|0%/0o|0%/0o|0%/0o| 
 +|''-s MALLOC='emmalloc%%'%%''|67927|826803|34944|23703|0%/0o|-1%/-8307o|0%/0o|-24,8%/-7807o|
  
 ====vcpkg==== ====vcpkg====
Ligne 180: Ligne 227:
 </code> </code>
  
-====WebAssembly.instantiateStreaming====+====WebAssembly.instantiateStreaming en TypeScript==== 
 + 
 +  * Sans le wrapper ''.js''
  
 Il est possible d'utiliser ''WebAssembly.instantiateStreaming'' pour charger le fichier ''.wasm'' sans passer par le fichier ''.js'' qui sert de wrapper. Il est possible d'utiliser ''WebAssembly.instantiateStreaming'' pour charger le fichier ''.wasm'' sans passer par le fichier ''.js'' qui sert de wrapper.
Ligne 199: Ligne 248:
 } }
  
 +@Component({
 +  selector: 'app-main',
 +  templateUrl: './main.component.html',
 +  styleUrls: ['./main.component.css'],
 +})
 export class MainComponent implements OnInit { export class MainComponent implements OnInit {
   private exports?: MyApi;   private exports?: MyApi;
Ligne 220: Ligne 274:
 Et cette fonction javascript est déclarée dans le fichier .js générée par emscripten. L'utilisation du fichier .js comme wrapper sera probablement nécessaire. Et cette fonction javascript est déclarée dans le fichier .js générée par emscripten. L'utilisation du fichier .js comme wrapper sera probablement nécessaire.
  
 +  * Avec le wrapper ''.js''
 +
 +Il faut commencer par autoriser l'utilisation du code javascript.
 +
 +<file javascript tsconfig.json>
 +{
 +  "compilerOptions": {
 +    ...,
 +    "allowJs": true,
 +    "esModuleInterop": true
 +  }
 +}
 +</file>
 +
 +Ensuite, utiliser le code TypeScript suivant :
 +
 +<file javascript main.component.ts>
 +import { Component, OnInit } from '@angular/core';
 +import * as Module from './jessica';
 +
 +@Component({
 +  selector: 'app-main',
 +  templateUrl: './main.component.html',
 +  styleUrls: ['./main.component.css'],
 +})
 +export class MainComponent implements OnInit {
 +  private instance?: any;
 +  constructor() {
 +    Module.default().then(async (instance: any) => {
 +      this.instance = instance;
 +      const vert1 = new this.instance.VerticalEccentricRaw();
 +      const vert2 = vert1.setE(0.2);
 +      console.log('getE ' + vert2.getE());
 +    });
 +  }
 +
 +  ngOnInit(): void {}
 +}
 +</file>
 +
 +  * Compatibilité avec ''node.js''
 +
 +Il est possible que le compilateur râle si on utilise des fonctionnalités de type bindings.
 +
 +<WRAP center round info 60%>
 +Si la compatibilité avec node.js n'est pas indispensable, on peut tout simplement désactiver via l'option de compilation ''-s ENVIRONMENT=web,worker''. Cette option ne réduit pas la taille du fichier ''.wasm'' et seulement de façon marginal le ''.js'' mais cela enlève les dépendances spécifiques à ''node.js''.
 +</WRAP>
 +
 +<code>
 +BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
 +This is no longer the case. Verify if you need this module and configure a polyfill for it.
 +
 +If you want to include a polyfill, you need to:
 +        - add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
 +        - install 'path-browserify'
 +If you don't want to include a polyfill, you can use an empty module like this:
 +        resolve.fallback: { "path": false }
 +</code>
 +
 +Pour les modules ''path'', ''crypto'' et ''stream'', on peut utiliser une librairie annexe pour résoudre ce problème :
 +
 +<file javascript tsconfig.json>
 +{
 +  "compilerOptions": {
 +    "paths": {
 +      "path": ["./node_modules/path-browserify"],
 +      "crypto": ["./node_modules/crypto-browserify"],
 +      "stream": ["./node_modules/stream-browserify"]
 +    },
 +  }
 +}
 +</file>
 +
 +et installer les dépendances :
 +
 +<code bash>
 +npm i path-browserify -D
 +npm i crypto-browserify -D
 +npm i stream-browserify -D
 +</code>
 +
 +[[https://github.com/angular/angular-cli/issues/20819#issuecomment-856003399|BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.]] {{ :prog:emscripten:breaking_change_webpack_5_used_to_include_polyfills_for_node.js_core_modules_by_default._issue_20819_angular_angular-cli_2021-07-24_20_06_22_.html |Archive du 17/05/2021 le 24/07/2021}}
 +
 +Apparemment, il existe un paquet qui résout tous ces problèmes en une fois : [[https://github.com/Richienb/node-polyfill-webpack-plugin|node-polyfill-webpack-plugin]]. Cela résout les problèmes pour les modules ''assert'', ''buffer'', ''console'', ''constants'', ''crypto'', ''domain'', ''events'', ''http'', ''https'', ''os'', ''path'', ''punycode'', ''process'', ''querystring'', ''stream'', ''_stream_duplex'', ''_stream_passthrough'', ''_stream_readable'', ''_stream_transform'', ''_stream_writable'', ''string_decoder'', ''sys'', ''timers'', ''tty'', ''url'', ''util'', ''vm'', ''zlib''.
 +
 +Par contre, il n'existe pas de module externe pour la fonctionnalité ''fs''. Dans ce cas, le compilateur ne vous proposera pas de solution :
 +
 +<code>
 +./projects/app-main/src/app/ui/main/jessica.js:380:30-43 - Error: Module not found: Error: Can't resolve 'fs' in '...\projects\app-main\src\app\ui\main'
 +</code>
 +
 +Dans ce cas, il faut désactiver le module. Les fonctions associées ne fonctionneront pas.
 +
 +<WRAP center round info 60%>
 +Il se peut que la compatibilité soient nécessaires pour les tests qui nécessitent node.js pour s'exécuter mais que TypeScript ne nécessite pas ces dépendances. Il est possible de tout désactiver pour TypeScript en les mettant tous à ''false'' dans la rubrique ''browser'' ci-dessous et sans installer les dépendances via ''npm''.
 +</WRAP>
 +
 +<file javascript package.json>
 +{
 +  ...,
 +  "browser": {
 +    "fs": false
 +  }
 +}
 +</file>
 +
 +[[https://github.com/angular/angular-cli/issues/8272#issuecomment-392777980|Error: Module not found: Error: Can't resolve 'fs']] {{ :prog:emscripten:error_module_not_found_error_can_t_resolve_fs_issue_8272_angular_angular-cli_2021-07-24_20_10_56_.html |Archive du 01/11/2017 le 24/07/2021}}
 =====Erreurs===== =====Erreurs=====
  
prog/emscripten.1627119537.txt.gz · Dernière modification : 2021/07/24 11:38 de root