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