-
Notifications
You must be signed in to change notification settings - Fork 82
WASM Example #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
None of us have tried yet, but i think it would be interesting to explore in the future. If a normal CMake Qt project can be built then it should be possible once the right Rust toolchain is picked. Or maybe there is potentially a route with a cargo build too. |
I have a Qt WebAssembly project I'd be interested to integrate Rust into. Starting with a PoC sounds sensible so I'll try to provide an example if nobody beats me to it. |
Small update, Qt 5 seems like too much pain - 5.15 uses emscripten 1.39.8, which uses llvm 11, while rust is now at llvm 15. As I understand it such a big difference is asking for trouble (and I get relocation errors when linking anyway). Downgrading to rust 1.51.0 that used llvm 11 has another set of issues I don't have time to deal with :D Qt 6 seems much more promising, since 6.4 uses emscripten 3.1.14 with llvm 15 so I'll try that later. |
Awesome progress! The CMake issue is related to #442. The alignment issue could be fun with |
Re #442 - I'm running CMake 3.25.2, the expression is recognized but for some reason not allowed when compiling with emscripten (the example compiles fine for x86_64) wasm separates 32bit and 64bit completely, and I'm building for wasm32 since I don't think wasm64-unknown-emscripten even exists in Rust? But that is definitely the issue, assertions expect a pointer size of 8 bytes while it's 4 in wasm32. Since they count basic types, wouldn't it be better to assert byte counts rather than multiples of the pointer size? Unless this verifies an assumption that is made on the Rust side. |
Hmm this probably needs discussing in that issue what solution can work everywhere 🤔 or whether there is another way around the WHOLE_ARCHIVE thing (cc @Be-ing ).
Normally when the Qt types uses pointers internally we have N Are you able to attach all the types that error when compiling so that we can understand if it's all types, or some that aren't quite asserted correctly ? |
Yup, will do after work. At a glance it seems it's only QColor and QVariant, but the compilation might have failed before it got to others. |
Thanks! That's hopefully good news as those two use unions and other types, but also are ones that we have used Once things are building we should consider how/if to build for the wasm target in CI 🤔 so that we ensure it keeps building. Building for the Rust target itself seems possible, getting a build of Qt for wasm seems more fun :-) |
For Qt5 there were docker images, I couldn't find one for Qt6 (though I didn't look too long) so I had to register on their website and use the installer. Thankfully I didn't need to recompile Qt itself since the prebuilt wasm32 toolkit is enough. I'll probably make a docker image myself since I prefer to work with it anyway. |
Considering that manually specifying the linker arguments worked, this seems to only be a limitation of CMake, not the linker for WASM. Could you report this issue upstream on the CMake issue tracker? |
There is a wasm32-emscripten vcpkg triplet. I have no idea if Qt builds with it though. |
@maciek134 are you able to describe further some of your setup so that I can help debug issues? I've got Qt wasm installed from 6.4.2, i've got emsdk installed, then with rustup it seems there is only a wasm32-unknown-emscripten target and not a toolchain ? (or i'm not getting the right combination). So I set the target to wasm32-unknown-emscript in When i try to build this fails to build the first few crate dependencies with lots of errors, i think it might be trying to build some things for x86 still though 🤔 Any ideas what i could be doing wrong? I installed emscripten like this cd ~/
git clone https://github.com/emscripten-core/emsdk.git .emsdk
cd .emsdk
./emsdk install latest
./emsdk activate latest
[build]
target = "wasm32-unknown-emscripten"
Default host: x86_64-unknown-linux-gnu
rustup home: /var/home/andrew/.rustup
installed targets for active toolchain
--------------------------------------
wasm32-unknown-emscripten
x86_64-unknown-linux-gnu
active toolchain
----------------
stable-x86_64-unknown-linux-gnu (default)
rustc 1.67.1 (d5a82bbd2 2023-02-07) I'm building like this source ~/.emsdk/emsdk_env.sh
mkdir -p build-wasm/
cd build-wasm/
~/.var/Qt/6.4.2/wasm_32/bin/qt-cmake ../
cmake --build . The actual build itself fails with lots of unknown arguments / file types etc in |
Yes the |
Aha, if i run Does this mean that the CMake build with corrision is not passing something through correctly ? although i do see --target set in the errors when using CMake 🤔 |
So the size changes in #447 now work on 32bit platforms like wasm. The next fun i have on my system is that something in the time methods is confused between 32bit and 64bit :-) = note: wasm-ld: error: function signature mismatch: time
>>> defined as (i32) -> i32 in /var/home/andrew/.var/Qt/6.4.2/wasm_32/lib/libQt6Core.a(qlocaltime.cpp.o)
>>> defined as (i32) -> i64 in /var/home/andrew/.emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/libc-debug.a(emscripten_time.o)
wasm-ld: error: function signature mismatch: mktime
>>> defined as (i32) -> i32 in /var/home/andrew/.var/Qt/6.4.2/wasm_32/lib/libQt6Core.a(qglobal.cpp.o)
>>> defined as (i32) -> i64 in /var/home/andrew/.emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/libc-debug.a(emscripten_time.o)
emcc: error: '/var/home/andrew/.emsdk/upstream/bin/wasm-ld @/tmp/emscripten_qs5iynpj.rsp.utf-8' failed (returned 1) |
Moving to emsdk 3.1.14 changes the error to undefined symbols instead.
|
Maybe there's a bug in the cc crate? |
I'll give you steps I did later today, didn't have much time lately. I definitely set the target for corrosion through a CMake variable though. |
This is what I did to the example (keep in mind I went the easy way and used the CMake one): maciek134@d878044 I used emscripten 3.1.4, Qt 6.4.2 (Qt downloaded from their website, not recompiled). Built with
Something is still wrong with the order somewhere, since on first compilation I get
And I guess it will always be one compilation old after that. |
sounds like the emscripten libc is compiled with |
This was when i was using the latest version of Thanks for the commit i'll see if that gets my CMake building. And we should look at why the order is wrong and requires two compilations 🤔 |
For the no-cmake build, I think passing I can't get it to work though, first it tries to pick up my system Qt installation and those are x64 so it fails:
So if I add my wasm_32 installation (
which I have no idea how to disable. |
Set the |
Ok, that builds fine now, but it won't load with QtLoader:
That was not it, using just Ah, there we go:
Just to put all my research here, adding |
I have been testing with running qt with wasm, android and linux and recently I tried using rust for components with cxx-qt. I got something working with which I'm not fully happy but at least it's something and wanted to share it here in the hope it might give someone a better insight in how to solve this properly. What I have is a small skeleton project which will run and build distribution artifacts for Linux, android and WASM all invoked from a single make file as an central entry point. It will manage the Qt installation, android SDK etc for you. The process I used to build everything was to delegate most of it to qmake because it knows best how to finally put everything together. when integrating rust components with cxx-qt in this project I had to create a fork with some changes to make it all work. Below are a list of changes I made to cxx-qt to make everything work for me:
Things to note in general for the skeleton project(for which I would probably needed to make a README but didn't):
Small pain points:
|
@jimmyvanhest Awesome work ! It'd be great to try and get the changes in your fork of cxx-qt into upstream. Are you able to submit each of the changes as separate pull requests ? (try to keep them as atomic / small as possible to aid reviews) Some of them sound like they can be fixes that are applied generally. Then others that are wasm specific, maybe we put those behind a feature ? We can also discuss the changes more clearly in pull requests. |
Note to self, features are supposed to be additive, so we may want the features for wasm to be the opposite way around. Eg have QDateTime behind a feature to enable it rather than disable it. Then this could be enabled by default but for wasm builds they can choose to have no default features / a wasm subset of features that work etc. |
Once we have a book / documentation of the build process ( cc @Be-ing ) and those changes are in, it'd be good to document the steps to make a wasm build so others can follow :-) |
@maciek134 FWIW, if I link QWasmIntegrationPlugin_init.cpp.o I get by the problem with not finding the platform plugin. Now, if only it could load my qml file from qrc... the same path works with native builds. |
Wonder if the build changes to being a QML module and then the path changes for QML / qrc stuff helps at all there, or if just in general the qrc paths have issues 🤔 |
I got past the issue with not finding the qml file by linking the generated *qml_module_resources.qrc.o directly in build.rs. Not sure of the proper change yet. Now it fails with:
QtQuick appears to be absent from the generated .wasm file. This is what I currently have (I also commented out the rust object in the QML file for now as it could not be found):
|
Ok, I got cargo_without_cmake working with e466628. These are not fixes but hacks to try and figure out what is and isn't missing/working. There are a few things I ran into. whole-archive isn't passed along to emscripten and llvm so the Qt libraries, qt-static-initializers and cxx-qt-generated get dropped in the wasm. I modified emsdk's emsdk/upstream/emscripten/tools/building.py to alter its arguments to use --whole-archive lib*.a --no-whole-archive. Presumably, if this can be provided in cxx-qt and make its way from cxx-qt to rustc, emscripten and llvm that would be the right thing to do. I was also running into failures because libraries were included on the command line more than once and compilation failed with duplicate symbols so I had building.py filter out duplicates. The real fix is probably to find out why they are duplicated to begin with. Using EMCC_DEBUG=1 leaves an rsp file in tmp that reveals the lack of whole-archive and the duplicate libs and include paths. emscripten_g11mql6f.rsp.utf-8.txt This is the change I made to emsdk's building.py:
I'm using a bash script to run cargo and create the qtloader.js and html file from the Qt templates. Presumably, this is something cxx-qt should do. These are the cxx-qt hacks I made. It primarily includes adding libraries and objects and providing some emscripten settings. I don't know how these should get included and what differs between wasm and native which obviously works...
|
This seems like an issue in rustc? Have you discussed this upstream? |
I think this problem will go away when |
@azzamsa @maciek134 @jimmyvanhest @mneilly wasm builds are now possible for a subset of use cases :) |
Hi.
Qt now supports compiling to WASM. Are we able to do this with CXX-Qt?
If this is true. I think we need to add a WASM example.
Thanks for CXX-Qt.
The text was updated successfully, but these errors were encountered: