[qt] Move utils to the standalone repo and update the setup (#3724)

This commit is contained in:
Tadej Novak
2025-08-15 22:36:54 +02:00
committed by GitHub
parent ef3954eb43
commit 153a980acf
10 changed files with 34 additions and 310 deletions

View File

@@ -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"]

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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/$<IF:$<PLATFORM_ID:Linux>,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
$<$<BOOL:${MLN_WITH_OPENGL}>:${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/gl/headless_backend.cpp>
$<$<BOOL:${MLN_WITH_METAL}>:${PROJECT_SOURCE_DIR}/platform/default/src/mbgl/mtl/headless_backend.cpp>
$<$<BOOL:${MLN_WITH_VULKAN}>:${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
$<$<BOOL:${MLN_WITH_OPENGL}>:${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(
$<BUILD_INTERFACE:mbgl-vendor-parsedate>
$<BUILD_INTERFACE:mbgl-vendor-nunicode>
$<BUILD_INTERFACE:mbgl-vendor-csscolorparser>
$<$<PLATFORM_ID:iOS>:$<BUILD_INTERFACE:maplibre-native-base-extras-filesystem>>
$<$<NOT:$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Emscripten>>>:z>
$<IF:$<BOOL:${MLN_QT_WITH_INTERNAL_SQLITE}>,$<BUILD_INTERFACE:mbgl-vendor-sqlite>,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 $<BUILD_INTERFACE:mbgl-vendor-icu>)
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
$<$<PLATFORM_ID:iOS>:$<BUILD_INTERFACE:maplibre-native-base-extras-filesystem>>
$<$<BOOL:${MLN_QT_WITH_INTERNAL_SQLITE}>:$<BUILD_INTERFACE:mbgl-vendor-sqlite>>
$<$<AND:$<PLATFORM_ID:Linux>,$<BOOL:${MLN_QT_WITH_INTERNAL_ICU}>>:$<BUILD_INTERFACE:mbgl-vendor-icu>>
PARENT_SCOPE

View File

@@ -1,56 +0,0 @@
#include "renderer_backend.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <QOpenGLContext>
#include <QtGlobal>
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<RenderableResource>(*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

View File

@@ -1,38 +0,0 @@
#pragma once
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <QtGlobal>
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

View File

@@ -1,50 +0,0 @@
#pragma once
#include <mbgl/actor/actor.hpp>
#include <mbgl/actor/actor_ref.hpp>
#include <mbgl/actor/mailbox.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/util/run_loop.hpp>
#include <memory>
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<mbgl::Mailbox>(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<mbgl::Mailbox> mailbox{};
mbgl::ActorRef<mbgl::RendererObserver> delegate;
};
} // namespace QMapLibre

View File

@@ -1,60 +0,0 @@
#include "scheduler.hpp"
#include <mbgl/util/monotonic_timer.hpp>
#include <mbgl/util/util.hpp>
#include <cassert>
namespace QMapLibre {
Scheduler::Scheduler() = default;
Scheduler::~Scheduler() {
MBGL_VERIFY_THREAD(tid);
}
void Scheduler::schedule(std::function<void()>&& function) {
const std::lock_guard<std::mutex> 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<std::function<void()>> taskQueue;
{
const std::unique_lock<std::mutex> 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<std::mutex> 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

View File

@@ -1,45 +0,0 @@
#pragma once
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/util/util.hpp>
#include <QObject>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
namespace QMapLibre {
class Scheduler : public QObject, public mbgl::Scheduler {
Q_OBJECT
public:
Scheduler();
~Scheduler() override;
// mbgl::Scheduler implementation.
void schedule(std::function<void()>&& function) final;
void waitForEmpty(const mbgl::util::SimpleIdentity tag = mbgl::util::SimpleIdentity::Empty) override;
mapbox::base::WeakPtr<mbgl::Scheduler> 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<std::size_t> pendingItems;
std::queue<std::function<void()>> m_taskQueue;
mapbox::base::WeakPtrFactory<Scheduler> weakFactory{this};
// Do not add members here, see `WeakPtrFactory`
};
} // namespace QMapLibre