From 6f5dfcdb7b71ff9866b74187f3709d92e1836dbc Mon Sep 17 00:00:00 2001 From: Eduardo Gonzalez Lazo <30321688+EddyTheCo@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:46:32 +0100 Subject: [PATCH] Fix static linking (#24) * use lates dependencies * static link the plugin * updated readme * use latest qt api --- .github/workflows/build-wasm.yaml | 2 + CMakeLists.txt | 204 +++++++++++++++--------------- README.md | 4 +- main.cpp | 23 ++-- wasm/examples/omclient | 10 +- wasm/examples/qt_qr_dec | 11 +- wasm/index.html | 4 +- wasm/js/initQTwasm.js | 63 --------- wasm/js/scripts.js | 79 ++++++++---- 9 files changed, 183 insertions(+), 217 deletions(-) delete mode 100644 wasm/js/initQTwasm.js diff --git a/.github/workflows/build-wasm.yaml b/.github/workflows/build-wasm.yaml index 1125fec..23d235a 100644 --- a/.github/workflows/build-wasm.yaml +++ b/.github/workflows/build-wasm.yaml @@ -17,6 +17,8 @@ jobs: id-token: write with: qtModules: 'qtwebsockets qtshadertools' + qtVersion: '6.6.0' + emsdkVersion: '3.1.37' deploy_page: ${{ ((github.event.pull_request.merged == true) && (startsWith(github.base_ref, 'main'))) }} release: if: startsWith(github.ref, 'refs/tags/v') diff --git a/CMakeLists.txt b/CMakeLists.txt index b84c5f9..c443a12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.24) -include(local_conf.cmake OPTIONAL) +include(${CMAKE_CURRENT_BINARY_DIR}/local_conf.cmake OPTIONAL) option(USE_QtQr "add qrcode image providers" ON) option(USE_OMClient "add open-meteo element" ON) @@ -9,15 +9,15 @@ option(USE_IOTA "add IOTA object types [not mantained right now]" OFF) include(FetchContent) FetchContent_Declare( - ccommon - GIT_REPOSITORY https://github.com/EddyTheCo/Common.git - GIT_TAG main -) + ccommon + GIT_REPOSITORY https://github.com/EddyTheCo/Common.git + GIT_TAG main + ) FetchContent_MakeAvailable(ccommon) version_from_git( - LOG OFF - TIMESTAMP "%Y%m%d%H%M%S" -) + LOG OFF + TIMESTAMP "%Y%m%d%H%M%S" + ) project(qmlonline VERSION ${VERSION} LANGUAGES CXX) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -29,109 +29,109 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui Quick Qml ) qt_standard_project_setup() qt6_add_executable(appqmlonline - main.cpp -) + main.cpp + ) if(USE_OMClient) - FetchContent_Declare( - OMQml - GIT_REPOSITORY https://github.com/EddyTheCo/OMClient.git - GIT_TAG main - FIND_PACKAGE_ARGS 0.0 CONFIG - ) -FetchContent_MakeAvailable(OMQml) -list(APPEND qmlimport OMQml) -target_link_libraries(appqmlonline PRIVATE OMQml) -endif(USE_OMClient) + FetchContent_Declare( + OMQml + GIT_REPOSITORY https://github.com/EddyTheCo/OMClient.git + GIT_TAG v0.1.2 + FIND_PACKAGE_ARGS 0.1 CONFIG + ) + FetchContent_MakeAvailable(OMQml) + target_link_libraries(appqmlonline PRIVATE OMQml + $<$,STATIC_LIBRARY>:OMQmlplugin>) +endif(USE_OMClient) if(USE_QtQr) - FetchContent_Declare( - qrCode - GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git - GIT_TAG v0.1.2 - FIND_PACKAGE_ARGS 0.1 CONFIG - ) -FetchContent_MakeAvailable(qrCode) -target_link_libraries(appqmlonline PRIVATE QtQrGen QtQrDec) - -target_compile_definitions(appqmlonline PRIVATE USE_QtQr) -list(APPEND qmlimport QtQrGen QtQrDec) + FetchContent_Declare( + qrCode + GIT_REPOSITORY https://github.com/EddyTheCo/qrCode.git + GIT_TAG v0.4.1 + FIND_PACKAGE_ARGS 0.4 CONFIG + ) + FetchContent_MakeAvailable(qrCode) + target_link_libraries(appqmlonline PRIVATE QtQrGen QtQrDec + $<$,STATIC_LIBRARY>:QtQrGenplugin> + $<$,STATIC_LIBRARY>:QtQrDecplugin> + ) + target_compile_definitions(appqmlonline PRIVATE USE_QtQr) endif(USE_QtQr) FetchContent_Declare( - MyDesigns - GIT_REPOSITORY https://github.com/EddyTheCo/MyDesigns.git - GIT_TAG v0.2.3 - FIND_PACKAGE_ARGS 0.2 CONFIG -) + MyDesigns + GIT_REPOSITORY https://github.com/EddyTheCo/MyDesigns.git + GIT_TAG v0.4.1 + FIND_PACKAGE_ARGS 0.4 CONFIG + ) FetchContent_MakeAvailable(MyDesigns) -list(APPEND qmlimport MyDesigns) if(USE_IOTA) - FetchContent_Declare( - outMonitor - GIT_REPOSITORY https://github.com/EddyTheCo/outMonitor.git - GIT_TAG v0.1.5 - FIND_PACKAGE_ARGS 0.1 CONFIG - ) -FetchContent_MakeAvailable(outMonitor) -FetchContent_Declare( - outCreator - GIT_REPOSITORY https://github.com/EddyTheCo/outCreator.git - GIT_TAG v0.1.1 - FIND_PACKAGE_ARGS 0.1 CONFIG -) -FetchContent_MakeAvailable(outCreator) -FetchContent_Declare( - outConsumer - GIT_REPOSITORY https://github.com/EddyTheCo/outConsumer.git - GIT_TAG v0.1.1 - FIND_PACKAGE_ARGS 0.1 CONFIG -) -FetchContent_MakeAvailable(outConsumer) -FetchContent_Declare( - blockSender - GIT_REPOSITORY https://github.com/EddyTheCo/BlockSender.git - GIT_TAG v0.1.1 - FIND_PACKAGE_ARGS 0.1 CONFIG -) -FetchContent_MakeAvailable(blockSender) -FetchContent_Declare( - account - GIT_REPOSITORY https://github.com/EddyTheCo/account.git - GIT_TAG v0.2.2 - FIND_PACKAGE_ARGS 0.2 CONFIG -) -FetchContent_MakeAvailable(account) -FetchContent_Declare( - nodeConection - GIT_REPOSITORY https://github.com/EddyTheCo/ConectionSettings.git - GIT_TAG v0.2.3 - FIND_PACKAGE_ARGS 0.2 CONFIG -) -FetchContent_MakeAvailable(nodeConection) -target_link_libraries(appqmlonline - PRIVATE outMonitor outCreator outConsumer blockSender account nodeConection ) -list(APPEND qmlimport outMonitor outCreator outConsumer blockSender nodeConection account) + FetchContent_Declare( + outMonitor + GIT_REPOSITORY https://github.com/EddyTheCo/outMonitor.git + GIT_TAG v0.1.5 + FIND_PACKAGE_ARGS 0.1 CONFIG + ) + FetchContent_MakeAvailable(outMonitor) + FetchContent_Declare( + outCreator + GIT_REPOSITORY https://github.com/EddyTheCo/outCreator.git + GIT_TAG v0.1.1 + FIND_PACKAGE_ARGS 0.1 CONFIG + ) + FetchContent_MakeAvailable(outCreator) + FetchContent_Declare( + outConsumer + GIT_REPOSITORY https://github.com/EddyTheCo/outConsumer.git + GIT_TAG v0.1.1 + FIND_PACKAGE_ARGS 0.1 CONFIG + ) + FetchContent_MakeAvailable(outConsumer) + FetchContent_Declare( + blockSender + GIT_REPOSITORY https://github.com/EddyTheCo/BlockSender.git + GIT_TAG v0.1.1 + FIND_PACKAGE_ARGS 0.1 CONFIG + ) + FetchContent_MakeAvailable(blockSender) + FetchContent_Declare( + account + GIT_REPOSITORY https://github.com/EddyTheCo/account.git + GIT_TAG v0.2.2 + FIND_PACKAGE_ARGS 0.2 CONFIG + ) + FetchContent_MakeAvailable(account) + FetchContent_Declare( + nodeConection + GIT_REPOSITORY https://github.com/EddyTheCo/ConectionSettings.git + GIT_TAG v0.2.3 + FIND_PACKAGE_ARGS 0.2 CONFIG + ) + FetchContent_MakeAvailable(nodeConection) + target_link_libraries(appqmlonline + PRIVATE outMonitor outCreator outConsumer blockSender account nodeConection ) + list(APPEND qmlimport outMonitor outCreator outConsumer blockSender nodeConection account) endif(USE_IOTA) -target_link_libraries(appqmlonline - PRIVATE MyDesigns Qt::Core Qt::Gui Qt::Qml Qt::Quick) +target_link_libraries(appqmlonline PRIVATE MyDesigns Qt::Core Qt::Gui Qt::Qml Qt::Quick + $<$,STATIC_LIBRARY>:MyDesignsplugin> + ) qt6_add_qml_module(appqmlonline - URI qmlonline - VERSION 1.0 - RESOURCE_PREFIX - "/esterVtech.com/imports" - QML_FILES - "main.qml" - SOURCES - "qmltextcode.cpp" "qmltextcode.h" - IMPORTS ${qmlimport} - IMPORT_PATH ${QML_IMPORT_PATH} -) + URI qmlonline + VERSION 1.0 + RESOURCE_PREFIX + "/esterVtech.com/imports" + QML_FILES + "main.qml" + SOURCES + "qmltextcode.cpp" "qmltextcode.h" + IMPORT_PATH ${CMAKE_BINARY_DIR} + ) if(EMSCRIPTEN) - target_compile_definitions(appqmlonline PRIVATE USE_EMSCRIPTEN) - add_custom_command( - TARGET appqmlonline - POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS -E copy "${CMAKE_CURRENT_BINARY_DIR}/appqmlonline.js" "${CMAKE_CURRENT_BINARY_DIR}/appqmlonline.wasm" "${CMAKE_CURRENT_BINARY_DIR}/qtloader.js" "${CMAKE_CURRENT_SOURCE_DIR}/wasm" - ) + target_compile_definitions(appqmlonline PRIVATE USE_EMSCRIPTEN) + add_custom_command( + TARGET appqmlonline + POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS -E copy "${CMAKE_CURRENT_BINARY_DIR}/appqmlonline.js" "${CMAKE_CURRENT_BINARY_DIR}/appqmlonline.wasm" "${CMAKE_CURRENT_BINARY_DIR}/qtloader.js" "${CMAKE_CURRENT_SOURCE_DIR}/wasm" + ) endif() diff --git a/README.md b/README.md index afe22c6..392e3b8 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This repo produce a Qt application that allows to run Qml code interactively. The resulting application can access QML types defined in C++. The purpose of this repo is to show online some C++/Qt/Qml projects. -For doing that the repo contains a wasm folder that produce a [web page](https://eddytheco.github.io/qmlonline/wasm/), +For doing that the repo contains a wasm folder that produce a [web page](https://eddytheco.github.io/qmlonline/), integrating a JavaScript code editor to the compiled Qt application of this repo. The integration is made by compiling the Qt application to Webassembly. @@ -17,7 +17,7 @@ Create build directory and build from there. ``` mkdir build cd build -./Qt../wasm_32/bin/qt-cmake -DCMAKE_BUILD_TYPE=Release ../qmlonline/ +./Qt../wasm_../bin/qt-cmake -DCMAKE_BUILD_TYPE=Release ../qmlonline/ cmake --build . ``` diff --git a/main.cpp b/main.cpp index cfd35e2..6d0ebf6 100644 --- a/main.cpp +++ b/main.cpp @@ -4,7 +4,7 @@ #ifdef USE_QtQr #include "Qrimageprovider.hpp" -#include"Qrimagedecoder.hpp" +#include "Qrimagedecoder.hpp" #endif @@ -14,23 +14,18 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); QQmlApplicationEngine engine; - engine.addImportPath("qrc:/esterVtech.com/imports"); + engine.addImportPath("qrc:/esterVtech.com/imports"); #ifdef USE_QtQr - engine.addImageProvider(QLatin1String("qrCodedarkred"), new QRImageProvider("darkred",1)); - engine.addImageProvider(QLatin1String("qrCodeBlue"), new QRImageProvider("blue",1)); - engine.addImageProvider(QLatin1String("qrCodeBlack"), new QRImageProvider("black",1)); - engine.addImageProvider(QLatin1String("qrCodemaroon"), new QRImageProvider("maroon",1)); - engine.addImageProvider(QLatin1String("wasm"), new WasmImageProvider()); + engine.addImageProvider(QLatin1String("qrCodedarkred"), new QRImageProvider("darkred",1)); + engine.addImageProvider(QLatin1String("qrCodeBlue"), new QRImageProvider("blue",1)); + engine.addImageProvider(QLatin1String("qrCodeBlack"), new QRImageProvider("black",1)); + engine.addImageProvider(QLatin1String("qrCodemaroon"), new QRImageProvider("maroon",1)); + engine.addImageProvider(QLatin1String("wasm"), new WasmImageProvider()); #endif - qDebug()< - - + + QML Online diff --git a/wasm/js/initQTwasm.js b/wasm/js/initQTwasm.js deleted file mode 100644 index 8789049..0000000 --- a/wasm/js/initQTwasm.js +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2023 Eduardo Gonzalez Lazo. -** Contact: https://eddytheco.github.io/ -** -****************************************************************************/ - -// initQTwasm provides javascript API for managing Qt application modules. -// -// initQTwasm provides API on top of QtLoader. The qtloader.js script has to be loaded before this. -// -// usage: -// -// app_name : name of the application -// wasm_url : path to the app_name.wasm app_name.js app_name....js files -// rootDivSele :name of the root div(html) where the app will be shown -// logoPath : fullpath to a logo image to show when compiling wasm -// - - let qtLoader = undefined; -function initQTwasm(wasm_url, app_name, rootDivSele, logoPath) { - const rootDiv = document.querySelector(rootDivSele); - - rootDiv.innerHTML += '
'; - - const spinner = rootDiv.querySelector('#qtspinner'); - const canvas = rootDiv.querySelector('#screen'); - const status = rootDiv.querySelector('#qtstatus'); - - const logo = spinner.querySelector('#logo'); - logo.style.cssText = String(logo.style.cssText); - - qtLoader = QtLoader({ - path: wasm_url, - restartMode: 'RestartOnCrash', - restartType: 'RestartModule', - canvasElements : [canvas], - showLoader: function(loaderStatus) { - spinner.style.display = 'block'; - canvas.style.display = 'none'; - status.innerHTML = loaderStatus + "..."; - }, - showError: function(errorText) { - status.innerHTML = errorText; - spinner.style.display = 'block'; - canvas.style.display = 'none'; - }, - showExit: function() { - status.innerHTML = "Application exit"; - if (qtLoader.exitCode !== undefined) - status.innerHTML += " with code " + qtLoader.exitCode; - if (qtLoader.exitText !== undefined) - status.innerHTML += " (" + qtLoader.exitText + ")"; - spinner.style.display = 'block'; - canvas.style.display = 'none'; - }, - showCanvas: function() { - spinner.style.display = 'none'; - canvas.style.display = 'block'; - }, - }); - qtLoader.loadEmscriptenModule(app_name); -} diff --git a/wasm/js/scripts.js b/wasm/js/scripts.js index 8a41a15..d6ef0c2 100644 --- a/wasm/js/scripts.js +++ b/wasm/js/scripts.js @@ -7,26 +7,55 @@ function getQueryParameters(url) { }); return parameters; } +let qtModule = undefined; +async function init() { + + const rootDiv = document.querySelector('#qtrootDiv'); + + rootDiv.innerHTML += '
'; + + const spinner = rootDiv.querySelector('#qtspinner'); + const screen = rootDiv.querySelector('#screen'); + const status = rootDiv.querySelector('#qtstatus'); + + + const showUi = (ui) => { + [spinner, screen].forEach(element => element.style.display = 'none'); + if (screen === ui) + screen.style.position = 'default'; + ui.style.display = 'block'; + } + + try { + showUi(spinner); + status.innerHTML = 'Loading...'; + + qtModule = await qtLoad({ + qt: { + onLoaded: () => + { + showUi(screen); + }, + onExit: exitData => + { + status.innerHTML = 'Application exit'; + status.innerHTML += + exitData.code !== undefined ? ` with code ` : ''; + status.innerHTML += + exitData.text !== undefined ? ` ()` : ''; + showUi(spinner); + }, + entryFunction: window.appqmlonline_entry, + containerElements: [screen], + + } + }); + } catch (e) { + console.error(e); + console.error(e.stack); + } + -function init() { - initQTwasm('.', 'appqmlonline', '#qtrootDiv', 'img/esterlogo.png'); - - checkModuleLoad = setInterval(() => { - if (qtLoader.module()) { - qtLoader.module().qmlTextCode.get_editor(0).setCode(editor.session.getValue()); - qtQR=qtLoader; - clearInterval(checkModuleLoad); - } - - if (typeof counter === 'undefined') { - counter = 0; - } - - counter++; - if (counter > 60) { - clearInterval(checkModuleLoad); - } - }, 1000); const url = window.location.href; const parameter = getQueryParameters(url); const example = (typeof parameter.example_url === 'undefined' ? 'simple' : parameter.example_url); @@ -77,12 +106,12 @@ function init() { editor.session.setValue(qmlcode_); format(); }); + qtQR=qtModule; + resizeSplitX(); + qtModule.qmlTextCode.get_editor(0).setCode(editor.session.getValue()); editor.getSession().on('change', () => { - if (qtLoader.module()) { - qtLoader.module().qmlTextCode.get_editor(0).setCode(editor.session.getValue()); - } - }); - resizeSplitX() + qtModule.qmlTextCode.get_editor(0).setCode(editor.session.getValue()); + }); } function resizeSplitX(event) { @@ -90,5 +119,5 @@ function resizeSplitX(event) { var editor = ace.edit("editor"); editor.resize(); var canvas = document.getElementById("screen");; - qtLoader.resizeCanvasElement(canvas); + qtModule.qtResizeContainerElement(canvas); }