blob: c42f9e5ca624e559530381b90c3053f7855acc7a [file] [log] [blame] [view]
Hosseind19299f2021-10-10 19:59:20 +02001# Support for Emscripten Cross Build
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +02002
Andrea Gelminib926ba62023-02-13 12:23:32 +01003This subdirectory provides support for building LibreOffice as WASM, with the Emscripten toolchain.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +02004
Tor Lillqvist187d3b62023-02-06 11:57:15 +02005You can build LibreOffice for WASM for two separate purposes: 1)
6Either to produce a WASM binary of LibreOffice as such, using Qt5 for
7its GUI, or 2) just compiling LibreOffice core ("LibreOffice
8Technology") to WASM without any UI for use in other software that
9provides the UI, like Collabora Online built as WASM.
Tor Lillqvist6f6b8792023-02-02 13:38:02 +020010
11The first purpose was the original reason for the WASM port and this
12document was originally written with that in mind. For the second
13purpose, look towards the end of the document for the section
14"Building headless LibreOffice as WASM for use in another product".
15
16## Status of LibreOffice as WASM with Qt
Hosseind19299f2021-10-10 19:59:20 +020017
Stephan Bergmann7d5c6252024-07-26 11:17:36 +020018Configure `--with-package-format=emscripten` to have `workdir/installation/LibreOffice/emscripten`
19populated with just the relevant files from `instdir`.
20
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010021The build generates a Writer-only LO build. You should be able to run either
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020022
Moritz Dugec8883292024-08-28 16:47:46 +020023 $ emrun --hostname 127.0.0.1 --serve_after_close workdir/installation/LibreOffice/emscripten/qt_soffice.html
24 $ emrun --hostname 127.0.0.1 --serve_after_close workdir/LinkTarget/Executable/qt_vcldemo.html
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020025
Hosseind19299f2021-10-10 19:59:20 +020026REMINDER: Always start new tabs in the browser, reload might fail / cache!
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020027
Hosseind19299f2021-10-10 19:59:20 +020028## Setup for the LO WASM build (with Qt)
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020029
Stephan Bergmann77ed3942025-11-21 14:19:21 +010030We're using Qt 5.15.2 with Emscripten 4.0.10. There are a bunch of Qt patches
Moritz Duge43070432024-04-03 12:04:04 +020031to fix the most grave bugs. Also there's rapid development in Emscripten, so
Andrea Gelmini38ed8102024-04-05 14:19:25 +020032using another version often causes arbitrary problems.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020033
Hosseind19299f2021-10-10 19:59:20 +020034- See below under Docker build for another build option
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020035
Hosseind19299f2021-10-10 19:59:20 +020036### Setup emscripten
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020037
Hosseind19299f2021-10-10 19:59:20 +020038<https://emscripten.org/docs/getting_started/index.html>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020039
Hosseind19299f2021-10-10 19:59:20 +020040 git clone https://github.com/emscripten-core/emsdk.git
Stephan Bergmann77ed3942025-11-21 14:19:21 +010041 ./emsdk install 4.0.10
42 ./emsdk activate 4.0.10
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020043
Hosseind19299f2021-10-10 19:59:20 +020044Example `bashrc` scriptlet:
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020045
Hosseind19299f2021-10-10 19:59:20 +020046 EMSDK_ENV=$HOME/Development/libreoffice/git_emsdk/emsdk_env.sh
47 [ -f "$EMSDK_ENV" ] && \. "$EMSDK_ENV" 1>/dev/null 2>&1
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020048
Hosseind19299f2021-10-10 19:59:20 +020049### Setup Qt
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020050
Hosseind19299f2021-10-10 19:59:20 +020051<https://doc.qt.io/qt-5/wasm.html>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020052
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010053Most of the information from <https://doc.qt.io/qt-6/wasm.html> is still valid for Qt5;
54generally the Qt6 WASM documentation is much better, because it incorporated many
55information from the Qt Wiki.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020056
Andrea Gelmini5ef2a7d2022-01-21 12:30:42 +010057FWIW: Qt 5.15 LTS is not maintained publicly and Qt WASM has quite a few bugs. Most
Tor Lillqvist52c37442022-12-14 21:38:08 +020058WASM fixes from Qt 6 are needed for Qt 5.15 too. Allotropia offers a Qt repository
59with the necessary patches cherry-picked.
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010060
Moritz Duge43070432024-04-03 12:04:04 +020061With "-opensource -confirm-license" you agree to the open source license.
62
Tor Lillqvist52c37442022-12-14 21:38:08 +020063 git clone https://github.com/allotropia/qt5.git
Hosseind19299f2021-10-10 19:59:20 +020064 cd qt5
Stephan Bergmann6e6451c2024-08-12 13:04:48 +020065 git checkout 5.15.2+wasm
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010066 ./init-repository --module-subset=qtbase
Stephan Bergmann22ce8ed2024-05-28 15:16:32 +020067 ./configure -opensource -confirm-license -xplatform wasm-emscripten -feature-thread -prefix <whatever> QMAKE_CFLAGS+=-sSUPPORT_LONGJMP=wasm QMAKE_CXXFLAGS+=-sSUPPORT_LONGJMP=wasm
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010068 make -j<CORES> module-qtbase
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020069
Stephan Bergmann6e6451c2024-08-12 13:04:48 +020070Note that `5.15.2+wasm` is a branch that is expected to contain further fixes as they become
71necessary.
72
Stephan Bergmann146fafa2024-08-07 15:01:25 +020073Do not include `-fwasm-exceptions` in the above `QMAKE_CXXFLAGS`, see
74<https://emscripten.org/docs/api_reference/emscripten.h.html#c.emscripten_set_main_loop> "Note:
75Currently, using the new Wasm exception handling and simulate_infinite_loop == true at the same time
76does not work yet in C++ projects that have objects with destructors on the stack at the time of the
77call." (Also see the EMSCRIPTEN-specific HACK in soffice_main, desktop/source/app/sofficemain.cxx,
78for what we need to do to work around that.)
79
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010080Optionally you can add the configure flag "-compile-examples". But then you also have to
81patch at least mkspecs/wasm-emscripten/qmake.conf with EXIT_RUNTIME=0, otherwise they will
82fail to run. In addition, building with examples will break with some of them, but at that
Moritz Duge43070432024-04-03 12:04:04 +020083point Qt already works and also most examples. Or just skip them. Other interesting flags
84might be "-nomake tests -no-pch -ccache".
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020085
Moritz Duge43070432024-04-03 12:04:04 +020086Linking takes quite a long time, because emscripten-finalize rewrites the whole WASM files with
87some options. This way the LO WASM possibly needs 64GB RAM. For faster link times add
88"-s WASM_BIGINT=1", change to ASSERTIONS=1 and use -g3 to prevent rewriting the WASM file and
89generating source maps (see emscripten.py, finalize_wasm, and avoid modify_wasm = True). This is
90just needed for Qt examples, as LO already uses the correct flags!
Hosseind19299f2021-10-10 19:59:20 +020091
Moritz Duge43070432024-04-03 12:04:04 +020092It's needed to install Qt5 to the chosen prefix. Else LO won't find all needed files in the
93right place. For installation you can do
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020094
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +010095 make -j<CORES> install
96or
97 make -j8 -C qtbase/src install_subtargets
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +020098
Hosseind19299f2021-10-10 19:59:20 +020099Current Qt fails to start the demo webserver: <https://bugreports.qt.io/browse/QTCREATORBUG-24072>
100
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +0100101Use `emrun --serve_after_close` to run Qt WASM demos.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200102
Stephan Bergmanne0178cf2024-08-18 15:45:26 +0200103Qt builds some 3rd-party libraries that it brings along (e.g., qt5/qtbase/src/3rdparty/freetype) and
104compiles its own code against the C/C++ include files of those 3rd-party libraries. But when we
105link LO, we link against our own versions of those libraries' archives (e.g.,
106workdir/UnpackedTarball/freetype/instdir/lib/libfreetype.a), not against the Qt ones (e.g.,
107$QT5DIR/lib/libqtfreetype.a). This mismatch between the include files that Qt is compiled against,
108vs. the archive actually linked in, seems to not cause issues in practice. (If it did, we could
109either try to make both Qt and LO link against e.g. -sUSE_FREETYPE from emscripten-ports, or we
Andrea Gelmini15651812024-08-19 07:53:53 +0200110could move Qt from a prerequisite to a proper external/qt5 LO module built during the LO build, and
Andrea Gelmini56c33b82024-08-19 07:53:12 +0200111hack its configuration to build against LO's external/freetype etc. The former approach, building Qt
Stephan Bergmanne0178cf2024-08-18 15:45:26 +0200112with -sUSE_FREETYPE, is even tried in qtbase/src/gui/configure.json, but apparently fails for
113reasons not studied further yet, cf. Qt's config.log.)
114
Hosseind19299f2021-10-10 19:59:20 +0200115### Setup LO
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200116
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +0100117`autogen.sh` is patched to use emconfigure. That basically sets various
118environment vars, especially `EMMAKEN_JUST_CONFIGURE`, which will create the
119correct output file names, checked by `configure` (`a.out`).
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200120
Jan-Marek Glogowski79365d62022-03-26 20:46:56 +0100121There's a distro config for WASM, but it just provides --host=wasm32-local-emscripten, which
122should be enough setup. The build itself is a cross build and the cross-toolset just depends
123on a minimal toolset (gcc, libc-dev, flex, bison); all else is build from source, because the
124final result is not depending on the build system at all.
Thorsten Behrensd7e5d192021-04-25 16:02:10 +0200125
126Recommended configure setup is thusly:
127
Hosseind19299f2021-10-10 19:59:20 +0200128* grab defaults
129 `--with-distro=LibreOfficeWASM32`
Thorsten Behrensd7e5d192021-04-25 16:02:10 +0200130
Hosseind19299f2021-10-10 19:59:20 +0200131* local config
Moritz Duge43070432024-04-03 12:04:04 +0200132 `QT5DIR=/dir/of/qt5/install/prefix`
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200133
Hosseind19299f2021-10-10 19:59:20 +0200134* if you want to use ccache on both sides of the build
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200135```
136--with-build-platform-configure-options=--enable-ccache
137--enable-ccache
138```
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200139
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +0100140FWIW: it's also possible to build an almost static Linux LibreOffice by just using
141--disable-dynloading --enable-customtarget-components. System externals are still
142linked dynamically, but everything else is static.
143
144### "Deploying" soffice.wasm
145
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200146```
147tar -chf wasm.tar --xform 's/.*program/lo-wasm/' instdir/program/soffice.* \
148 instdir/program/qt*
149```
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +0100150
Andrea Gelmini5ef2a7d2022-01-21 12:30:42 +0100151Your HTTP server needs to provide additional headers:
Jan-Marek Glogowski12a6b57c2022-01-10 04:50:03 +0100152* add_header Cross-Origin-Opener-Policy same-origin
153* add_header Cross-Origin-Embedder-Policy require-corp
154
155The default html to use should be qt_soffice.html
156
157### Debugging setup
158
159Since a few months you can use DWARF information embedded by LLVM into the WASM
160to debug WASM in Chrome. You need to enable an experimental feature and install
161an additional extension. The whole setup is described in:
162
163https://developer.chrome.com/blog/wasm-debugging-2020/
164
165This way you don't need source maps (much faster linking!) and can resolve local
166WASM variables to C++ names!
167
168Per default, the WASM debug build splits the DWARF information into an additional
169WASM file, postfixed '.debug.wasm'.
170
Hosseind19299f2021-10-10 19:59:20 +0200171### Using Docker to cross-build with emscripten
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200172
173If you prefer a controlled environment (sadly emsdk install/activate
174is _not_ stable over time, as e.g. nodejs versions evolve), that is
175easy to replicate across different machines - consider the docker
176images we're providing.
177
178Config/setup file see
Hosseind19299f2021-10-10 19:59:20 +0200179<https://git.libreoffice.org/lode/+/ccb36979563635b51215477455953252c99ec013>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200180
181Run
182
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200183```
184docker-compose build
185```
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200186
187in the lode/docker dir to get the container prepared. Run
188
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200189```
190PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm \
191 -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder
192```
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200193
Hosseind19299f2021-10-10 19:59:20 +0200194to perform an actual `srcdir != builddir` build; the container mounts
195checked-out git repo and output dir via `docker-compose.yml` (so make
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200196sure the path names there match your setup):
197
198The lode setup expects, inside the lode/docker subdir, the following directories:
199
Hosseind19299f2021-10-10 19:59:20 +0200200- core (`git checkout`)
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200201- workdir (the output dir - gets written into)
Hosseind19299f2021-10-10 19:59:20 +0200202- cache (`ccache tree`)
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200203- tarballs (external project tarballs gets written and cached there)
204
Sarper Akdemir841f8982023-08-07 14:41:32 +0300205### UNO bindings with Embind
206
207Right now there's a very rough implementation in place. With lots of different
208bits unimplemented. And it _might_ be leaking memory. i.e. Lots of room for
209improvement! ;)
210
211Some usage examples through javascript of the current implementation:
212```js
213// inserts a string at the start of the Writer document.
Stephan Bergmann91bedca2024-07-18 11:44:45 +0200214Module.uno_init.then(function() {
215 const css = Module.uno.com.sun.star;
Stephan Bergmanndd332f72024-07-25 16:59:33 +0200216 let xModel = Module.getCurrentModelFromViewSh();
217 if (xModel === null || !css.text.XTextDocument.query(xModel)) {
218 const desktop = css.frame.Desktop.create(Module.getUnoComponentContext());
219 const args = new Module.uno_Sequence_com$sun$star$beans$PropertyValue(
220 0, Module.uno_Sequence.FromSize);
221 xModel = css.frame.XComponentLoader.query(desktop).loadComponentFromURL(
Stephan Bergmann56e620e2026-04-02 13:17:01 +0200222 'file:///TODO/example.odt', '_default', 0, args);
Stephan Bergmanndd332f72024-07-25 16:59:33 +0200223 args.delete();
224 }
Stephan Bergmann91bedca2024-07-18 11:44:45 +0200225 const xTextDocument = css.text.XTextDocument.query(xModel);
226 const xText = xTextDocument.getText();
227 const xTextCursor = xText.createTextCursor();
228 xTextCursor.setString("string here!");
229});
Sarper Akdemir841f8982023-08-07 14:41:32 +0300230```
231
232```js
233// changes each paragraph of the Writer document to a random color.
Stephan Bergmann91bedca2024-07-18 11:44:45 +0200234Module.uno_init.then(function() {
235 const css = Module.uno.com.sun.star;
Stephan Bergmanndd332f72024-07-25 16:59:33 +0200236 let xModel = Module.getCurrentModelFromViewSh();
237 if (xModel === null || !css.text.XTextDocument.query(xModel)) {
238 const desktop = css.frame.Desktop.create(Module.getUnoComponentContext());
239 const args = new Module.uno_Sequence_com$sun$star$beans$PropertyValue(
240 0, Module.uno_Sequence.FromSize);
241 xModel = css.frame.XComponentLoader.query(desktop).loadComponentFromURL(
Stephan Bergmann56e620e2026-04-02 13:17:01 +0200242 'file:///TODO/example.odt', '_default', 0, args);
Stephan Bergmanndd332f72024-07-25 16:59:33 +0200243 args.delete();
244 }
Stephan Bergmann91bedca2024-07-18 11:44:45 +0200245 const xTextDocument = css.text.XTextDocument.query(xModel);
246 const xText = xTextDocument.getText();
247 const xEnumAccess = css.container.XEnumerationAccess.query(xText);
248 const xParaEnumeration = xEnumAccess.createEnumeration();
249 while (xParaEnumeration.hasMoreElements()) {
250 const next = xParaEnumeration.nextElement();
251 const xParagraph = css.text.XTextRange.query(next.get());
252 const xParaProps = css.beans.XPropertySet.query(xParagraph);
253 const color = new Module.uno_Any(
254 Module.uno_Type.Long(), Math.floor(Math.random() * 0xFFFFFF));
255 xParaProps.setPropertyValue("CharColor", color);
256 next.delete();
257 color.delete();
258 }
259});
Sarper Akdemir841f8982023-08-07 14:41:32 +0300260```
261
Stephan Bergmanncccc9832024-08-14 16:54:49 +0200262If you enter the above examples into the browser console, you need to enter them into the console of
Stephan Bergmann9416baf2024-10-30 11:00:58 +0100263the first web worker thread, which is the LO main thread since we use -sPROXY_TO_PTHREAD, not
Stephan Bergmanncccc9832024-08-14 16:54:49 +0200264into the console of the browser's main thread.
Sarper Akdemir841f8982023-08-07 14:41:32 +0300265
Stephan Bergmanncccc9832024-08-14 16:54:49 +0200266Alternatively, you can do the following: Put an example into some file like `example.js` that you
267put next to the `qt_soffice.html` that you serve to the browser (i.e., in
268`workdir/installation/LibreOffice/emscripten/`). Create another small JS snippet file like
269`include.js` (which is only needed during the build) containing
270```
271Module.uno_scripts = ['./example.js'];
272```
273And rebuild LO configured with an additional
Stephan Bergmannb88b5f52024-08-20 17:52:49 +0200274`EMSCRIPTEN_EXTRA_SOFFICE_PRE_JS=/...path-to.../include.js`.
Sarper Akdemir841f8982023-08-07 14:41:32 +0300275
Hosseind19299f2021-10-10 19:59:20 +0200276## Tools for problem diagnosis
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200277
Hosseind19299f2021-10-10 19:59:20 +0200278* `nm -s` should list the symbols in the archive, based on the index generated by ranlib.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200279 If you get linking errors that archive has no index.
280
281
Hosseind19299f2021-10-10 19:59:20 +0200282## Emscripten filesystem access with threads
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200283
Hosseind19299f2021-10-10 19:59:20 +0200284This is closed, but not really fixed IMHO:
285
286- <https://github.com/emscripten-core/emscripten/issues/3922>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200287
Hosseind19299f2021-10-10 19:59:20 +0200288## Dynamic libraries `/` modules in emscripten
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200289
Hosseind19299f2021-10-10 19:59:20 +0200290There is a good summary in:
291
292- <https://bugreports.qt.io/browse/QTBUG-63925>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200293
294Summary: you can't use modules and threads.
295
Hosseind19299f2021-10-10 19:59:20 +0200296This is mentioned at the end of:
297
298- <https://github.com/emscripten-core/emscripten/wiki/Linking>
299
300The usage of `MAIN_MODULE` and `SIDE_MODULE` has other problems, a major one IMHO is symbol resolution at runtime only.
301So this works really more like plugins in the sense of symbol resolution without dependencies `/` rpath.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200302
Andrea Gelmini5f102422021-05-05 23:38:21 +0200303There is some clang-level dynamic-linking in progress (WASM dlload). The following link is already a bit old,
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200304but I found it a god summary of problems to expect:
Hosseind19299f2021-10-10 19:59:20 +0200305
306- <https://iandouglasscott.com/2019/07/18/experimenting-with-webassembly-dynamic-linking-with-clang/>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200307
308
Hosseind19299f2021-10-10 19:59:20 +0200309## Mixed information, links, problems, TODO
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200310
Hosseind19299f2021-10-10 19:59:20 +0200311More info on Qt WASM emscripten pthreads:
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200312
Hosseind19299f2021-10-10 19:59:20 +0200313- <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support>
314
315WASM needs `-pthread` at compile, not just link time for atomics support. Alternatively you can provide
316`-s USE_PTHREADS=1`, but both don't seem to work reliable, so best provide both.
317<https://github.com/emscripten-core/emscripten/issues/10370>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200318
319The output file must have the prefix .o, otherwise the WASM files will get a
Hosseind19299f2021-10-10 19:59:20 +0200320`node.js` shebang (!) and ranlib won't be able to index the library (link errors).
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200321
322Qt with threads has further memory limit. From Qt configure:
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200323```
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200324Project MESSAGE: Setting PTHREAD_POOL_SIZE to 4
325Project MESSAGE: Setting TOTAL_MEMORY to 1GB
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200326```
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200327
Hosseind19299f2021-10-10 19:59:20 +0200328You can actually allocate 4GB:
329
330- <https://bugzilla.mozilla.org/show_bug.cgi?id=1392234>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200331
332LO uses a nested event loop to run dialogs in general, but that won't work, because you can't drive
333the browser event loop. like VCL does with the system event loop in the various VCL backends.
334Changing this will need some major work (basically dropping Application::Execute).
335
336But with the know problems with exceptions and threads, this might change:
Hosseind19299f2021-10-10 19:59:20 +0200337
338- <https://github.com/emscripten-core/emscripten/pull/11518>
339- <https://github.com/emscripten-core/emscripten/issues/11503>
340- <https://github.com/emscripten-core/emscripten/issues/11233>
341- <https://github.com/emscripten-core/emscripten/issues/12035>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200342
343We're also using emconfigure at the moment. Originally I patched emscripten, because it
Andrea Gelmini5f102422021-05-05 23:38:21 +0200344wouldn't create the correct a.out file for C++ configure tests. Later I found that
Hosseind19299f2021-10-10 19:59:20 +0200345the `emconfigure` sets `EMMAKEN_JUST_CONFIGURE` to work around the problem.
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200346
Hosseind19299f2021-10-10 19:59:20 +0200347ICU bug:
348
349- <https://github.com/emscripten-core/emscripten/issues/10129>
350
351Alternative, probably:
352
353- <https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200354
355There is a wasm64, but that still uses 32bit pointers!
356
Hosseind19299f2021-10-10 19:59:20 +0200357Old outdated docs:
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200358
Hosseind19299f2021-10-10 19:59:20 +0200359- <https://wiki.documentfoundation.org/Development/Emscripten>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200360
Hosseind19299f2021-10-10 19:59:20 +0200361Reverted patch:
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200362
Hosseind19299f2021-10-10 19:59:20 +0200363- <https://cgit.freedesktop.org/libreoffice/core/commit/?id=0e21f6619c72f1e17a7b0a52b6317810973d8a3e>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200364
Hosseind19299f2021-10-10 19:59:20 +0200365Generally <https://emscripten.org/docs/porting>:
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200366
Hosseind19299f2021-10-10 19:59:20 +0200367- <https://emscripten.org/docs/porting/guidelines/api_limitations.html#api-limitations>
368- <https://emscripten.org/docs/porting/files/file_systems_overview.html#file-system-overview>
369- <https://emscripten.org/docs/porting/pthreads.html>
370- <https://emscripten.org/docs/porting/emscripten-runtime-environment.html>
371
372This will be interesting:
373
374- <https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-an-event-loop>
375
376This didn't help much yet:
377
378- <https://github.com/emscripten-ports>
379
380Emscripten supports standalone WASI binaries:
381
382- <https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone>
383- <https://www.qt.io/qt-examples-for-webassembly>
384- <http://qtandeverything.blogspot.com/2017/06/qt-for-web-assembly.html>
385- <http://qtandeverything.blogspot.com/2020/>
386- <https://emscripten.org/docs/api_reference/Filesystem-API.html>
387- <https://discuss.python.org/t/add-a-webassembly-wasm-runtime/3957/12>
388- <http://git.savannah.gnu.org/cgit/config.git>
389- <https://webassembly.org/specs/>
390- <https://developer.chrome.com/docs/native-client/>
391- <https://emscripten.org/docs/getting_started/downloads.html>
392- <https://github.com/openpgpjs/openpgpjs/blob/master/README.md#getting-started>
393- <https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API>
394- <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-intro.md>
395- <https://www.ip6.li/de/security/x.509_kochbuch/openssl-fuer-webassembly-compilieren>
396- <https://emscripten.org/docs/introducing_emscripten/about_emscripten.html#about-emscripten-porting-code>
397- <https://emscripten.org/docs/compiling/Building-Projects.html>
Jan-Marek Glogowski3dd7e772021-04-23 14:04:06 +0200398
Stephan Bergmann5b1df772024-07-24 17:26:46 +0200399### Threads and the event loop
400
401The Emscripten emulation of pthreads requires the JS main thread event loop to be able to promptly
402respond both when spawning and when exiting a pthread. But the Qt5 event loop runs on the JS main
403thread, so the JS main thread event loop is blocked while a LO VCL Task is executed. And our
404pthreads are typically spawned and joined from within such Task executions, which means that the JS
405main thread event loop is not available to reliably perform those Emscripten pthread operations.
406
407For pthread spawning, the solution is to set -sPTHREAD_POOL_SIZE to a sufficiently large value, so
408that each of our pthread spawning requests during an inappropriate time finds a pre-spawned JS
409Worker available.
410
411There are patterns (like, at the time of writing this, the configmgr::Components::WriteThread) where
412a pthread can get spawned and joined and then re-spawned (and re-joined) multiple times during a
413single VCL Task execution (i.e., without the JS main thread event loop having a chance to get in
Andrea Gelmini566fbd52024-07-25 09:03:27 +0200414between any of those operations). But as the underlying Emscripten pthread exiting operations will
Stephan Bergmann5b1df772024-07-24 17:26:46 +0200415therefore queue up, the pthread spawning operations will eventually run out of -sPTHREAD_POOL_SIZE
416pre-spawned JS Workers. The solution here is to change our pthread usage patterns accordingly, so
417that such pthreads are rather kept running than being joined and re-spawned.
418
419(-sPROXY_TO_PTHREAD would move the Qt5 event loop off the JS main thread, which should elegantly
420solve all of the above issues. But Qt5 just doesn't appear to be prepared to run on anything but
421the JS main thread; e.g., it tries to access the global JS `window` object in various places, which
422is available on the JS main thread but not in a JS Worker.)
423
Tor Lillqvist6f6b8792023-02-02 13:38:02 +0200424## Building headless LibreOffice as WASM for use in another product
425
426### Set up Emscripten
427
428Follow the instructions in the first part of this document.
429
430### No Qt needed.
431
Tor Lillqvist187d3b62023-02-06 11:57:15 +0200432You don't need any dependencies other than those that normally are
433downloaded and compiled when building LibreOffice.
Tor Lillqvist6f6b8792023-02-02 13:38:02 +0200434
435### Set up LO
436
437For instance, this autogen.input works for me:
438
Ilmari Lauhakangas14f8c602025-03-27 20:04:54 +0200439```
440--disable-debug
441--enable-sal-log
442--disable-crashdump
443--host=wasm32-local-emscripten
444--disable-gui
445--with-wasm-module=writer
446--with-package-format=emscripten
447```
Tor Lillqvist6f6b8792023-02-02 13:38:02 +0200448
Tor Lillqvist297c71c2023-02-13 11:04:30 +0200449For building LO core for use in COWASM, it is known to work to use
450Emscripten 3.1.30 (and not just 2.0.31 which is what the LO+Qt5 work
Stephan Bergmann31729452024-03-06 12:49:43 +0100451has been using in the past).
Tor Lillqvist297c71c2023-02-13 11:04:30 +0200452
Tor Lillqvist6f6b8792023-02-02 13:38:02 +0200453### That's all
454
455After all, in this case you are building LO core headless for it to be used by other software.
Tor Lillqvist187d3b62023-02-06 11:57:15 +0200456
457Note that a soffice.wasm will be built, but that is just because of
458how the makefilery has been set up. We do need the soffice.data file
459that contains the in-memory file system needed by the LibreOffice
460Technology core code during run-time, though. That is at the moment
461built as a side-effect when building soffice.wasm.