victronenergy / gui-v2

Other
28 stars 10 forks source link

7. WebAssembly / Emscripten build #70

Closed chriadam closed 2 years ago

chriadam commented 2 years ago

We need to try a WebAssembly build of the UI, and test it in various browsers. Eventually, we need to switch from DBus to MQTT for the data model integration, but that can come later... First step is to ensure that animations / UI works, and iron out build issues.

Subtasks:

chriadam commented 2 years ago

Important to note, from the Qt For WebAssembly docs: "Qt for WebAssembly is available under commercial licenses from The Qt Company. In addition, it is available under the GNU General Public License, version 3. See Qt Licensing for further details." [https://doc-snapshots.qt.io/qt6-dev/wasm.html]

That is, no LGPL support, only Commercial or GPL usage is allowed, apparently. I think this is because it builds in effect a statically-linked version of Qt.

chriadam commented 2 years ago

I spent a bunch of time trying to get this to work today. I had to use Qt 6.2.2 because Qt For WebAssembly wasn't available in Qt 6.2.0 (at least, it wasn't installable via the Qt Maintenance Tool, for me). Eventually, I got to the point where I could build and run in QtCreator, and it was generating the appropriate files (venus-gui-v2.html, venus-gui-v2.js, venus-gui-v2.wasm, qtloader.js). I could run the application so long as main.qml didn't import Victron.VenusOS (that is, it would run if main.qml only used QtQuick things). But as soon as I tried uncommenting the import Victron.VenusOS statement, it would hang on startup (with no useful output in the browser's developer console).

The diff is attached (basically, removing any DBus related things from the build, but also some tweaks needed to get build artifacts in the right spot etc).

I can spend more time investigating this if it is desired - but it might not be worthwhile depending on licensing concerns.

webassembly.diff.txt

chriadam commented 2 years ago

Cheat sheet things:

1) install emscripten 2.0.14 2) install QtForWebAssembly 6.2.2 3) open a command console, run e.g. "C:\Development\emscripten\emsdk\emsdk_env.bat" to source the env 4) run QtCreator from within that command console (otherwise QtCreator will not find the emscripten compilers) 5) check that the options->kits shows the WebAssembly kit as working (its compilers should point to "C:\Development\emscripten\emsdk\emscripten\emcc" and "C:\Development\emscripten\emsdk\emscripten\emc++") 6) apply the diff above 7) build in release mode 8) run. it should use emrun to spawn a python web service which serves the page on an appropriate localhost port, and your default browser (e.g. chrome) should pop up and show it.

chriadam commented 2 years ago

I did some more investigation into this. The chriadam-webassembly-two branch shows what I did: basically, I removed everything, starting from a very basic skeleton, and then slowly added back pieces until it failed to run properly.

The good news is: a very large number of things work, including:

The bad news is: QML language support within Qt For WebAssembly is lacking at least one very important feature: enums defined in QML. Attempting to define an enum in QML (or dereference a defined enum) causes immediate hang at runtime. See e.g. https://github.com/victronenergy/gui-v2/pull/122/commits/c7e061e9d8e2c422570f77a083987daf598adafb for an isolated example.

We use QML-defined enums quite a bit, currently. We can transition away from them, by defining types in C++ which expose those enums, so that's the approach I will take. But it will touch a lot of code, and potentially cause some transition conflicts etc.

Once I've done that ... well, I'll continue investigation to see what other problems we hit. No doubt there will be more things to fix or work around.

chriadam commented 2 years ago

Ok, the enums thing went nicely, and resolved that issue.

The next issue is that we are hitting QTBUG-66976 (spurious warning about cyclic dependencies in singleton types). On desktop and device, this spurious warning is basically ignored. In WebAssembly, it causes a hang.

See https://github.com/victronenergy/gui-v2/pull/122/commits/263f6eba33fb4ac3a894b68e42a1ea40f5723903 for an example of how to work around the issue. In practise, we shouldn't replace all enum value lookups with hardcoded values, but instead we should make this a non-singleton type, with an instance declared in main.qml and made accessible via PageManager or similar.

With this resolved, we have e.g. circular gauges working, so QtQuick.Shapes rendering works fine in webassembly. I also tested custom font loading, and that seems to be working fine, also, as are image resources.

I will continue investigation. I think we're pretty close to having everything working, now.

chriadam commented 2 years ago

Yup, got pretty much everything running. There are some rendering and input issues (z-ordering of some items, e.g. tank drilldowns; listview flicking interaction doesn't work, e.g. control cards list or levels page with many tanks)... But it's looking good.

See the attached build with instructions for how to run on Windows.

// edit: removed the build, since my antivirus is detecting it as containing malware. I assume it's just because of the webassembly binary ... but just to be sure, you should build it yourself for testing, following the instructions in the earlier comment above.

chriadam commented 2 years ago

The remaining issues were fixed, and WebAssembly support was merged to mainline with https://github.com/victronenergy/gui-v2/pull/135 - closing issue as Done.