From 153a980acf745f98464a63ea3fcc04f95f0aca15 Mon Sep 17 00:00:00 2001 From: Tadej Novak Date: Fri, 15 Aug 2025 22:36:54 +0200 Subject: [PATCH] [qt] Move utils to the standalone repo and update the setup (#3724) --- .github/actions/qt6-build/Dockerfile | 5 -- .github/actions/qt6-build/action.yml | 6 --- .github/actions/qt6-build/entrypoint.sh | 19 ------- .github/workflows/qt-ci.yml | 32 ++++------- platform/qt/qt.cmake | 33 ++++++++---- platform/qt/src/utils/renderer_backend.cpp | 56 ------------------- platform/qt/src/utils/renderer_backend.hpp | 38 ------------- platform/qt/src/utils/renderer_observer.hpp | 50 ----------------- platform/qt/src/utils/scheduler.cpp | 60 --------------------- platform/qt/src/utils/scheduler.hpp | 45 ---------------- 10 files changed, 34 insertions(+), 310 deletions(-) delete mode 100644 .github/actions/qt6-build/Dockerfile delete mode 100644 .github/actions/qt6-build/action.yml delete mode 100755 .github/actions/qt6-build/entrypoint.sh delete mode 100644 platform/qt/src/utils/renderer_backend.cpp delete mode 100644 platform/qt/src/utils/renderer_backend.hpp delete mode 100644 platform/qt/src/utils/renderer_observer.hpp delete mode 100644 platform/qt/src/utils/scheduler.cpp delete mode 100644 platform/qt/src/utils/scheduler.hpp diff --git a/.github/actions/qt6-build/Dockerfile b/.github/actions/qt6-build/Dockerfile deleted file mode 100644 index 63e721316..000000000 --- a/.github/actions/qt6-build/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ghcr.io/maplibre/linux-builder:centos8-gcc11 - -# Copy and set the entry point -COPY entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/qt6-build/action.yml b/.github/actions/qt6-build/action.yml deleted file mode 100644 index 3c6874fa1..000000000 --- a/.github/actions/qt6-build/action.yml +++ /dev/null @@ -1,6 +0,0 @@ -# action.yml -name: 'Qt6 Linux Builder' -description: 'Helper action to build in a specific Docker container' -runs: - using: 'docker' - image: 'Dockerfile' diff --git a/.github/actions/qt6-build/entrypoint.sh b/.github/actions/qt6-build/entrypoint.sh deleted file mode 100755 index 702bcc3f8..000000000 --- a/.github/actions/qt6-build/entrypoint.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash -l - -source /opt/rh/gcc-toolset-11/enable - -set -e -set -x - -export CCACHE_DIR="$GITHUB_WORKSPACE/.ccache" -export PATH="$QT_ROOT_DIR/bin:$PATH" - -mkdir build && cd build -qt-cmake ../source/ \ - -G Ninja \ - -DCMAKE_BUILD_TYPE="Release" \ - -DCMAKE_C_COMPILER_LAUNCHER="ccache" \ - -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" \ - -DMLN_WITH_QT=ON \ - -DMLN_QT_IGNORE_ICU=OFF -ninja diff --git a/.github/workflows/qt-ci.yml b/.github/workflows/qt-ci.yml index cded63c78..5466ab285 100644 --- a/.github/workflows/qt-ci.yml +++ b/.github/workflows/qt-ci.yml @@ -59,22 +59,16 @@ jobs: strategy: matrix: include: - - name: Linux_GCC11 - os: ubuntu-24.04 - build_type: RelWithDebInfo - qt_version: 6.8.1 - qt_target: desktop - compiler: "" - name: Linux_GCC14 os: ubuntu-24.04 build_type: RelWithDebInfo - qt_version: 6.8.1 + qt_version: 6.9.1 qt_target: desktop compiler: "gcc-14" - name: macOS os: macos-14 build_type: RelWithDebInfo - qt_version: 6.8.1 + qt_version: 6.9.1 qt_target: desktop deployment_target: 12.0 deployment_arch: "x86_64;arm64" @@ -82,7 +76,7 @@ jobs: - name: macOS_LLVM os: macos-14 build_type: RelWithDebInfo - qt_version: 6.8.1 + qt_version: 6.9.1 qt_target: desktop deployment_target: 12.0 deployment_arch: "arm64" @@ -91,7 +85,7 @@ jobs: os: windows-2022 build_type: "RelWithDebInfo" compiler_type: x64 - qt_version: 6.8.1 + qt_version: 6.9.1 qt_target: desktop qt_arch: win64_msvc2022_64 qt_tools: "" @@ -112,7 +106,7 @@ jobs: submodules: true - name: Install test dependencies - if: runner.os == 'Linux' && matrix.compiler != '' + if: runner.os == 'Linux' run: | sudo apt-get update sudo apt-get install \ @@ -130,13 +124,13 @@ jobs: - name: Install compiler (Linux) id: install_compiler - if: runner.os == 'Linux' && matrix.compiler != '' + if: runner.os == 'Linux' uses: rlalik/setup-cpp-compiler@master with: compiler: ${{ matrix.compiler }} - name: Setup compiler (Linux) - if: runner.os == 'Linux' && matrix.compiler != '' + if: runner.os == 'Linux' env: CC: ${{ steps.install_compiler.outputs.cc }} CXX: ${{ steps.install_compiler.outputs.cxx }} @@ -209,11 +203,7 @@ jobs: ninja - name: Build maplibre-native (Linux, Qt6) - if: runner.os == 'Linux' && matrix.compiler == '' - uses: ./source/.github/actions/qt6-build - - - name: Build maplibre-native (Linux, Qt6, custom compiler) - if: runner.os == 'Linux' && matrix.compiler != '' + if: runner.os == 'Linux' run: | mkdir build && cd build qt-cmake ../source/ \ @@ -224,8 +214,8 @@ jobs: -DMLN_WITH_QT=ON ninja - - name: Build maplibre-native (Linux, Qt6, custom compiler, internal libraries) - if: runner.os == 'Linux' && matrix.compiler != '' + - name: Build maplibre-native (Linux, Qt6, internal libraries) + if: runner.os == 'Linux' run: | mkdir build-internal && cd build-internal qt-cmake ../source/ \ @@ -239,7 +229,7 @@ jobs: ninja - name: Run tests (Linux) - if: runner.os == 'Linux' && matrix.compiler != '' + if: runner.os == 'Linux' uses: coactions/setup-xvfb@v1 with: run: ctest --output-on-failure diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake index c6ae2394b..1c06dd6ca 100644 --- a/platform/qt/qt.cmake +++ b/platform/qt/qt.cmake @@ -17,7 +17,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") unset(CMAKE_FIND_ROOT_PATH) endif() - find_package(ICU COMPONENTS uc REQUIRED) + # Use PkgConfig to find ICU + find_package(PkgConfig REQUIRED) + pkg_check_modules(ICU_UC REQUIRED icu-uc) + pkg_check_modules(ICU_I18N REQUIRED icu-i18n) if(MLN_QT_IGNORE_ICU) set(CMAKE_PREFIX_PATH ${_CMAKE_PREFIX_PATH_ORIG}) @@ -59,16 +62,28 @@ if (MSVC) endforeach() endif() +# Qt Vulkan renderer backend: only when MLN_WITH_VULKAN and qvulkaninstance.h present +if(MLN_WITH_VULKAN) + find_path(QT_VULKAN_HEADER qvulkaninstance.h + PATHS ${Qt${QT_VERSION_MAJOR}Gui_INCLUDE_DIRS} + NO_DEFAULT_PATH) + + if(NOT QT_VULKAN_HEADER) + message(FATAL_ERROR "Qt build has no Vulkan headers; can not build Qt Vulkan backend") + endif() +endif() + target_sources( mbgl-core PRIVATE ${PROJECT_SOURCE_DIR}/platform/$,default/src/mbgl/text/bidi.cpp,qt/src/mbgl/bidi.cpp> ${PROJECT_SOURCE_DIR}/platform/default/include/mbgl/gfx/headless_backend.hpp ${PROJECT_SOURCE_DIR}/platform/default/include/mbgl/gfx/headless_frontend.hpp - ${PROJECT_SOURCE_DIR}/platform/default/include/mbgl/gl/headless_backend.hpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gfx/headless_backend.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gfx/headless_frontend.cpp - ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gl/headless_backend.cpp + $<$:${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gl/headless_backend.cpp> + $<$:${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/mtl/headless_backend.cpp> + $<$:${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/vulkan/headless_backend.cpp> ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/i18n/collator.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/layermanager/layer_manager.cpp ${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/platform/time.cpp @@ -92,7 +107,7 @@ target_sources( ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/async_task.cpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/async_task_impl.hpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/gl_functions.cpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/headless_backend_qt.cpp + $<$:${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/headless_backend_qt.cpp> ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/http_file_source.cpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/http_file_source.hpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/http_request.cpp @@ -109,11 +124,6 @@ target_sources( ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/timer.cpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/timer_impl.hpp ${PROJECT_SOURCE_DIR}/platform/qt/src/mbgl/utf.cpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/utils/renderer_backend.cpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/utils/renderer_backend.hpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/utils/renderer_observer.hpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/utils/scheduler.cpp - ${PROJECT_SOURCE_DIR}/platform/qt/src/utils/scheduler.hpp ) target_compile_definitions( @@ -140,6 +150,7 @@ target_link_libraries( $ $ $ + $<$:$> $<$,$>>:z> $,$,Qt${QT_VERSION_MAJOR}::Sql> PRIVATE @@ -153,7 +164,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") if (MLN_QT_WITH_INTERNAL_ICU) target_link_libraries(mbgl-core PUBLIC $) else() - target_link_libraries(mbgl-core PUBLIC ICU::uc) + target_link_libraries(mbgl-core PUBLIC ${ICU_UC_LIBRARIES} ${ICU_I18N_LIBRARIES}) + target_include_directories(mbgl-core PRIVATE ${ICU_UC_INCLUDE_DIRS} ${ICU_I18N_INCLUDE_DIRS}) endif() endif() @@ -164,6 +176,7 @@ if(MLN_QT_HAS_PARENT) mbgl-vendor-parsedate mbgl-vendor-nunicode mbgl-vendor-csscolorparser + $<$:$> $<$:$> $<$,$>:$> PARENT_SCOPE diff --git a/platform/qt/src/utils/renderer_backend.cpp b/platform/qt/src/utils/renderer_backend.cpp deleted file mode 100644 index bc601cde6..000000000 --- a/platform/qt/src/utils/renderer_backend.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "renderer_backend.hpp" - -#include -#include - -#include - -#include - -namespace QMapLibre { - -class RenderableResource final : public mbgl::gl::RenderableResource { -public: - explicit RenderableResource(RendererBackend &backend_) - : backend(backend_) {} - - void bind() override { - assert(mbgl::gfx::BackendScope::exists()); - backend.restoreFramebufferBinding(); - backend.setViewport(0, 0, backend.getSize()); - } - -private: - RendererBackend &backend; -}; - -RendererBackend::RendererBackend(const mbgl::gfx::ContextMode mode) - : mbgl::gl::RendererBackend(mode), - mbgl::gfx::Renderable({0, 0}, std::make_unique(*this)) {} - -RendererBackend::~RendererBackend() = default; - -void RendererBackend::updateAssumedState() { - assumeFramebufferBinding(ImplicitFramebufferBinding); - assumeViewport(0, 0, size); -} - -void RendererBackend::restoreFramebufferBinding() { - setFramebufferBinding(m_fbo); -} - -void RendererBackend::updateFramebuffer(quint32 fbo, const mbgl::Size &newSize) { - m_fbo = fbo; - size = newSize; -} - -/*! - Initializes an OpenGL extension function such as Vertex Array Objects (VAOs), - required by MapLibre Native engine. -*/ -mbgl::gl::ProcAddress RendererBackend::getExtensionFunctionPointer(const char *name) { - QOpenGLContext *thisContext = QOpenGLContext::currentContext(); - return thisContext->getProcAddress(name); -} - -} // namespace QMapLibre diff --git a/platform/qt/src/utils/renderer_backend.hpp b/platform/qt/src/utils/renderer_backend.hpp deleted file mode 100644 index 5077d5459..000000000 --- a/platform/qt/src/utils/renderer_backend.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace QMapLibre { - -class RendererBackend final : public mbgl::gl::RendererBackend, public mbgl::gfx::Renderable { -public: - explicit RendererBackend(mbgl::gfx::ContextMode mode); - ~RendererBackend() override; - - void updateFramebuffer(quint32 fbo, const mbgl::Size &newSize); - void restoreFramebufferBinding(); - - // mbgl::gfx::RendererBackend implementation -public: - mbgl::gfx::Renderable &getDefaultRenderable() override { return *this; } - -protected: - // No-op, implicit mode. - void activate() override {} - void deactivate() override {} - - // mbgl::gl::RendererBackend implementation -protected: - mbgl::gl::ProcAddress getExtensionFunctionPointer(const char *name) override; - void updateAssumedState() override; - -private: - quint32 m_fbo{}; - - Q_DISABLE_COPY(RendererBackend) -}; - -} // namespace QMapLibre diff --git a/platform/qt/src/utils/renderer_observer.hpp b/platform/qt/src/utils/renderer_observer.hpp deleted file mode 100644 index 161198cdc..000000000 --- a/platform/qt/src/utils/renderer_observer.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -namespace QMapLibre { - -// Forwards RendererObserver signals to the given -// Delegate RendererObserver on the given RunLoop -class RendererObserver final : public mbgl::RendererObserver { -public: - RendererObserver(mbgl::util::RunLoop &mapRunLoop, mbgl::RendererObserver &delegate_) - : mailbox(std::make_shared(mapRunLoop)), - delegate(delegate_, mailbox) {} - - ~RendererObserver() final { mailbox->close(); } - - void onInvalidate() final { delegate.invoke(&mbgl::RendererObserver::onInvalidate); } - - void onResourceError(std::exception_ptr err) final { - delegate.invoke(&mbgl::RendererObserver::onResourceError, err); - } - - void onWillStartRenderingMap() final { delegate.invoke(&mbgl::RendererObserver::onWillStartRenderingMap); } - - void onWillStartRenderingFrame() final { delegate.invoke(&mbgl::RendererObserver::onWillStartRenderingFrame); } - - void onDidFinishRenderingFrame(RenderMode mode, - bool repaintNeeded, - bool placementChanged, - double frameEncodingTime, - double frameRenderingTime) final { - void (mbgl::RendererObserver::*f)( - RenderMode, bool, bool, double, double) = &mbgl::RendererObserver::onDidFinishRenderingFrame; - delegate.invoke(f, mode, repaintNeeded, placementChanged, frameEncodingTime, frameRenderingTime); - } - - void onDidFinishRenderingMap() final { delegate.invoke(&mbgl::RendererObserver::onDidFinishRenderingMap); } - -private: - std::shared_ptr mailbox{}; - mbgl::ActorRef delegate; -}; - -} // namespace QMapLibre diff --git a/platform/qt/src/utils/scheduler.cpp b/platform/qt/src/utils/scheduler.cpp deleted file mode 100644 index 7ab5364c5..000000000 --- a/platform/qt/src/utils/scheduler.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "scheduler.hpp" - -#include -#include - -#include - -namespace QMapLibre { - -Scheduler::Scheduler() = default; - -Scheduler::~Scheduler() { - MBGL_VERIFY_THREAD(tid); -} - -void Scheduler::schedule(std::function&& function) { - const std::lock_guard lock(m_taskQueueMutex); - m_taskQueue.push(std::move(function)); - - // Need to force the main thread to wake - // up this thread and process the events. - emit needsProcessing(); -} - -void Scheduler::processEvents() { - std::queue> taskQueue; - { - const std::unique_lock lock(m_taskQueueMutex); - std::swap(taskQueue, m_taskQueue); - pendingItems += taskQueue.size(); - } - - while (!taskQueue.empty()) { - auto& function = taskQueue.front(); - if (function) { - function(); - } - taskQueue.pop(); - pendingItems--; - } - - cvEmpty.notify_all(); -} - -void Scheduler::waitForEmpty([[maybe_unused]] const mbgl::util::SimpleIdentity tag) { - MBGL_VERIFY_THREAD(tid); - - std::unique_lock lock(m_taskQueueMutex); - const auto isDone = [&] { - return m_taskQueue.empty() && pendingItems == 0; - }; - - while (!isDone()) { - cvEmpty.wait(lock); - } - - assert(m_taskQueue.size() + pendingItems == 0); -} - -} // namespace QMapLibre diff --git a/platform/qt/src/utils/scheduler.hpp b/platform/qt/src/utils/scheduler.hpp deleted file mode 100644 index 99b26b7b7..000000000 --- a/platform/qt/src/utils/scheduler.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include -#include -#include -#include - -namespace QMapLibre { - -class Scheduler : public QObject, public mbgl::Scheduler { - Q_OBJECT - -public: - Scheduler(); - ~Scheduler() override; - - // mbgl::Scheduler implementation. - void schedule(std::function&& function) final; - - void waitForEmpty(const mbgl::util::SimpleIdentity tag = mbgl::util::SimpleIdentity::Empty) override; - - mapbox::base::WeakPtr makeWeakPtr() override { return weakFactory.makeWeakPtr(); } - - void processEvents(); - -signals: - void needsProcessing(); - -private: - MBGL_STORE_THREAD(tid); - - std::mutex m_taskQueueMutex; - std::condition_variable cvEmpty; - std::atomic pendingItems; - std::queue> m_taskQueue; - mapbox::base::WeakPtrFactory weakFactory{this}; - // Do not add members here, see `WeakPtrFactory` -}; - -} // namespace QMapLibre