Skip to content

Fix Linux mingw cross-compile and add a Linux/Wine CI workflow#5812

Open
koppor wants to merge 2 commits into
masterfrom
linux-wine-ci
Open

Fix Linux mingw cross-compile and add a Linux/Wine CI workflow#5812
koppor wants to merge 2 commits into
masterfrom
linux-wine-ci

Conversation

@koppor

@koppor koppor commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Running on WSL w/ Wine

grafik

🤖 This description was generated by Claude Code.

What

cmd/build-linux-wine.ts (cross-compile the full SumatraPDF.exe with mingw-w64 on Linux and run it under Wine) had drifted out of sync since it was added: the mupdf-libs aggregate removal, the src/base rework, and a number of new or renamed src/ files broke both compile and link. Because no CI exercises this path, nothing caught it. This PR makes the Linux cross-build green again and adds a CI workflow so it stays green.

Latent portability bugs fixed in source (invisible to MSVC):

  • two case-sensitive #include mismatches (theme.h in EditAnnotations.cpp, SumatraPdf.h in Notifications.cpp) — fatal on any case-sensitive filesystem
  • INT_MAX used in Vec.h without <limits.h> (added to Base.h; MSVC gets it transitively)
  • Size Size() const; in Geom.h — gcc rejects the unelaborated form ("changes meaning of Size")
  • four pointer-truncating (LONG)hwnd / (int)hwnd casts in src/uia/ — hard errors under clang; now the canonical HandleToLong()
  • SetThreadDescription isn't declared by mingw-w64 headers before v12 — declared in WinDynCalls.h under #ifdef __MINGW32__ (an identical redeclaration is harmless on newer headers, and the block is invisible to MSVC)
  • unrar's internal C++ Archive class collides with src/base/Archive.cpp's Archive since the base rework — GNU ld errors on the duplicate strong symbols (MSVC silently picks one via COMDAT, a latent hazard there too). unrar TUs now compile with -DArchive=UnrarArchive; consumers only use the C API in dll.hpp, which doesn't mention the class.

Shared lib-def drift (cmd/build-lib-defs.ts — also benefits the mac/linux native builds):

  • extract: add ext/extract/src to includes (memento.h lives there)
  • libheif: restore the heif_components / heif_metadata / heif_omaf API files (premake lists them; the TS defs had dropped them → link errors from ExifDump)
  • mupdf: add cull-device.c, options.c, md.c plus the cmark-gfm include dirs and CMARK_GFM_STATIC_DEFINE (previously patched locally in build-linux.ts only)

cmd/build-with-mingw.ts re-synced with premake: the removed mupdfLibs import replaced with the individual restored libs; djvudec, a-gumbo, zopfli libs added; ~30 added/renamed src files (AIChat*, PdfDarkMode*, PdfCad*, the RefHover and CommandPalette splits, FindBar/FindWindow, Markdown*, WebpReader, SumatraLog, AppUnitTests, …); missing include dirs (libjxl, libheif, libwebp, cmark, djvudec); -Wno-narrowing for mingw's QITABENT macro under clang; the generated TTS/Test stubs re-synced with the current TextToSpeech.h / WStr signatures; a missing basename import.

Toolchain: resolveMingwTools now prefers x86_64-w64-mingw32-g++-posix — Debian's unsuffixed mingw is the win32-threads flavor whose libstdc++ has no std::mutex (libheif needs it). On Ubuntu the unsuffixed name is already the posix flavor, so nothing changes there.

CI — .github/workflows/linux.yml: cross-compiles in a debian:trixie container (mingw-w64 ≥ 12 is the practical floor: ubuntu-24.04 runners ship v11, whose headers predate SetThreadDescription, DWMWCP_*, …), runs the built exe's built-in unit tests under Wine (xvfb) as the gate, runs a render smoke test (-bench on a repo PDF, gated on its "Finished" output since -bench doesn't return 0 on success), and uploads the exe as an artifact.

