| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 1 | # Support for Emscripten Cross Build |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 2 | |
| Andrea Gelmini | b926ba6 | 2023-02-13 12:23:32 +0100 | [diff] [blame^] | 3 | This subdirectory provides support for building LibreOffice as WASM, with the Emscripten toolchain. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 4 | |
| Tor Lillqvist | 187d3b6 | 2023-02-06 11:57:15 +0200 | [diff] [blame] | 5 | You can build LibreOffice for WASM for two separate purposes: 1) |
| 6 | Either to produce a WASM binary of LibreOffice as such, using Qt5 for |
| 7 | its GUI, or 2) just compiling LibreOffice core ("LibreOffice |
| 8 | Technology") to WASM without any UI for use in other software that |
| 9 | provides the UI, like Collabora Online built as WASM. |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 10 | |
| 11 | The first purpose was the original reason for the WASM port and this |
| 12 | document was originally written with that in mind. For the second |
| 13 | purpose, 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 |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 17 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 18 | The build generates a Writer-only LO build. You should be able to run either |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 19 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 20 | $ emrun --serve_after_close instdir/program/qt_soffice.html |
| 21 | $ emrun --serve_after_close workdir/LinkTarget/Executable/qt_vcldemo.html |
| 22 | $ emrun --serve_after_close workdir/LinkTarget/Executable/qt_wasm-qt5-mandelbrot.html |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 23 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 24 | REMINDER: Always start new tabs in the browser, reload might fail / cache! |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 25 | INFO: latest browser won't work anymore with 0.0.0.0 and need 127.0.0.1. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 26 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 27 | ## Setup for the LO WASM build (with Qt) |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 28 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 29 | We're using Qt 5.15.2 with Emscripten 2.0.31. There are a bunch of Qt patches |
| 30 | to fix the most grave bugs. Also newer Emscripten versions have various bugs |
| 31 | with the FS image support. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 32 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 33 | - See below under Docker build for another build option |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 34 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 35 | ### Setup emscripten |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 36 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 37 | <https://emscripten.org/docs/getting_started/index.html> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 38 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 39 | git clone https://github.com/emscripten-core/emsdk.git |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 40 | ./emsdk install 2.0.31 |
| 41 | ./emsdk activate --embedded 2.0.31 |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 42 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 43 | Example `bashrc` scriptlet: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 44 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 45 | EMSDK_ENV=$HOME/Development/libreoffice/git_emsdk/emsdk_env.sh |
| 46 | [ -f "$EMSDK_ENV" ] && \. "$EMSDK_ENV" 1>/dev/null 2>&1 |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 47 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 48 | ### Setup Qt |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 49 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 50 | <https://doc.qt.io/qt-5/wasm.html> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 51 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 52 | Most of the information from <https://doc.qt.io/qt-6/wasm.html> is still valid for Qt5; |
| 53 | generally the Qt6 WASM documentation is much better, because it incorporated many |
| 54 | information from the Qt Wiki. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 55 | |
| Andrea Gelmini | 5ef2a7d | 2022-01-21 12:30:42 +0100 | [diff] [blame] | 56 | FWIW: Qt 5.15 LTS is not maintained publicly and Qt WASM has quite a few bugs. Most |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 57 | WASM fixes from Qt 6 are needed for Qt 5.15 too. Allotropia offers a Qt repository |
| 58 | with the necessary patches cherry-picked. |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 59 | |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 60 | git clone https://github.com/allotropia/qt5.git |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 61 | cd qt5 |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 62 | git checkout v5.15.2+wasm |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 63 | ./init-repository --module-subset=qtbase |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 64 | ./configure -xplatform wasm-emscripten -feature-thread -prefix <whatever> |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 65 | make -j<CORES> module-qtbase |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 66 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 67 | Optionally you can add the configure flag "-compile-examples". But then you also have to |
| 68 | patch at least mkspecs/wasm-emscripten/qmake.conf with EXIT_RUNTIME=0, otherwise they will |
| 69 | fail to run. In addition, building with examples will break with some of them, but at that |
| 70 | point Qt already works and also most examples. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 71 | Building with examples will break with some of them, but at that point Qt already works. |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 72 | Or just skip them. Other interesting flags might be "-nomake tests -no-pch -ccache". |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 73 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 74 | Linking takes quite a long time, because emscripten-finalize rewrites the whole WASM files |
| 75 | with some options. This way the LO WASM needs at least 64GB RAM. For faster link times add |
| 76 | "-s WASM_BIGINT=1", change to ASSERTIONS=1 nd use -g3 to prevent rewriting the WASM file |
| 77 | and generating source maps (see emscripten.py, finalize_wasm, and avoid modify_wasm = True). |
| 78 | This is just needed for Qt examples, as LO already uses the correct flags! |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 79 | |
| Andrea Gelmini | 5ef2a7d | 2022-01-21 12:30:42 +0100 | [diff] [blame] | 80 | The install is not really needed, as LO currently just uses qtbase on its own. You can do |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 81 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 82 | make -j<CORES> install |
| 83 | or |
| 84 | make -j8 -C qtbase/src install_subtargets |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 85 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 86 | Current Qt fails to start the demo webserver: <https://bugreports.qt.io/browse/QTCREATORBUG-24072> |
| 87 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 88 | Use `emrun --serve_after_close` to run Qt WASM demos. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 89 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 90 | ### Setup LO |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 91 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 92 | `autogen.sh` is patched to use emconfigure. That basically sets various |
| 93 | environment vars, especially `EMMAKEN_JUST_CONFIGURE`, which will create the |
| 94 | correct output file names, checked by `configure` (`a.out`). |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 95 | |
| Jan-Marek Glogowski | 79365d6 | 2022-03-26 20:46:56 +0100 | [diff] [blame] | 96 | There's a distro config for WASM, but it just provides --host=wasm32-local-emscripten, which |
| 97 | should be enough setup. The build itself is a cross build and the cross-toolset just depends |
| 98 | on a minimal toolset (gcc, libc-dev, flex, bison); all else is build from source, because the |
| 99 | final result is not depending on the build system at all. |
| Thorsten Behrens | d7e5d19 | 2021-04-25 16:02:10 +0200 | [diff] [blame] | 100 | |
| 101 | Recommended configure setup is thusly: |
| 102 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 103 | * grab defaults |
| 104 | `--with-distro=LibreOfficeWASM32` |
| Thorsten Behrens | d7e5d19 | 2021-04-25 16:02:10 +0200 | [diff] [blame] | 105 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 106 | * local config |
| 107 | `QT5DIR=/dir/of/git_qt5/qtbase` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 108 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 109 | * if you want to use ccache on both sides of the build |
| 110 | `--with-build-platform-configure-options=--enable-ccache` |
| 111 | `--enable-ccache` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 112 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 113 | FWIW: it's also possible to build an almost static Linux LibreOffice by just using |
| 114 | --disable-dynloading --enable-customtarget-components. System externals are still |
| 115 | linked dynamically, but everything else is static. |
| 116 | |
| Jan-Marek Glogowski | 79365d6 | 2022-03-26 20:46:56 +0100 | [diff] [blame] | 117 | #### Experimental (AKA currently broken) WASM exception + SjLj build |
| 118 | |
| 119 | You can build LO with WASM exceptions, which should be "much" faster then the JS |
| 120 | based Emscripten EH handling. For setjmp / longjmp (SjLj) used by the PNG and JPEG |
| 121 | libraries error handling, this needs Emscripten 3.1.3+. That builds, but execution |
| 122 | still fails early with a signature mismatch call to Task::UpdateMinPeriod in LO's |
| Andrea Gelmini | 3bfea3c | 2022-03-30 20:13:29 +0200 | [diff] [blame] | 123 | job scheduler code. Unfortunately the build also needs a Qt build with |
| Jan-Marek Glogowski | 79365d6 | 2022-03-26 20:46:56 +0100 | [diff] [blame] | 124 | "-s SUPPORT_LONGJMP=wasm", which is incompatible with the JS EH + SjLj. |
| 125 | |
| 126 | The LO configure flag is simply an additional --enable-wasm-exceptions. Qt5 can |
| 127 | be patched in qtbase/mkspecs/wasm-emscripten/qmake.conf with the addition of |
| 128 | |
| 129 | QMAKE_CFLAGS += -s SUPPORT_LONGJMP=wasm |
| 130 | QMAKE_CXXFLAGS += -s SUPPORT_LONGJMP=wasm |
| 131 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 132 | ### "Deploying" soffice.wasm |
| 133 | |
| 134 | tar -chf wasm.tar --xform 's/.*program/lo-wasm/' instdir/program/soffice.* \ |
| 135 | instdir/program/qt* |
| 136 | |
| Andrea Gelmini | 5ef2a7d | 2022-01-21 12:30:42 +0100 | [diff] [blame] | 137 | Your HTTP server needs to provide additional headers: |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 138 | * add_header Cross-Origin-Opener-Policy same-origin |
| 139 | * add_header Cross-Origin-Embedder-Policy require-corp |
| 140 | |
| 141 | The default html to use should be qt_soffice.html |
| 142 | |
| 143 | ### Debugging setup |
| 144 | |
| 145 | Since a few months you can use DWARF information embedded by LLVM into the WASM |
| 146 | to debug WASM in Chrome. You need to enable an experimental feature and install |
| 147 | an additional extension. The whole setup is described in: |
| 148 | |
| 149 | https://developer.chrome.com/blog/wasm-debugging-2020/ |
| 150 | |
| 151 | This way you don't need source maps (much faster linking!) and can resolve local |
| 152 | WASM variables to C++ names! |
| 153 | |
| 154 | Per default, the WASM debug build splits the DWARF information into an additional |
| 155 | WASM file, postfixed '.debug.wasm'. |
| 156 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 157 | ### Using Docker to cross-build with emscripten |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 158 | |
| 159 | If you prefer a controlled environment (sadly emsdk install/activate |
| 160 | is _not_ stable over time, as e.g. nodejs versions evolve), that is |
| 161 | easy to replicate across different machines - consider the docker |
| 162 | images we're providing. |
| 163 | |
| 164 | Config/setup file see |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 165 | <https://git.libreoffice.org/lode/+/ccb36979563635b51215477455953252c99ec013> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 166 | |
| 167 | Run |
| 168 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 169 | docker-compose build |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 170 | |
| 171 | in the lode/docker dir to get the container prepared. Run |
| 172 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 173 | PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm \ |
| 174 | -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 175 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 176 | to perform an actual `srcdir != builddir` build; the container mounts |
| 177 | checked-out git repo and output dir via `docker-compose.yml` (so make |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 178 | sure the path names there match your setup): |
| 179 | |
| 180 | The lode setup expects, inside the lode/docker subdir, the following directories: |
| 181 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 182 | - core (`git checkout`) |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 183 | - workdir (the output dir - gets written into) |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 184 | - cache (`ccache tree`) |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 185 | - tarballs (external project tarballs gets written and cached there) |
| 186 | |
| 187 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 188 | ## Ideas for an UNO bridge implementation |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 189 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 190 | My post to Discord #emscripten: |
| 191 | |
| 192 | "I'm looking for a way to do an abstract call |
| Andrea Gelmini | 5f10242 | 2021-05-05 23:38:21 +0200 | [diff] [blame] | 193 | from one WASM C++ object to another WASM C++ object, so like FFI / WebIDL, |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 194 | just within WASM. All my code is C++ and normally I have bridge code, with |
| 195 | assembler to implement the function call /RTTI and exception semantics of the |
| 196 | specified platform. Code is at |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 197 | <https://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno>. |
| 198 | I've read a bit about `call_indirect` and stuff, but I don't have yet a good |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 199 | idea, how I could implement this (and there is an initial feature/wasm branch |
| 200 | for the interested). I probably need some fixed lookup table, like on iOS, |
| 201 | because AFAIK you can't dynamically generate code in WASM. So any pointers or |
| 202 | ideas for an implementation? I can disassemble some minimalistic WASM example |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 203 | and read clang code for `WASM_EmscriptenInvoke`, but if there were some |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 204 | standalone code or documentation I'm missing, that would be nice to know." |
| 205 | |
| 206 | We basically would go the same way then the other backends. Write the bridge in |
| 207 | C++, which is probably largely boilerplate code, but the function call in WAT |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 208 | (<https://github.com/WebAssembly/wabt>) based on the LLVM WASM calling |
| 209 | conventions in `WASM_EmscriptenInvoke`. I didn't get a reply to that question for |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 210 | hours. Maybe I'll open an Emscripten issue, if we really have to implement |
| 211 | this. |
| 212 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 213 | WASM dynamic dispatch: |
| 214 | |
| 215 | - <https://fitzgeraldnick.com/2018/04/26/how-does-dynamic-dispatch-work-in-wasm.html> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 216 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 217 | ## Tools for problem diagnosis |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 218 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 219 | * `nm -s` should list the symbols in the archive, based on the index generated by ranlib. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 220 | If you get linking errors that archive has no index. |
| 221 | |
| 222 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 223 | ## Emscripten filesystem access with threads |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 224 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 225 | This is closed, but not really fixed IMHO: |
| 226 | |
| 227 | - <https://github.com/emscripten-core/emscripten/issues/3922> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 228 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 229 | ## Dynamic libraries `/` modules in emscripten |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 230 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 231 | There is a good summary in: |
| 232 | |
| 233 | - <https://bugreports.qt.io/browse/QTBUG-63925> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 234 | |
| 235 | Summary: you can't use modules and threads. |
| 236 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 237 | This is mentioned at the end of: |
| 238 | |
| 239 | - <https://github.com/emscripten-core/emscripten/wiki/Linking> |
| 240 | |
| 241 | The usage of `MAIN_MODULE` and `SIDE_MODULE` has other problems, a major one IMHO is symbol resolution at runtime only. |
| 242 | So this works really more like plugins in the sense of symbol resolution without dependencies `/` rpath. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 243 | |
| Andrea Gelmini | 5f10242 | 2021-05-05 23:38:21 +0200 | [diff] [blame] | 244 | There is some clang-level dynamic-linking in progress (WASM dlload). The following link is already a bit old, |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 245 | but I found it a god summary of problems to expect: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 246 | |
| 247 | - <https://iandouglasscott.com/2019/07/18/experimenting-with-webassembly-dynamic-linking-with-clang/> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 248 | |
| 249 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 250 | ## Mixed information, links, problems, TODO |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 251 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 252 | More info on Qt WASM emscripten pthreads: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 253 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 254 | - <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support> |
| 255 | |
| 256 | WASM needs `-pthread` at compile, not just link time for atomics support. Alternatively you can provide |
| 257 | `-s USE_PTHREADS=1`, but both don't seem to work reliable, so best provide both. |
| 258 | <https://github.com/emscripten-core/emscripten/issues/10370> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 259 | |
| 260 | The output file must have the prefix .o, otherwise the WASM files will get a |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 261 | `node.js` shebang (!) and ranlib won't be able to index the library (link errors). |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 262 | |
| 263 | Qt with threads has further memory limit. From Qt configure: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 264 | ```` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 265 | Project MESSAGE: Setting PTHREAD_POOL_SIZE to 4 |
| 266 | Project MESSAGE: Setting TOTAL_MEMORY to 1GB |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 267 | ```` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 268 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 269 | You can actually allocate 4GB: |
| 270 | |
| 271 | - <https://bugzilla.mozilla.org/show_bug.cgi?id=1392234> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 272 | |
| 273 | LO uses a nested event loop to run dialogs in general, but that won't work, because you can't drive |
| 274 | the browser event loop. like VCL does with the system event loop in the various VCL backends. |
| 275 | Changing this will need some major work (basically dropping Application::Execute). |
| 276 | |
| 277 | But with the know problems with exceptions and threads, this might change: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 278 | |
| 279 | - <https://github.com/emscripten-core/emscripten/pull/11518> |
| 280 | - <https://github.com/emscripten-core/emscripten/issues/11503> |
| 281 | - <https://github.com/emscripten-core/emscripten/issues/11233> |
| 282 | - <https://github.com/emscripten-core/emscripten/issues/12035> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 283 | |
| 284 | We're also using emconfigure at the moment. Originally I patched emscripten, because it |
| Andrea Gelmini | 5f10242 | 2021-05-05 23:38:21 +0200 | [diff] [blame] | 285 | wouldn't create the correct a.out file for C++ configure tests. Later I found that |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 286 | the `emconfigure` sets `EMMAKEN_JUST_CONFIGURE` to work around the problem. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 287 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 288 | ICU bug: |
| 289 | |
| 290 | - <https://github.com/emscripten-core/emscripten/issues/10129> |
| 291 | |
| 292 | Alternative, probably: |
| 293 | |
| 294 | - <https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Intl> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 295 | |
| 296 | There is a wasm64, but that still uses 32bit pointers! |
| 297 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 298 | Old outdated docs: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 299 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 300 | - <https://wiki.documentfoundation.org/Development/Emscripten> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 301 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 302 | Reverted patch: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 303 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 304 | - <https://cgit.freedesktop.org/libreoffice/core/commit/?id=0e21f6619c72f1e17a7b0a52b6317810973d8a3e> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 305 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 306 | Generally <https://emscripten.org/docs/porting>: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 307 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 308 | - <https://emscripten.org/docs/porting/guidelines/api_limitations.html#api-limitations> |
| 309 | - <https://emscripten.org/docs/porting/files/file_systems_overview.html#file-system-overview> |
| 310 | - <https://emscripten.org/docs/porting/pthreads.html> |
| 311 | - <https://emscripten.org/docs/porting/emscripten-runtime-environment.html> |
| 312 | |
| 313 | This will be interesting: |
| 314 | |
| 315 | - <https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-an-event-loop> |
| 316 | |
| 317 | This didn't help much yet: |
| 318 | |
| 319 | - <https://github.com/emscripten-ports> |
| 320 | |
| 321 | Emscripten supports standalone WASI binaries: |
| 322 | |
| 323 | - <https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone> |
| 324 | - <https://www.qt.io/qt-examples-for-webassembly> |
| 325 | - <http://qtandeverything.blogspot.com/2017/06/qt-for-web-assembly.html> |
| 326 | - <http://qtandeverything.blogspot.com/2020/> |
| 327 | - <https://emscripten.org/docs/api_reference/Filesystem-API.html> |
| 328 | - <https://discuss.python.org/t/add-a-webassembly-wasm-runtime/3957/12> |
| 329 | - <http://git.savannah.gnu.org/cgit/config.git> |
| 330 | - <https://webassembly.org/specs/> |
| 331 | - <https://developer.chrome.com/docs/native-client/> |
| 332 | - <https://emscripten.org/docs/getting_started/downloads.html> |
| 333 | - <https://github.com/openpgpjs/openpgpjs/blob/master/README.md#getting-started> |
| 334 | - <https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API> |
| 335 | - <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-intro.md> |
| 336 | - <https://www.ip6.li/de/security/x.509_kochbuch/openssl-fuer-webassembly-compilieren> |
| 337 | - <https://emscripten.org/docs/introducing_emscripten/about_emscripten.html#about-emscripten-porting-code> |
| 338 | - <https://emscripten.org/docs/compiling/Building-Projects.html> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 339 | |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 340 | ## Building headless LibreOffice as WASM for use in another product |
| 341 | |
| 342 | ### Set up Emscripten |
| 343 | |
| 344 | Follow the instructions in the first part of this document. |
| 345 | |
| 346 | ### No Qt needed. |
| 347 | |
| Tor Lillqvist | 187d3b6 | 2023-02-06 11:57:15 +0200 | [diff] [blame] | 348 | You don't need any dependencies other than those that normally are |
| 349 | downloaded and compiled when building LibreOffice. |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 350 | |
| 351 | ### Set up LO |
| 352 | |
| 353 | For instance, this autogen.input works for me: |
| 354 | |
| 355 | `--disable-debug` |
| 356 | `--enable-sal-log` |
| 357 | `--disable-crashdump` |
| 358 | `--host=wasm32-local-emscripten` |
| 359 | `--disable-gui` |
| 360 | `--with-main-module=writer` |
| 361 | |
| Tor Lillqvist | 297c71c | 2023-02-13 11:04:30 +0200 | [diff] [blame] | 362 | For building LO core for use in COWASM, it is known to work to use |
| 363 | Emscripten 3.1.30 (and not just 2.0.31 which is what the LO+Qt5 work |
| 364 | has been using). |
| 365 | |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 366 | ### That's all |
| 367 | |
| 368 | After all, in this case you are building LO core headless for it to be used by other software. |
| Tor Lillqvist | 187d3b6 | 2023-02-06 11:57:15 +0200 | [diff] [blame] | 369 | |
| 370 | Note that a soffice.wasm will be built, but that is just because of |
| 371 | how the makefilery has been set up. We do need the soffice.data file |
| 372 | that contains the in-memory file system needed by the LibreOffice |
| 373 | Technology core code during run-time, though. That is at the moment |
| 374 | built as a side-effect when building soffice.wasm. |