ofz#45081 check font length
[LibreOffice.git] / wasm-qt / README.md
blob2591d2de297d404e0dc130b6752aa67db09e87e4
1 # Support for Emscripten Cross Build
3 This module provides support for emscripten cross build
5 ## Status
7     $ make
8     $ emrun --serve_after_close instdir/program/ui-previewer.html
10 The `ui-previewer` "binary" will "crash" with memory alignment problems.
12 You can run the WASM mandelbrot Qt example, if you copy its HTML
13 and the qtloader.js from the Qt's example folder after build with:
15     $ emrun --serve_after_close workdir/LinkTarget/Executable/mandelbrot.html
17 REMINDER: Always start new tabs in the browser, reload might fail / cache!
20 ## Setup for the LO WASM build (with Qt)
22 We're using Qt 5.15 with the officially supported emscripten v1.39.8.
23 But there are several potential problems with threads and exceptions, so this will likely
24 change later to a newer emscripten.
26 Qt WASM is not yet used with LO, just if you're wondering!
28 - See below under Docker build for another build option
30 ### Setup emscripten
32 <https://emscripten.org/docs/getting_started/index.html>
34     git clone https://github.com/emscripten-core/emsdk.git
35     ./emsdk install 1.39.8
36     ./emsdk activate --embedded 1.39.8
38 Example `bashrc` scriptlet:
40     EMSDK_ENV=$HOME/Development/libreoffice/git_emsdk/emsdk_env.sh
41     [ -f "$EMSDK_ENV" ] && \. "$EMSDK_ENV" 1>/dev/null 2>&1
43 ### Setup Qt
45 <https://doc.qt.io/qt-5/wasm.html>
47 I originally build the Qt 5.15 branch, but probably better to build a tag like v5.15.2.
49 So:
51     git clone https://github.com/qt/qt5.git
52     cd qt5
53     git checkout v5.15.2
54     ./init-repository
55     ./configure -xplatform wasm-emscripten -feature-thread -compile-examples -prefix $PWD/qtbase
56     make -j<CORES> module-qtbase module-qtdeclarative
58 Building with examples will break with some of them, but at that point Qt already works.
60 At some point Qt configure failed for me with:
62 "Checking for target architecture... Project ERROR: target architecture detection binary not found."
64 What seems to have fixed this was to run "emsdk activate 1.39.8" again.
66 Current Qt fails to start the demo webserver: <https://bugreports.qt.io/browse/QTCREATORBUG-24072>
68 Use `emrun --serve_after_close` to run Qt WASM demos
70 Enabling multi-thread support in Firefox is a bit of work with older versions:
72 - <https://bugzilla.mozilla.org/show_bug.cgi?id=1477743#c7>
73 - <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support>
74 - <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer>
77 ### Setup LO
79 `autogen.sh` is patched to use emconfigure. That basically sets various environment vars,
80 especially `EMMAKEN_JUST_CONFIGURE`, which will create the correct output file names, checked by
81 `configure` (`a.out`).
83 There's a distro config for WASM (work in progress), that gets your
84 defaults right (and currently disables a ton of 3rd party stuff which
85 is not essential).
87 Recommended configure setup is thusly:
89 * grab defaults
90     `--with-distro=LibreOfficeWASM32`
92 * local config
93     `QT5DIR=/dir/of/git_qt5/qtbase`
95 * if you want to use ccache on both sides of the build
96     `--with-build-platform-configure-options=--enable-ccache`
97     `--enable-ccache`
99 ### Using Docker to cross-build with emscripten
101 If you prefer a controlled environment (sadly emsdk install/activate
102 is _not_ stable over time, as e.g. nodejs versions evolve), that is
103 easy to replicate across different machines - consider the docker
104 images we're providing.
106 Config/setup file see
107 <https://git.libreoffice.org/lode/+/ccb36979563635b51215477455953252c99ec013>
111     docker-compose build
113 in the lode/docker dir to get the container prepared. Run
115     PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder
117 to perform an actual `srcdir != builddir` build; the container mounts
118 checked-out git repo and output dir via `docker-compose.yml` (so make
119 sure the path names there match your setup):
121 The lode setup expects, inside the lode/docker subdir, the following directories:
123 - core (`git checkout`)
124 - workdir (the output dir - gets written into)
125 - cache (`ccache tree`)
126 - tarballs (external project tarballs gets written and cached there)
129 ## Ideas for an UNO bridge implementation
131 My post to Discord #emscripten:
133 "I'm looking for a way to do an abstract call
134 from one WASM C++ object to another WASM C++ object, so like FFI / WebIDL,
135 just within WASM. All my code is C++ and normally I have bridge code, with
136 assembler to implement the function call /RTTI and exception semantics of the
137 specified platform. Code is at
138 <https://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno>.
139 I've read a bit about `call_indirect` and stuff, but I don't have yet a good
140 idea, how I could implement this (and  there is an initial feature/wasm branch
141 for the interested). I probably need some fixed lookup table, like on iOS,
142 because AFAIK you can't dynamically generate code in WASM. So any pointers or
143 ideas for an implementation? I can disassemble some minimalistic WASM example
144 and read clang code for `WASM_EmscriptenInvoke`, but if there were some
145 standalone code or documentation I'm missing, that would be nice to know."
147 We basically would go the same way then the other backends. Write the bridge in
148 C++, which is probably largely boilerplate code, but the function call in WAT
149 (<https://github.com/WebAssembly/wabt>) based on the LLVM WASM calling
150 conventions in `WASM_EmscriptenInvoke`. I didn't get a reply to that question for
151 hours. Maybe I'll open an Emscripten issue, if we really have to implement
152 this.
154 WASM dynamic dispatch:
156 - <https://fitzgeraldnick.com/2018/04/26/how-does-dynamic-dispatch-work-in-wasm.html>
159 ## Workaround for eventual clang WASM compiler bug
161 ````
162 sc/source/core/data/attarray.cxx:378:44: error: call to member function 'erase' is ambiguous
163                         aNewCondFormatData.erase(nIndex);
164                         ~~~~~~~~~~~~~~~~~~~^~~~~
165 include/o3tl/sorted_vector.hxx:86:15: note: candidate function
166     size_type erase( const Value& x )
167               ^
168 include/o3tl/sorted_vector.hxx:97:10: note: candidate function
169     void erase( size_t index )
170 ````
172 This is currently patched by using `x.erase` (`x.begin() + nIndex`).
174 There shouldn't be an ambiguity, because of "[WebAssembly] Change size_t to `unsigned long`."
175 <https://reviews.llvm.org/rGdf07a35912d78781ed6a62a7c032bfef5085a4f5#change-IrS9f6jH6PFq>,
176 from "Jul 23 2018" which pre-dates the emscripten tag 1.39.8 from 02/14/2020 by ~1.5y.
179 ## Tools for problem diagnosis
181 * `nm -s` should list the symbols in the archive, based on the index generated by ranlib.
182   If you get linking errors that archive has no index.
185 ## Emscripten filesystem access with threads
187 This is closed, but not really fixed IMHO:
189 - <https://github.com/emscripten-core/emscripten/issues/3922>
192 ## Dynamic libraries `/` modules in emscripten
194 There is a good summary in:
196 - <https://bugreports.qt.io/browse/QTBUG-63925>
198 Summary: you can't use modules and threads.
200 This is mentioned at the end of:
202 - <https://github.com/emscripten-core/emscripten/wiki/Linking>
204 The usage of `MAIN_MODULE` and `SIDE_MODULE` has other problems, a major one IMHO is symbol resolution at runtime only.
205 So this works really more like plugins in the sense of symbol resolution without dependencies `/` rpath.
207 There is some clang-level dynamic-linking in progress (WASM dlload). The following link is already a bit old,
208 but I found it a god summary of problems to expect:
210 - <https://iandouglasscott.com/2019/07/18/experimenting-with-webassembly-dynamic-linking-with-clang/>
213 ## Mixed information, links, problems, TODO
215 More info on Qt WASM emscripten pthreads:
217 - <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support>
219 WASM needs `-pthread` at compile, not just link time for atomics support. Alternatively you can provide
220 `-s USE_PTHREADS=1`, but both don't seem to work reliable, so best provide both.
221 <https://github.com/emscripten-core/emscripten/issues/10370>
223 The output file must have the prefix .o, otherwise the WASM files will get a
224 `node.js` shebang (!) and ranlib won't be able to index the library (link errors).
226 Qt with threads has further memory limit. From Qt configure:
227 ````
228 Project MESSAGE: Setting PTHREAD_POOL_SIZE to 4
229 Project MESSAGE: Setting TOTAL_MEMORY to 1GB
230 ````
232 You can actually allocate 4GB:
234 - <https://bugzilla.mozilla.org/show_bug.cgi?id=1392234>
236 LO uses a nested event loop to run dialogs in general, but that won't work, because you can't drive
237 the browser event loop. like VCL does with the system event loop in the various VCL backends.
238 Changing this will need some major work (basically dropping Application::Execute).
240 But with the know problems with exceptions and threads, this might change:
242 - <https://github.com/emscripten-core/emscripten/pull/11518>
243 - <https://github.com/emscripten-core/emscripten/issues/11503>
244 - <https://github.com/emscripten-core/emscripten/issues/11233>
245 - <https://github.com/emscripten-core/emscripten/issues/12035>
247 We're also using emconfigure at the moment. Originally I patched emscripten, because it
248 wouldn't create the correct a.out file for C++ configure tests. Later I found that
249 the `emconfigure` sets `EMMAKEN_JUST_CONFIGURE` to work around the problem.
251 ICU bug:
253 - <https://github.com/emscripten-core/emscripten/issues/10129>
255 Alternative, probably:
257 - <https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl>
259 There is a wasm64, but that still uses 32bit pointers!
261 Old outdated docs:
263 - <https://wiki.documentfoundation.org/Development/Emscripten>
265 Reverted patch:
267 - <https://cgit.freedesktop.org/libreoffice/core/commit/?id=0e21f6619c72f1e17a7b0a52b6317810973d8a3e>
269 Generally <https://emscripten.org/docs/porting>:
271 - <https://emscripten.org/docs/porting/guidelines/api_limitations.html#api-limitations>
272 - <https://emscripten.org/docs/porting/files/file_systems_overview.html#file-system-overview>
273 - <https://emscripten.org/docs/porting/pthreads.html>
274 - <https://emscripten.org/docs/porting/emscripten-runtime-environment.html>
276 This will be interesting:
278 - <https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-an-event-loop>
280 This didn't help much yet:
282 - <https://github.com/emscripten-ports>
284 Emscripten supports standalone WASI binaries:
286 - <https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone>
287 - <https://www.qt.io/qt-examples-for-webassembly>
288 - <http://qtandeverything.blogspot.com/2017/06/qt-for-web-assembly.html>
289 - <http://qtandeverything.blogspot.com/2020/>
290 - <https://emscripten.org/docs/api_reference/Filesystem-API.html>
291 - <https://discuss.python.org/t/add-a-webassembly-wasm-runtime/3957/12>
292 - <http://git.savannah.gnu.org/cgit/config.git>
293 - <https://webassembly.org/specs/>
294 - <https://developer.chrome.com/docs/native-client/>
295 - <https://emscripten.org/docs/getting_started/downloads.html>
296 - <https://github.com/openpgpjs/openpgpjs/blob/master/README.md#getting-started>
297 - <https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API>
298 - <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-intro.md>
299 - <https://www.ip6.li/de/security/x.509_kochbuch/openssl-fuer-webassembly-compilieren>
300 - <https://emscripten.org/docs/introducing_emscripten/about_emscripten.html#about-emscripten-porting-code>
301 - <https://emscripten.org/docs/compiling/Building-Projects.html>