Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-63925

WebAssembly: dynamic linking and dlopen

    XMLWordPrintable

Details

    Description

      What is the benefit? Why is this valuable?

      Issue: Dynamic linking could provide smaller downloads by only downloading the modules that are needed. Also needed for binary QML and shared libraries that have been requested by several customers.

      What are common use cases?

      Solution: Qt WebAssembly provides dynamic linking support to allow optimising download sizes and allows shared libraries.

      Technical information

      External Documentation

      WebAssembly supports modules and dynamic linking. These are low-level APIs

      Emscripten supports dynamic linking with compiler options and a run-time API.

      Dynamic Linking for Qt

      Emscripten supports dividing programs into one main module and several side modules, where the main module contains all system libraries. This is controlled by setting -s MAIN_MODULE=1/-s SIDE_MODULE=1 on the linker line.

      There are two choices for the main module:

      • Qt Core
      • The application binary

      The main module then needs to link/include all needed system libraries. It's possible to set EMCC_FORCE_STDLIBS=1 (on the environment) to enable "kitchen sink" mode, but this option is currently broken.

      Setting MAIN_MODULE=1 makes emscripten not generate wasm fetching code: qtloader.js should either implement Module.readBinary or fetch the main wasm module and set Module.wasmBinary. (Going one step further we should look into compiling the wasm file from qtloader.js as well in order to enable streaming compiles. This is done by setting Module.instantiateWasm)

      Side modules are loaded by setting Module.dynamicLibraries to an array of wasm file paths (not binaries!), which emscripten will fetch and compile. The module list can either be created manually or be provided by the build system (we'll aim to support both).

      dlopen for Qt

      Emscripten supports dlopen()ning side modules. The dlopen implementation expects to find the side module wasm binary on the filesystem: dlopen("foo.wasm") reads "/foo.wasm" and so on.

      The easiest way to handle this is to preload the wasm files onto the (default-enabled) MEMFS file system in qtloader.js. All modules must then be specified at load time. This runs somewhat counter to the dynamic nature of dlopen. There are however other possible issues that prevents true dlopen-any-file:

      • dlopen is synchronous API, which is hard/impossible to implement on the main thread
      • The callers of dlopen may expect it to return in a reasonable time (and not wait for a download)

      Prototypes and implementation

      Minimal emscripten prototype: emscripten_dynamic

      Build Qt libs as wasm modules WIP: https://codereview.qt-project.org/230044

      Load libQtCore.wasm prototype: https://github.com/msorvig/qt-webassembly-examples/tree/master/core_dynamic

      Qt Implementation Tasks

      Attachments

        Issue Links

          Activity

            People

              lpotter Lorn Potter
              lpotter Lorn Potter
              Veli-Pekka Heinonen Veli-Pekka Heinonen
              Votes:
              16 Vote for this issue
              Watchers:
              30 Start watching this issue

              Dates

                Created:
                Updated: