Qt Everywhere — так именуются архивы с исходниками Qt. В 5.12.0 завезут WebAssembly и WebGL стриминг и everywhere звучит уже по другому. Так и просилось что-нибудь запрототипировать. Был быстро накидан прототип чатика на веб-сокетах, что бы протестировать поддержку сети. Под катом будет инструкция по сборке и запуска проекта на WebAssembly, пример вызова JavaScript из С++.
Сборка Qt с WebAssembly
Сперва нужно поставить toolchain emscripten, которым будем собирать Qt. Не забудьте прописать переменные окружения, что бы qmake нашел emcc. Скрипт configure запускался со следующими параметрами:
./configure \ -prefix /home/dmitry/Qt/5.12.0/wasm \ -xplatform wasm-emscripten \ -confirm-license -opensource \ -nomake tests \ -c++std c++1z \ -nomake examples \ -release \ -no-dbus \ -skip qtxmlpatterns \ -skip qttools
Дальше как и везде:
$ make $ make install
Сборка и запуск проекта
$ ~/Qt/5.12.0/wasm/bin/qmake $ make $ emrun chat.html
Платформенно-зависимый код
Зашивать url на котором висит бэкенд не очень хорошо, т.к. захочется запускать на произвольном порту. В случает работы из браузера нужно взять location.hostname и location.port что бы определить где запущен бэкенд. Для этого придется немного пописать на JavaScript.
Для любителей дефайнов есть Q_OS_WASM, я же предпочитаю выносить код в pimpl и отдельные файлы. Pimpl здесь лишний, но код разнесу на разные файлы
Заведем какой-нибудь конфиг
//config.h #pragma once #include <QtCore/QUrl> class Config { public: static QUrl wsUrl(); };
и две реализации
//config.cpp #include <QtCore/QCoreApplication> #include <QtCore/QCommandLineParser> #include "config.h" QUrl Config::wsUrl() { QCommandLineParser parser; QCommandLineOption wsOption(QStringList() << "u" << "url" , "WebSocket url" , "url" , "ws://localhost:1234"); parser.addOption(wsOption); parser.process(*QCoreApplication::instance()); return QUrl(parser.value(wsOption)); }
//config_wasm.cpp #include <QtCore/QByteArray> #include <emscripten/emscripten.h> #include <emscripten/html5.h> #include "config.h" QUrl Config::wsUrl() { QByteArray buff(1024, 0); EM_ASM_({ var url = "ws://"+ window.location.hostname + ":" + window.location.port + "/ws"; stringToUTF8(url, $0, $1); }, buff.data(), buff.size()); return QUrl(QString::fromUtf8(buff)); }
Осталось прописать в pro файле
wasm { SOURCES += config_wasm.cpp } else { SOURCES += config.cpp }
EM_ASM_ это магия emscripten позволяющая вызывать JavaScript код из C++. Хотя можно это было сделать и без JavaScript
emscripten::val location = emscripten::val::global("location"); auto host = QString::fromStdString(location["host"].as<string>()); auto protocol = QString::fromStdString(location["protocol"].as<string>());
Поддержка в браузерах
Десктопные браузеры: запускается и работает в Сhrome, Firefox, Safari, Edge(тут пришлось включить экспериментальные функции JavaScript). В зависимости от железа могут быть существенные задержки на компиляции WebAssembly.
В Chrome на Andorid могут пройти минуты на компиляцию WebAssembly. Сразу заметил отсутствия поддержки мобильных браузеров, а именно нет вызова системной клавиатуры, при попытки ввести текст.
Safari на iOS 12 тут приложение падает на этапе компиляции WebAssembly и я не стал дебажить. Теоретически можно перейти на asm.js, но это требует отдельного исследования.
Qt Quick WebGL
В блоге позиционировался как VNC на веб-сокетах с отрисовкой на WebGL. Из зависимостей Qt WebSockets и Qt собранный с поддержкой OpenGL ES 2 т.е. гонять на железе без GPU будет мучительно. Для её поддержки достаточно поставить Qt WebGL Streaming Plugin в онлайн установщике и запустить приложение с параметром -platform webgl или -platform webgl:port=80, если нужно указать порт.
Но у этой технологии есть свои ограничения:
- задержки или пресловутый input lag;
- отсутствует поддержка приложений на Qt Widgets;
- отсутствие передачи звука;
- одно пользовательское соединение на процесс т.е. во второй вкладке уже не зайти, будет крутиться прелоадер.
Так же я заметил проседание fps при анимации StackView на переходах между экранами. Достоинство WebGL стриминга:
- встроенный сервер;
- минимум усилий. Мне не пришлось собирать из исходников Qt и отдельно пересобирать существующее приложение.
Способы применения WebAssembly и WebGL Streaming
Альтернатива Wt когда есть готовое приложение на C++ и к нему нужно прикрутить веб-интерфейс. Например web-интерфейс к torrent качалке.
Web интерфейс для какого-нибудь умного дома. Не даром в Qt завезли MQTT, а на msorvig/qt-webassembly-examples пример mqtt_simpleclient. Можно иметь общий код UI который работает на планшете и в браузере.
