diff --git a/.github/workflows/LinuxInstall.yml b/.github/workflows/LinuxInstall.yml
index 5d7e99816..9a06c253b 100644
--- a/.github/workflows/LinuxInstall.yml
+++ b/.github/workflows/LinuxInstall.yml
@@ -109,6 +109,7 @@ jobs:
- name: 'VCPKG: Set up VCPKG'
run: |
+ mkdir -p "$VCPKG_DEFAULT_BINARY_CACHE"
VCPKG_COMMIT="$(python3 - <<'PY'
import json
with open("loupe/vcpkg-configuration.json", encoding="utf-8") as f:
@@ -204,6 +205,60 @@ jobs:
evidence_dir="$RUNNER_TEMP/loupe-package-boundary-linux"
mkdir -p "$evidence_dir"
set -o pipefail
+ # Qt may ship the proprietary Mimer SQL driver, but its external
+ # libmimerapi.so is not part of the Loop distribution. linuxdeployqt
+ # validates every discovered plugin and aborts on that unresolved
+ # dependency, so remove this non-distributable optional driver from
+ # the ephemeral Qt installation before deployment.
+ sqldrivers_dir="$QT_ROOT_DIR/plugins/sqldrivers"
+ for optional_driver in libqsqlmimer.so libqsqloci.so; do
+ driver="$sqldrivers_dir/$optional_driver"
+ if [[ -e "$driver" ]]; then
+ rm -f "$driver"
+ echo "Removed non-distributable optional Qt SQL driver: $driver" | tee -a "$evidence_dir/linuxdeployqt.txt"
+ fi
+ done
+ for driver in "$sqldrivers_dir"/*.so; do
+ [[ -e "$driver" ]] || continue
+ unresolved="$(ldd "$driver" | awk '/=> not found/ { print $1 }')"
+ if [[ -n "$unresolved" ]]; then
+ echo "Removed Qt SQL driver with unresolved dependencies ($unresolved): $driver" | tee -a "$evidence_dir/linuxdeployqt.txt"
+ rm -f "$driver"
+ fi
+ done
+ platform_dir="install/usr/lib/platforms"
+ mkdir -p "$platform_dir"
+ for platform_plugin in libqoffscreen.so libqminimal.so; do
+ source_plugin="$QT_ROOT_DIR/plugins/platforms/$platform_plugin"
+ if [[ -e "$source_plugin" ]]; then
+ cp -f "$source_plugin" "$platform_dir/$platform_plugin"
+ echo "Staged Qt platform plugin: $platform_plugin" | tee -a "$evidence_dir/linuxdeployqt.txt"
+ elif [[ "$platform_plugin" == "libqoffscreen.so" ]]; then
+ echo "::error::Required Qt platform plugin is missing: $source_plugin"
+ exit 1
+ fi
+ done
+ qml_module_source="LoupeEditor/Loupe/Quick"
+ qml_module_destination="install/usr/lib/qml/Loupe/Quick"
+ if [[ ! -d "$qml_module_source" ]]; then
+ echo "::error::Built Loupe.Quick QML module is missing: $qml_module_source"
+ exit 1
+ fi
+ mkdir -p "$qml_module_destination"
+ cp -a "$qml_module_source/." "$qml_module_destination/"
+ sqlite_driver="$QT_ROOT_DIR/plugins/sqldrivers/libqsqlite.so"
+ if [[ ! -e "$sqlite_driver" ]]; then
+ echo "::error::Required Qt SQLite driver is missing: $sqlite_driver"
+ exit 1
+ fi
+ mkdir -p install/usr/lib/sqldrivers
+ cp -f "$sqlite_driver" install/usr/lib/sqldrivers/libqsqlite.so
+ cat > install/usr/bin/qt.conf <<'EOF'
+ [Paths]
+ Prefix=..
+ Plugins=lib
+ Qml2Imports=lib/qml
+ EOF
cp install/usr/share/icons/hicolor/scalable/apps/io.github.mberrys.Loupe-pdf.svg install/io.github.mberrys.Loupe-pdf.svg
bash "$GITHUB_WORKSPACE/loupe/scripts/ci/download_verified.sh" \
--gh-asset "probonopd/linuxdeployqt" \
diff --git a/.github/workflows/WindowsInstall.yml b/.github/workflows/WindowsInstall.yml
index f5c0bb53e..44462bcd5 100644
--- a/.github/workflows/WindowsInstall.yml
+++ b/.github/workflows/WindowsInstall.yml
@@ -280,6 +280,20 @@ jobs:
throw "windeployqt failed for $name with exit code $exitCode"
}
}
+ $qmlModuleSource = Join-Path $env:GITHUB_WORKSPACE "loupeuildLoupeEditorLoupeQuick"
+ $qmlModuleDestination = Join-Path $installBin "qmlLoupeQuick"
+ if (-not (Test-Path -LiteralPath $qmlModuleSource -PathType Container)) {
+ throw "Built Loupe.Quick QML module is missing: $qmlModuleSource"
+ }
+ New-Item -ItemType Directory -Force -Path $qmlModuleDestination | Out-Null
+ Copy-Item -LiteralPath (Join-Path $qmlModuleSource "*") -Destination $qmlModuleDestination -Recurse -Force
+ $sqliteDriver = Join-Path $env:QT_ROOT_DIR "pluginssqldriversqsqlite.dll"
+ $sqliteDestination = Join-Path $installBin "sqldriversqsqlite.dll"
+ if (-not (Test-Path -LiteralPath $sqliteDriver)) {
+ throw "Required Qt SQLite driver is missing: $sqliteDriver"
+ }
+ New-Item -ItemType Directory -Force -Path (Split-Path -Parent $sqliteDestination) | Out-Null
+ Copy-Item -LiteralPath $sqliteDriver -Destination $sqliteDestination -Force
# The clean installed-artifact smoke intentionally removes developer
# Qt environment variables. Make the staged tree self-describing so
@@ -289,7 +303,7 @@ jobs:
[Paths]
Prefix=.
Plugins=.
- Qml2Imports=qml
+ Qml2Imports=qml;.
"@ | Set-Content -LiteralPath (Join-Path $installBin "qt.conf") -Encoding ascii
Copy-Item -LiteralPath (Join-Path $installBin "qt.conf") -Destination (Join-Path $evidenceDir "qt.conf")
env:
diff --git a/Desktop/io.github.mberrys.Loupe-pdf.appdata.xml b/Desktop/io.github.mberrys.Loupe-pdf.appdata.xml
index 788c0d6a1..8a4879ea3 100644
--- a/Desktop/io.github.mberrys.Loupe-pdf.appdata.xml
+++ b/Desktop/io.github.mberrys.Loupe-pdf.appdata.xml
@@ -16,9 +16,9 @@
Utility
Michael Berry
- https://github.com/mberrys/Loupe-pdf
- https://github.com/mberrys/Loupe-pdf/issues
- https://github.com/mberrys/Loupe-pdf
+ https://github.com/studio-berry/loop
+ https://github.com/studio-berry/loop/issues
+ https://github.com/studio-berry/loop
io.github.mberrys.Loupe-pdf.desktop
diff --git a/WixInstaller/Product.wxs.in b/WixInstaller/Product.wxs.in
index ded0b92f7..945907039 100644
--- a/WixInstaller/Product.wxs.in
+++ b/WixInstaller/Product.wxs.in
@@ -254,6 +254,9 @@ ${LOUPE_WIX_QT_STYLES_COMPONENT}
+
+
+
diff --git a/changes/cdx-ci-packaging-repair.md b/changes/cdx-ci-packaging-repair.md
new file mode 100644
index 000000000..8f8477ddb
--- /dev/null
+++ b/changes/cdx-ci-packaging-repair.md
@@ -0,0 +1,4 @@
+Category: fixed
+Audience: maintainers
+Breaking-Change: no
+Summary: Ensure Linux packaging creates the vcpkg binary cache directory and include the staged Qt configuration in the Windows MSI.
diff --git a/scripts/smoke-test-appimage.sh b/scripts/smoke-test-appimage.sh
index 6c63ddb5d..f4a7d89a9 100644
--- a/scripts/smoke-test-appimage.sh
+++ b/scripts/smoke-test-appimage.sh
@@ -127,7 +127,7 @@ PDF_TOOL="${BIN_DIR}/PdfTool"
PROFILE_PATH="${PROFILES_DIR}/loupe-default.json"
set +e
-PREFLIGHT_OUTPUT="$("$PDF_TOOL" preflight "$TEST_PDF" --profile "$PROFILE_PATH" --console-format text 2>&1)"
+PREFLIGHT_OUTPUT="$("$PDF_TOOL" preflight "$TEST_PDF" --profile "$PROFILE_PATH" --console-format json 2>&1)"
PREFLIGHT_EXIT=$?
set -e
diff --git a/scripts/smoke-test-install.ps1 b/scripts/smoke-test-install.ps1
index 4677eebef..6c2b508fe 100644
--- a/scripts/smoke-test-install.ps1
+++ b/scripts/smoke-test-install.ps1
@@ -251,20 +251,20 @@ Remove-Item Env:QT_ROOT_DIR -ErrorAction SilentlyContinue
Remove-Item Env:Qt6_DIR -ErrorAction SilentlyContinue
Remove-Item Env:LOUPE_QT_ROOT -ErrorAction SilentlyContinue
try {
- $preflightOutput = & $pdfTool preflight $TestPdf --profile $profilePath --console-format text 2>&1
+ $preflightOutput = & $pdfTool preflight $TestPdf --profile $profilePath --console-format json 2>&1
$preflightExit = $LASTEXITCODE
Remove-Item Env:QT_QUICK_BACKEND -ErrorAction SilentlyContinue
$nativeOutput = @(& $editor --quick-smoke 2>&1)
$nativeExit = $LASTEXITCODE
if ($nativeExit -ne 0) {
- throw "LoupeEditor native Quick startup failed with exit code $($nativeExit): $nativeOutput"
+ throw "LoupeEditor native Quick startup failed with exit code $($nativeExit): $($nativeOutput -join [Environment]::NewLine)"
}
Write-Host "OK: LoupeEditor native Quick startup"
$env:QT_QUICK_BACKEND = "software"
$softwareOutput = @(& $editor --quick-smoke 2>&1)
$softwareExit = $LASTEXITCODE
if ($softwareExit -ne 0) {
- throw "LoupeEditor software Quick startup failed with exit code $($softwareExit): $softwareOutput"
+ throw "LoupeEditor software Quick startup failed with exit code $($softwareExit): $($softwareOutput -join [Environment]::NewLine)"
}
Write-Host "OK: LoupeEditor software Quick startup"
} finally {