From 4cd4d74e71505dda57d6f3caf9e684123937671b Mon Sep 17 00:00:00 2001 From: George Apostolopoulos Date: Sun, 24 May 2026 00:23:44 +0300 Subject: [PATCH 1/2] Change to shared lib --- CMakeLists.txt | 7 +++++++ example/CMakeLists.txt | 6 +++++- example/main.cpp | 2 -- src/CMakeLists.txt | 13 ++++++++++++- src/qdatabrowser.cpp | 11 ----------- src/qdatabrowser.h | 7 +++---- 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f71028..edc8372 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,12 +22,19 @@ if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${PROJECT_NAME}" CACHE PATH "Default install path" FORCE) else() set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local" CACHE PATH "Default install path" FORCE) + set(LINUX_LOCAL_BUILD ON) endif() endif() # Install folder support include(GNUInstallDirs) +if(LINUX_LOCAL_BUILD) + set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_FULL_LIBDIR}") + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF) + message (STATUS "Install rpath = ${CMAKE_INSTALL_RPATH}") +endif() + find_package(Qt5 REQUIRED COMPONENTS Core Widgets Svg) message(STATUS "Found Qt5 at ${Qt5_DIR}") diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 39115bc..7f0bc60 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,4 +1,4 @@ -add_executable(databrowser +add_executable(databrowser main.cpp ) @@ -6,3 +6,7 @@ target_link_libraries(databrowser PRIVATE ${PROJECT_NAME} ) +install(TARGETS databrowser + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + diff --git a/example/main.cpp b/example/main.cpp index 34a9789..4579aa4 100644 --- a/example/main.cpp +++ b/example/main.cpp @@ -220,8 +220,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); - QDataBrowser::initResources(); - // select fusion style if available // for consistent look among different platforms QStringList style_keys = QStyleFactory::keys(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1d99983..817fe4b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(${PROJECT_NAME} STATIC +add_library(${PROJECT_NAME} SHARED qdatabrowser.h qdatabrowser.cpp qdataview.h @@ -10,9 +10,19 @@ add_library(${PROJECT_NAME} STATIC dataslice.cpp ) +include(GenerateExportHeader) +generate_export_header(${PROJECT_NAME} + EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/qtdatabrowser_export.h +) +set_target_properties(${PROJECT_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON +) + set(INSTALL_HEADERS qdatabrowser.h QDataBrowser + ${CMAKE_CURRENT_BINARY_DIR}/qtdatabrowser_export.h ) target_link_libraries(${PROJECT_NAME} @@ -27,6 +37,7 @@ target_link_libraries(${PROJECT_NAME} target_include_directories(${PROJECT_NAME} PUBLIC $ + $ $ ) diff --git a/src/qdatabrowser.cpp b/src/qdatabrowser.cpp index 6158699..9121329 100644 --- a/src/qdatabrowser.cpp +++ b/src/qdatabrowser.cpp @@ -134,17 +134,6 @@ class SqueezedDataStore : public AbstractDataStore SqueezedDataStore(); }; -// this must be outside any namespace -inline void __initResource__() -{ - Q_INIT_RESOURCE(qtdatabrowser); -} - -void QDataBrowser::initResources() -{ - __initResource__(); -} - QDataBrowser::QDataBrowser(QWidget *parent, bool ignoreSingletonDims) : QSplitter{parent}, ignoreSingletonDims_(ignoreSingletonDims), lastLeftPanelPos(100) { diff --git a/src/qdatabrowser.h b/src/qdatabrowser.h index 1d88d94..678f353 100644 --- a/src/qdatabrowser.h +++ b/src/qdatabrowser.h @@ -8,6 +8,8 @@ #include #include +#include "qtdatabrowser_export.h" + class QStandardItemModel; class QStandardItem; class QTreeView; @@ -22,7 +24,7 @@ class QDataSliceSelector; class AbstractDataStore; -class QDataBrowser : public QSplitter +class QTDATABROWSER_EXPORT QDataBrowser : public QSplitter { Q_OBJECT @@ -51,9 +53,6 @@ class QDataBrowser : public QSplitter public: explicit QDataBrowser(QWidget *parent = nullptr, bool ignoreSingletonDims = true); - // init static lib resources (icons, etc.) - static void initResources(); - // properties const QString &treeTitle() const { return treeTitle_; } void setTreeTitle(const QString &t); From 8a8e35d0c12b6174abaf402e2c60b446547370cf Mon Sep 17 00:00:00 2001 From: George Apostolopoulos Date: Sun, 24 May 2026 01:53:36 +0300 Subject: [PATCH 2/2] Add msys2 PKGBUILD file and update CI --- .github/workflows/windows-build.yml | 67 +++++++++++++++++++++----- dist/mingw64/PKGBUILD | 70 +++++++++++++++++++++++++++ dist/mingw64/build_pkg.sh | 74 +++++++++++++++++++++++++++++ 3 files changed, 200 insertions(+), 11 deletions(-) create mode 100644 dist/mingw64/PKGBUILD create mode 100755 dist/mingw64/build_pkg.sh diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a876f3c..7046eb7 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -30,18 +30,36 @@ jobs: msystem: UCRT64 update: true install: >- + base-devel + git mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-ninja mingw-w64-ucrt-x86_64-qt5-base mingw-w64-ucrt-x86_64-qt5-svg mingw-w64-ucrt-x86_64-gcc - # TODO: replace this step with the real QMatPlotWidget install once - # a package or release artifact is available for MSYS2 UCRT64. - - name: Install QMatPlotWidget (stub) + - name: Resolve version + id: ver + shell: bash run: | - echo "QMatPlotWidget installation not yet automated — add steps here." - exit 1 + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "tag=${{ inputs.version }}" >> "$GITHUB_OUTPUT" + else + echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" + fi + + - name: Download QMatPlotWidget packages + shell: pwsh + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $tag = gh release list --repo gapost/qmatplotwidget --limit 1 --json tagName --jq '.[0].tagName' + gh release download $tag --repo gapost/qmatplotwidget ` + --pattern "*.pkg.tar.zst" ` + --dir C:\Temp\qmatplotwidget-pkgs + + - name: Install QMatPlotWidget packages + run: pacman -U --noconfirm /c/Temp/qmatplotwidget-pkgs/*.pkg.tar.zst - name: Configure run: | @@ -55,12 +73,39 @@ jobs: - name: Install run: cmake --install build - - name: Package - run: cmake --build build --target package + - name: Create zip + shell: pwsh + run: | + $ver = "${{ steps.ver.outputs.tag }}".TrimStart('v') + Compress-Archive -Path build\QtDataBrowser\* ` + -DestinationPath "QtDataBrowser-${ver}-win64.zip" - - name: Upload artifact + - name: Build MSYS2 packages + run: bash dist/mingw64/build_pkg.sh ${{ steps.ver.outputs.tag }} + + - name: Upload zip uses: actions/upload-artifact@v4 with: - name: QtDataBrowser-windows - path: build/QtDataBrowser-*-win64.* - if-no-files-found: warn + name: QtDataBrowser-win64-zip + path: QtDataBrowser-*-win64.zip + + - name: Upload runtime package + uses: actions/upload-artifact@v4 + with: + name: QtDataBrowser-ucrt64-runtime + path: dist/mingw64/build/mingw-w64-ucrt-x86_64-qtdatabrowser-[0-9]*.pkg.tar.zst + + - name: Upload devel package + uses: actions/upload-artifact@v4 + with: + name: QtDataBrowser-ucrt64-devel + path: dist/mingw64/build/mingw-w64-ucrt-x86_64-qtdatabrowser-devel-*.pkg.tar.zst + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + if: startsWith(github.ref, 'refs/tags/') + with: + prerelease: ${{ contains(github.ref_name, '_') || contains(github.ref_name, '-') }} + files: | + QtDataBrowser-*-win64.zip + dist/mingw64/build/mingw-w64-ucrt-x86_64-qtdatabrowser-*.pkg.tar.zst diff --git a/dist/mingw64/PKGBUILD b/dist/mingw64/PKGBUILD new file mode 100644 index 0000000..519b8d8 --- /dev/null +++ b/dist/mingw64/PKGBUILD @@ -0,0 +1,70 @@ +# Maintainer: George Apostolopoulos + +_realname=qtdatabrowser +pkgbase=mingw-w64-${_realname} +pkgname=( + "${MINGW_PACKAGE_PREFIX}-${_realname}" + "${MINGW_PACKAGE_PREFIX}-${_realname}-devel" +) +pkgver=0.2.0 +pkgrel=1 +pkgdesc="A Qt widget for exploring multi-dimensional scientific data" +arch=('any') +mingw_arch=('mingw64' 'ucrt64' 'clang64' 'clangarm64') +url="https://github.com/ir2-lab/QtDataBrowser" +license=('spdx:MIT') +makedepends=( + "${MINGW_PACKAGE_PREFIX}-cmake" + "${MINGW_PACKAGE_PREFIX}-ninja" + "${MINGW_PACKAGE_PREFIX}-cc" + "${MINGW_PACKAGE_PREFIX}-qt5-base" + "${MINGW_PACKAGE_PREFIX}-qt5-svg" + "${MINGW_PACKAGE_PREFIX}-qmatplotwidget-devel" +) +source=("${_realname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz") +sha256sums=('SKIP') + +build() { + mkdir -p "${srcdir}/build-${MSYSTEM}" && cd "${srcdir}/build-${MSYSTEM}" + + MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ + cmake \ + -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \ + -DQTDATABROWSER_BUILD_EXAMPLES=OFF \ + "${srcdir}/QtDataBrowser-${pkgver}" + + cmake --build . +} + +_package_all() { + cd "${srcdir}/build-${MSYSTEM}" + DESTDIR="${pkgdir}" cmake --install . +} + +eval "package_${MINGW_PACKAGE_PREFIX}-${_realname}() { + pkgdesc=\"\${pkgdesc} (runtime)\" + depends=( + \"${MINGW_PACKAGE_PREFIX}-qt5-base\" + \"${MINGW_PACKAGE_PREFIX}-qmatplotwidget\" + ) + + _package_all + + rm -rf \"\${pkgdir}\${MINGW_PREFIX}/include/\" + rm -rf \"\${pkgdir}\${MINGW_PREFIX}/lib/cmake/\" + find \"\${pkgdir}\${MINGW_PREFIX}/lib/\" -name '*.a' -delete 2>/dev/null || true +}" + +eval "package_${MINGW_PACKAGE_PREFIX}-${_realname}-devel() { + pkgdesc=\"\${pkgdesc} (development)\" + depends=( + \"${MINGW_PACKAGE_PREFIX}-${_realname}=\${pkgver}\" + \"${MINGW_PACKAGE_PREFIX}-qt5-base\" + ) + + _package_all + + rm -f \"\${pkgdir}\${MINGW_PREFIX}/bin/\"*.dll +}" diff --git a/dist/mingw64/build_pkg.sh b/dist/mingw64/build_pkg.sh new file mode 100755 index 0000000..8c4edde --- /dev/null +++ b/dist/mingw64/build_pkg.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Build the UCRT64 MSYS2 packages for QtDataBrowser. +# Must be run from the project root directory. +# Usage: bash dist/mingw64/build_pkg.sh (e.g. v0.2.0) + +set -euo pipefail + +# --------------------------------------------------------------------------- +# Arguments +# --------------------------------------------------------------------------- +VERSION="${1:-}" +if [[ -z "${VERSION}" ]]; then + echo "Usage: $(basename "$0") (e.g. v0.2.0)" >&2 + exit 1 +fi + +# Strip leading 'v' to get the bare version number used by PKGBUILD +PKGVER="${VERSION#v}" + +# --------------------------------------------------------------------------- +# Paths +# --------------------------------------------------------------------------- +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +BUILD_DIR="${SCRIPT_DIR}/build" + +# Must match the left-hand side of source=() in PKGBUILD +ARCHIVE_NAME="qtdatabrowser-${PKGVER}.tar.gz" +ARCHIVE_PATH="${BUILD_DIR}/${ARCHIVE_NAME}" + +# Must match the directory referenced inside build() in PKGBUILD +GIT_PREFIX="QtDataBrowser-${PKGVER}/" + +# --------------------------------------------------------------------------- +# Sanity checks +# --------------------------------------------------------------------------- +if ! command -v makepkg-mingw &>/dev/null; then + echo "error: makepkg-mingw not found — run this script inside an MSYS2 shell" >&2 + exit 1 +fi + +# --------------------------------------------------------------------------- +# 1. Create source archive +# --------------------------------------------------------------------------- +mkdir -p "${BUILD_DIR}" + +echo "==> Creating source archive from HEAD..." +git -C "${PROJECT_ROOT}" archive \ + --format=tar.gz \ + --prefix="${GIT_PREFIX}" \ + HEAD \ + -o "${ARCHIVE_PATH}" + +# --------------------------------------------------------------------------- +# 2. Prepare PKGBUILD with correct version and checksum +# --------------------------------------------------------------------------- +SHA256=$(sha256sum "${ARCHIVE_PATH}" | awk '{print $1}') + +echo "==> Preparing PKGBUILD (pkgver=${PKGVER}, sha256=${SHA256})..." +sed \ + -e "s/^pkgver=.*/pkgver=${PKGVER}/" \ + -e "s/sha256sums=('SKIP')/sha256sums=('${SHA256}')/" \ + "${SCRIPT_DIR}/PKGBUILD" > "${BUILD_DIR}/PKGBUILD" + +# --------------------------------------------------------------------------- +# 3. Build UCRT64 package +# --------------------------------------------------------------------------- +echo "==> Building UCRT64 packages..." +cd "${BUILD_DIR}" +MINGW_ARCH=ucrt64 makepkg-mingw --noconfirm -sCLf + +echo "" +echo "==> Done. Built packages:" +ls "${BUILD_DIR}"/*.pkg.tar.* 2>/dev/null || echo " (none found)"