How tested

On Linux, inside a debian:trixie container (the same environment the CI job uses):

bun cmd/build-linux-wine.ts                                              # -> out/dbg64-wine/SumatraPDF.exe (PE32+)
xvfb-run -a wine out/dbg64-wine/SumatraPDF.exe -for-testing -unit-tests  # "Passed all 24 tests", exit 0
xvfb-run -a wine out/dbg64-wine/SumatraPDF.exe -for-testing -bench tests/issue-3219.pdf
                                                                         # "Finished (in 10.83 ms)"

The workflow itself was validated locally with nektos/act running the real job in the same container before pushing.

The source changes are written to be no-ops for MSVC (include/decl fixes, HandleToLong, a mingw-only #ifdef block; the unrar rename lives in the TS lib defs only — premake is untouched), but I could not compile on Windows from this machine — the Windows CI run on this PR is the verification for that.

🤖 Generated with Claude Code

The mingw-w64 cross-build (cmd/build-linux-wine.ts) had drifted since
it was added: the mupdf-libs aggregate removal, the src/base rework and
a number of new/renamed src files broke compile and link. Fix the
drift, plus latent portability bugs the MSVC build can't see:

- case-sensitive #include mismatches (theme.h, SumatraPdf.h)
- INT_MAX used in Vec.h without <limits.h> (add to Base.h)
- 'Size Size() const' rejected by gcc without an elaborated type
- HWND-to-LONG casts rejected by clang; use HandleToLong
- SetThreadDescription missing from mingw-w64 headers before v12
- unrar's internal Archive class collides with src/base/Archive.cpp's
  Archive under GNU ld (MSVC picks one via COMDAT); rename it to
  UnrarArchive in unrar TUs only
- shared lib defs: restore files premake has but the TS defs lost
  (libheif heif_components/metadata/omaf, mupdf cull-device.c,
  options.c, md.c + cmark includes) and add extract's memento.h dir

Prefer the posix-threads mingw flavor: Debian's default is win32
threads, whose libstdc++ lacks the std::mutex that libheif needs.

Add .github/workflows/linux.yml: cross-compile in a debian:trixie
container (mingw-w64 >= 12 required), run the exe's built-in unit
tests under Wine (xvfb), gate a render smoke test on its output, and
upload the exe as an artifact - so this build path cannot rot silently
again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mBFgiNUBqbB5x2dg996Ft
prompt: get SumatraPDF fully working on Linux with a minimal patch and working CI; first PR: the Wine cross-build fixes plus a CI job that builds and tests under Wine
@koppor

koppor commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator Author

I think, for me, this would be a good start when switching my main OS to Linux 😅.

Move the Linux workflow from a debian:trixie container to the plain
ubuntu-24.04 runner and cache the apt packages with
awalsh128/cache-apt-pkgs-action (execute_install_scripts for wine's
update-alternatives postinst).

ubuntu-24.04 ships mingw-w64 v11, which needs three accommodations:

- src/base/WinDynCalls.h: define the Windows 11 DWM corner/border
  enums for pre-v12 headers (the dwm:: wrappers pass them as DWORD)
- ext/darkmodelib/src/StdAfx.h: same, plus the Mica backdrop types
  and newer DWMWA attribute ids the library uses
- cmd/build-with-mingw.ts: mingw-w64 v11 has UIA headers but no
  libuiautomationcore.a import library; synthesize one with dlltool
  from a .def listing the functions we call

Verified in an ubuntu:24.04 container with that exact package set:
full build, "Passed all 24 tests" under Wine 9, render smoke passes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012mBFgiNUBqbB5x2dg996Ft
prompt: run the Linux workflow on ubuntu 24.04 and use awalsh128/cache-apt-pkgs-action for apt installation
@koppor

koppor commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator Author

I am not sure about mingw 11 vs. 12, but the "hack" proposed by Claude sounds reasonable to support Ubuntu-24.04, too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant