| 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 | |
| Stephan Bergmann | 3172945 | 2024-03-06 12:49:43 +0100 | [diff] [blame] | 29 | We're using Qt 5.15.2 with Emscripten 3.1.46. There are a bunch of Qt patches |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 30 | to fix the most grave bugs. Also there's rapid development in Emscripten, so |
| Andrea Gelmini | 38ed810 | 2024-04-05 14:19:25 +0200 | [diff] [blame] | 31 | using another version often causes arbitrary problems. |
| 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 |
| Stephan Bergmann | 3172945 | 2024-03-06 12:49:43 +0100 | [diff] [blame] | 40 | ./emsdk install 3.1.46 |
| 41 | ./emsdk activate 3.1.46 |
| 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 | |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 60 | With "-opensource -confirm-license" you agree to the open source license. |
| 61 | |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 62 | git clone https://github.com/allotropia/qt5.git |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 63 | cd qt5 |
| Tor Lillqvist | 52c3744 | 2022-12-14 21:38:08 +0200 | [diff] [blame] | 64 | git checkout v5.15.2+wasm |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 65 | ./init-repository --module-subset=qtbase |
| Stephan Bergmann | 22ce8ed | 2024-05-28 15:16:32 +0200 | [diff] [blame] | 66 | ./configure -opensource -confirm-license -xplatform wasm-emscripten -feature-thread -prefix <whatever> QMAKE_CFLAGS+=-sSUPPORT_LONGJMP=wasm QMAKE_CXXFLAGS+=-sSUPPORT_LONGJMP=wasm |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 67 | make -j<CORES> module-qtbase |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 68 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 69 | Optionally you can add the configure flag "-compile-examples". But then you also have to |
| 70 | patch at least mkspecs/wasm-emscripten/qmake.conf with EXIT_RUNTIME=0, otherwise they will |
| 71 | fail to run. In addition, building with examples will break with some of them, but at that |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 72 | point Qt already works and also most examples. Or just skip them. Other interesting flags |
| 73 | might be "-nomake tests -no-pch -ccache". |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 74 | |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 75 | Linking takes quite a long time, because emscripten-finalize rewrites the whole WASM files with |
| 76 | some options. This way the LO WASM possibly needs 64GB RAM. For faster link times add |
| 77 | "-s WASM_BIGINT=1", change to ASSERTIONS=1 and use -g3 to prevent rewriting the WASM file and |
| 78 | generating source maps (see emscripten.py, finalize_wasm, and avoid modify_wasm = True). This is |
| 79 | just needed for Qt examples, as LO already uses the correct flags! |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 80 | |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 81 | It's needed to install Qt5 to the chosen prefix. Else LO won't find all needed files in the |
| 82 | right place. For installation you can do |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 83 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 84 | make -j<CORES> install |
| 85 | or |
| 86 | make -j8 -C qtbase/src install_subtargets |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 87 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 88 | Current Qt fails to start the demo webserver: <https://bugreports.qt.io/browse/QTCREATORBUG-24072> |
| 89 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 90 | Use `emrun --serve_after_close` to run Qt WASM demos. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 91 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 92 | ### Setup LO |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 93 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 94 | `autogen.sh` is patched to use emconfigure. That basically sets various |
| 95 | environment vars, especially `EMMAKEN_JUST_CONFIGURE`, which will create the |
| 96 | correct output file names, checked by `configure` (`a.out`). |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 97 | |
| Jan-Marek Glogowski | 79365d6 | 2022-03-26 20:46:56 +0100 | [diff] [blame] | 98 | There's a distro config for WASM, but it just provides --host=wasm32-local-emscripten, which |
| 99 | should be enough setup. The build itself is a cross build and the cross-toolset just depends |
| 100 | on a minimal toolset (gcc, libc-dev, flex, bison); all else is build from source, because the |
| 101 | final result is not depending on the build system at all. |
| Thorsten Behrens | d7e5d19 | 2021-04-25 16:02:10 +0200 | [diff] [blame] | 102 | |
| 103 | Recommended configure setup is thusly: |
| 104 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 105 | * grab defaults |
| 106 | `--with-distro=LibreOfficeWASM32` |
| Thorsten Behrens | d7e5d19 | 2021-04-25 16:02:10 +0200 | [diff] [blame] | 107 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 108 | * local config |
| Moritz Duge | 4307043 | 2024-04-03 12:04:04 +0200 | [diff] [blame] | 109 | `QT5DIR=/dir/of/qt5/install/prefix` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 110 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 111 | * if you want to use ccache on both sides of the build |
| 112 | `--with-build-platform-configure-options=--enable-ccache` |
| 113 | `--enable-ccache` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 114 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 115 | FWIW: it's also possible to build an almost static Linux LibreOffice by just using |
| 116 | --disable-dynloading --enable-customtarget-components. System externals are still |
| 117 | linked dynamically, but everything else is static. |
| 118 | |
| 119 | ### "Deploying" soffice.wasm |
| 120 | |
| 121 | tar -chf wasm.tar --xform 's/.*program/lo-wasm/' instdir/program/soffice.* \ |
| 122 | instdir/program/qt* |
| 123 | |
| Andrea Gelmini | 5ef2a7d | 2022-01-21 12:30:42 +0100 | [diff] [blame] | 124 | Your HTTP server needs to provide additional headers: |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 125 | * add_header Cross-Origin-Opener-Policy same-origin |
| 126 | * add_header Cross-Origin-Embedder-Policy require-corp |
| 127 | |
| 128 | The default html to use should be qt_soffice.html |
| 129 | |
| 130 | ### Debugging setup |
| 131 | |
| 132 | Since a few months you can use DWARF information embedded by LLVM into the WASM |
| 133 | to debug WASM in Chrome. You need to enable an experimental feature and install |
| 134 | an additional extension. The whole setup is described in: |
| 135 | |
| 136 | https://developer.chrome.com/blog/wasm-debugging-2020/ |
| 137 | |
| 138 | This way you don't need source maps (much faster linking!) and can resolve local |
| 139 | WASM variables to C++ names! |
| 140 | |
| 141 | Per default, the WASM debug build splits the DWARF information into an additional |
| 142 | WASM file, postfixed '.debug.wasm'. |
| 143 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 144 | ### Using Docker to cross-build with emscripten |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 145 | |
| 146 | If you prefer a controlled environment (sadly emsdk install/activate |
| 147 | is _not_ stable over time, as e.g. nodejs versions evolve), that is |
| 148 | easy to replicate across different machines - consider the docker |
| 149 | images we're providing. |
| 150 | |
| 151 | Config/setup file see |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 152 | <https://git.libreoffice.org/lode/+/ccb36979563635b51215477455953252c99ec013> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 153 | |
| 154 | Run |
| 155 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 156 | docker-compose build |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 157 | |
| 158 | in the lode/docker dir to get the container prepared. Run |
| 159 | |
| Jan-Marek Glogowski | 12a6b57c | 2022-01-10 04:50:03 +0100 | [diff] [blame] | 160 | PARALLELISM=4 BUILD_OPTIONS= BUILD_TARGET=build docker-compose run --rm \ |
| 161 | -e PARALLELISM -e BUILD_TARGET -e BUILD_OPTIONS builder |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 162 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 163 | to perform an actual `srcdir != builddir` build; the container mounts |
| 164 | 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] | 165 | sure the path names there match your setup): |
| 166 | |
| 167 | The lode setup expects, inside the lode/docker subdir, the following directories: |
| 168 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 169 | - core (`git checkout`) |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 170 | - workdir (the output dir - gets written into) |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 171 | - cache (`ccache tree`) |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 172 | - tarballs (external project tarballs gets written and cached there) |
| 173 | |
| 174 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 175 | ## Ideas for an UNO bridge implementation |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 176 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 177 | My post to Discord #emscripten: |
| 178 | |
| 179 | "I'm looking for a way to do an abstract call |
| Andrea Gelmini | 5f10242 | 2021-05-05 23:38:21 +0200 | [diff] [blame] | 180 | 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] | 181 | just within WASM. All my code is C++ and normally I have bridge code, with |
| 182 | assembler to implement the function call /RTTI and exception semantics of the |
| 183 | specified platform. Code is at |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 184 | <https://cgit.freedesktop.org/libreoffice/core/tree/bridges/source/cpp_uno>. |
| 185 | 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] | 186 | idea, how I could implement this (and there is an initial feature/wasm branch |
| 187 | for the interested). I probably need some fixed lookup table, like on iOS, |
| 188 | because AFAIK you can't dynamically generate code in WASM. So any pointers or |
| 189 | ideas for an implementation? I can disassemble some minimalistic WASM example |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 190 | 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] | 191 | standalone code or documentation I'm missing, that would be nice to know." |
| 192 | |
| 193 | We basically would go the same way then the other backends. Write the bridge in |
| 194 | C++, which is probably largely boilerplate code, but the function call in WAT |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 195 | (<https://github.com/WebAssembly/wabt>) based on the LLVM WASM calling |
| 196 | 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] | 197 | hours. Maybe I'll open an Emscripten issue, if we really have to implement |
| 198 | this. |
| 199 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 200 | WASM dynamic dispatch: |
| 201 | |
| 202 | - <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] | 203 | |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 204 | ### UNO bindings with Embind |
| 205 | |
| 206 | Right now there's a very rough implementation in place. With lots of different |
| 207 | bits unimplemented. And it _might_ be leaking memory. i.e. Lots of room for |
| 208 | improvement! ;) |
| 209 | |
| 210 | Some usage examples through javascript of the current implementation: |
| 211 | ```js |
| 212 | // inserts a string at the start of the Writer document. |
| Stephan Bergmann | 621322b | 2024-02-27 21:59:37 +0100 | [diff] [blame] | 213 | let uno = init_unoembind_uno(Module); |
| 214 | let css = uno.com.sun.star; |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 215 | xModel = Module.getCurrentModelFromViewSh(); |
| Stephan Bergmann | 1c81f63 | 2024-04-18 16:05:48 +0200 | [diff] [blame] | 216 | xTextDocument = css.text.XTextDocument.query(xModel); |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 217 | xText = xTextDocument.getText(); |
| Stephan Bergmann | 1c81f63 | 2024-04-18 16:05:48 +0200 | [diff] [blame] | 218 | xSimpleText = css.text.XSimpleText.query(xText); |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 219 | xTextCursor = xSimpleText.createTextCursor(); |
| Stephan Bergmann | 1c81f63 | 2024-04-18 16:05:48 +0200 | [diff] [blame] | 220 | xTextRange = css.text.XTextRange.query(xTextCursor); |
| Stephan Bergmann | 453049b | 2024-02-03 16:01:28 +0100 | [diff] [blame] | 221 | xTextRange.setString("string here!"); |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 222 | xModel.delete(); xTextDocument.delete(); xText.delete(); xSimpleText.delete(); xTextCursor.delete(); xTextRange.delete(); |
| 223 | ``` |
| 224 | |
| 225 | ```js |
| 226 | // changes each paragraph of the Writer document to a random color. |
| Stephan Bergmann | 621322b | 2024-02-27 21:59:37 +0100 | [diff] [blame] | 227 | let uno = init_unoembind_uno(Module); |
| 228 | let css = uno.com.sun.star; |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 229 | xModel = Module.getCurrentModelFromViewSh(); |
| Stephan Bergmann | 1c81f63 | 2024-04-18 16:05:48 +0200 | [diff] [blame] | 230 | xEnumAccess = css.container.XEnumerationAccess.query(xText); |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 231 | xParaEnumeration = xEnumAccess.createEnumeration(); |
| 232 | |
| 233 | while (xParaEnumeration.hasMoreElements()) { |
| Stephan Bergmann | 1c81f63 | 2024-04-18 16:05:48 +0200 | [diff] [blame] | 234 | xParagraph = css.text.XTextRange.query(xParaEnumeration.nextElement().get()); |
| 235 | if (xParagraph !== null) { |
| 236 | xParaProps = css.beans.XPropertySet.query(xParagraph); |
| Stephan Bergmann | 80bb8c6 | 2024-03-08 17:50:57 +0100 | [diff] [blame] | 237 | let color = new Module.uno_Any( |
| 238 | Module.uno_Type.Long(), Math.floor(Math.random() * 0xFFFFFF)); |
| Stephan Bergmann | f1a47d4 | 2024-02-29 11:35:46 +0100 | [diff] [blame] | 239 | xParaProps.setPropertyValue("CharColor", color); |
| 240 | color.delete(); |
| Sarper Akdemir | 841f898 | 2023-08-07 14:41:32 +0300 | [diff] [blame] | 241 | } |
| 242 | } |
| 243 | ``` |
| 244 | |
| 245 | |
| 246 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 247 | ## Tools for problem diagnosis |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 248 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 249 | * `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] | 250 | If you get linking errors that archive has no index. |
| 251 | |
| 252 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 253 | ## Emscripten filesystem access with threads |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 254 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 255 | This is closed, but not really fixed IMHO: |
| 256 | |
| 257 | - <https://github.com/emscripten-core/emscripten/issues/3922> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 258 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 259 | ## Dynamic libraries `/` modules in emscripten |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 260 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 261 | There is a good summary in: |
| 262 | |
| 263 | - <https://bugreports.qt.io/browse/QTBUG-63925> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 264 | |
| 265 | Summary: you can't use modules and threads. |
| 266 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 267 | This is mentioned at the end of: |
| 268 | |
| 269 | - <https://github.com/emscripten-core/emscripten/wiki/Linking> |
| 270 | |
| 271 | The usage of `MAIN_MODULE` and `SIDE_MODULE` has other problems, a major one IMHO is symbol resolution at runtime only. |
| 272 | 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] | 273 | |
| Andrea Gelmini | 5f10242 | 2021-05-05 23:38:21 +0200 | [diff] [blame] | 274 | 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] | 275 | but I found it a god summary of problems to expect: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 276 | |
| 277 | - <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] | 278 | |
| 279 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 280 | ## Mixed information, links, problems, TODO |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 281 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 282 | More info on Qt WASM emscripten pthreads: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 283 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 284 | - <https://wiki.qt.io/Qt_for_WebAssembly#Multithreading_Support> |
| 285 | |
| 286 | WASM needs `-pthread` at compile, not just link time for atomics support. Alternatively you can provide |
| 287 | `-s USE_PTHREADS=1`, but both don't seem to work reliable, so best provide both. |
| 288 | <https://github.com/emscripten-core/emscripten/issues/10370> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 289 | |
| 290 | 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] | 291 | `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] | 292 | |
| 293 | Qt with threads has further memory limit. From Qt configure: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 294 | ```` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 295 | Project MESSAGE: Setting PTHREAD_POOL_SIZE to 4 |
| 296 | Project MESSAGE: Setting TOTAL_MEMORY to 1GB |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 297 | ```` |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 298 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 299 | You can actually allocate 4GB: |
| 300 | |
| 301 | - <https://bugzilla.mozilla.org/show_bug.cgi?id=1392234> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 302 | |
| 303 | LO uses a nested event loop to run dialogs in general, but that won't work, because you can't drive |
| 304 | the browser event loop. like VCL does with the system event loop in the various VCL backends. |
| 305 | Changing this will need some major work (basically dropping Application::Execute). |
| 306 | |
| 307 | But with the know problems with exceptions and threads, this might change: |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 308 | |
| 309 | - <https://github.com/emscripten-core/emscripten/pull/11518> |
| 310 | - <https://github.com/emscripten-core/emscripten/issues/11503> |
| 311 | - <https://github.com/emscripten-core/emscripten/issues/11233> |
| 312 | - <https://github.com/emscripten-core/emscripten/issues/12035> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 313 | |
| 314 | 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] | 315 | 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] | 316 | the `emconfigure` sets `EMMAKEN_JUST_CONFIGURE` to work around the problem. |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 317 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 318 | ICU bug: |
| 319 | |
| 320 | - <https://github.com/emscripten-core/emscripten/issues/10129> |
| 321 | |
| 322 | Alternative, probably: |
| 323 | |
| 324 | - <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] | 325 | |
| 326 | There is a wasm64, but that still uses 32bit pointers! |
| 327 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 328 | Old outdated docs: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 329 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 330 | - <https://wiki.documentfoundation.org/Development/Emscripten> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 331 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 332 | Reverted patch: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 333 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 334 | - <https://cgit.freedesktop.org/libreoffice/core/commit/?id=0e21f6619c72f1e17a7b0a52b6317810973d8a3e> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 335 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 336 | Generally <https://emscripten.org/docs/porting>: |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 337 | |
| Hossein | d19299f | 2021-10-10 19:59:20 +0200 | [diff] [blame] | 338 | - <https://emscripten.org/docs/porting/guidelines/api_limitations.html#api-limitations> |
| 339 | - <https://emscripten.org/docs/porting/files/file_systems_overview.html#file-system-overview> |
| 340 | - <https://emscripten.org/docs/porting/pthreads.html> |
| 341 | - <https://emscripten.org/docs/porting/emscripten-runtime-environment.html> |
| 342 | |
| 343 | This will be interesting: |
| 344 | |
| 345 | - <https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-an-event-loop> |
| 346 | |
| 347 | This didn't help much yet: |
| 348 | |
| 349 | - <https://github.com/emscripten-ports> |
| 350 | |
| 351 | Emscripten supports standalone WASI binaries: |
| 352 | |
| 353 | - <https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone> |
| 354 | - <https://www.qt.io/qt-examples-for-webassembly> |
| 355 | - <http://qtandeverything.blogspot.com/2017/06/qt-for-web-assembly.html> |
| 356 | - <http://qtandeverything.blogspot.com/2020/> |
| 357 | - <https://emscripten.org/docs/api_reference/Filesystem-API.html> |
| 358 | - <https://discuss.python.org/t/add-a-webassembly-wasm-runtime/3957/12> |
| 359 | - <http://git.savannah.gnu.org/cgit/config.git> |
| 360 | - <https://webassembly.org/specs/> |
| 361 | - <https://developer.chrome.com/docs/native-client/> |
| 362 | - <https://emscripten.org/docs/getting_started/downloads.html> |
| 363 | - <https://github.com/openpgpjs/openpgpjs/blob/master/README.md#getting-started> |
| 364 | - <https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API> |
| 365 | - <https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-intro.md> |
| 366 | - <https://www.ip6.li/de/security/x.509_kochbuch/openssl-fuer-webassembly-compilieren> |
| 367 | - <https://emscripten.org/docs/introducing_emscripten/about_emscripten.html#about-emscripten-porting-code> |
| 368 | - <https://emscripten.org/docs/compiling/Building-Projects.html> |
| Jan-Marek Glogowski | 3dd7e77 | 2021-04-23 14:04:06 +0200 | [diff] [blame] | 369 | |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 370 | ## Building headless LibreOffice as WASM for use in another product |
| 371 | |
| 372 | ### Set up Emscripten |
| 373 | |
| 374 | Follow the instructions in the first part of this document. |
| 375 | |
| 376 | ### No Qt needed. |
| 377 | |
| Tor Lillqvist | 187d3b6 | 2023-02-06 11:57:15 +0200 | [diff] [blame] | 378 | You don't need any dependencies other than those that normally are |
| 379 | downloaded and compiled when building LibreOffice. |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 380 | |
| 381 | ### Set up LO |
| 382 | |
| 383 | For instance, this autogen.input works for me: |
| 384 | |
| 385 | `--disable-debug` |
| 386 | `--enable-sal-log` |
| 387 | `--disable-crashdump` |
| 388 | `--host=wasm32-local-emscripten` |
| 389 | `--disable-gui` |
| 390 | `--with-main-module=writer` |
| 391 | |
| Tor Lillqvist | 297c71c | 2023-02-13 11:04:30 +0200 | [diff] [blame] | 392 | For building LO core for use in COWASM, it is known to work to use |
| 393 | Emscripten 3.1.30 (and not just 2.0.31 which is what the LO+Qt5 work |
| Stephan Bergmann | 3172945 | 2024-03-06 12:49:43 +0100 | [diff] [blame] | 394 | has been using in the past). |
| Tor Lillqvist | 297c71c | 2023-02-13 11:04:30 +0200 | [diff] [blame] | 395 | |
| Tor Lillqvist | 6f6b879 | 2023-02-02 13:38:02 +0200 | [diff] [blame] | 396 | ### That's all |
| 397 | |
| 398 | 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] | 399 | |
| 400 | Note that a soffice.wasm will be built, but that is just because of |
| 401 | how the makefilery has been set up. We do need the soffice.data file |
| 402 | that contains the in-memory file system needed by the LibreOffice |
| 403 | Technology core code during run-time, though. That is at the moment |
| 404 | built as a side-effect when building soffice.wasm. |