Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/linux-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Linux Package

on:
push:
branches: [main, master]
tags: ['v*']
pull_request:
branches: [main, master]
workflow_dispatch:

jobs:
build:
name: Build Linux x86_64
runs-on: ubuntu-24.04
steps:
- name: Check out source code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y meson ninja-build gcc g++ libgtk-4-dev

- name: Configure
run: |
meson setup linux/builddir-dist \
--prefix=/usr \
--buildtype=release \
--strip \
-Db_lto=true

- name: Build
run: meson compile -C linux/builddir-dist -j$(nproc)

- name: Run tests
run: meson test -C linux/builddir-dist

- name: Package
run: bash linux/dist/package.sh --release

- name: Upload tarball artifact
uses: actions/upload-artifact@v4
with:
name: sumatrapdf-linux-x86_64
path: out/sumatrapdf-*-linux-x86_64.tar.gz
retention-days: 30

release:
name: Publish Release
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: sumatrapdf-linux-x86_64

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: sumatrapdf-*-linux-x86_64.tar.gz
generate_release_notes: true
draft: false
prerelease: ${{ contains(github.ref, 'dev') || contains(github.ref, 'rc') }}
83 changes: 61 additions & 22 deletions agents.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,81 @@
This is a C++ program for Windows, using mostly win32 windows API functions
This is a C++ program for Windows, using mostly win32 windows API functions.

We don't use STL but our own string / helper / container functions implemented in src\utils directory
Never commit changes automatically. Always wait for explicit command to commit changes.

Assume that Visual Studio command-line tools are available in the PATH environment variable (cl.exe, msbuild.exe etc.)
## Project Layout

Our code is in src/ directory. External dependencies are in ext/ directory and mupdf\ directory
- `src/` — Our application code (C++17, Win32 API)
- `src/utils/` — Custom utility library (strings, containers, file I/O, Win32 helpers)
- `ext/` — External dependencies (freetype, harfbuzz, libjpeg-turbo, zlib, etc.)
- `mupdf/` — MuPDF library (PDF rendering engine)
- `cmd/` — TypeScript build/codegen scripts (run with `bun`)
- `docs/md/` — Documentation in Markdown
- `vs2022/` — Generated Visual Studio solution (do not edit manually)
- `out/` — Build output directory

To build run: bun ./cmd/build.ts
## Code Conventions

This creates ./out/dbg64/SumatraPDF.exe executable
- **No STL** — Use custom containers: `Vec<T>`, `StrVec`, `Dict<K,V>` from `src/utils/`
- **No exceptions** — Explicit error handling throughout
- **String utilities**: `str::Dup()`, `str::Free()`, `str::Eq()` etc. from `src/utils/StrUtil.h`
- **Naming**: PascalCase for types/classes, camelCase for variables, `CmdXxx` for commands
- **Memory**: Manual management with `new`/`delete`, `str::Dup()`/`str::Free()`
- **Unicode**: `WCHAR*` for Win32 UI, `char*` (UTF-8) internally
- **Formatting**: Chromium-based style, 4-space indent, 120 column limit (see `.clang-format`)
- **Key namespaces**: `str::`, `path::`, `file::`, `url::`, `trans::`, `mui::`

To debug run: `windbgx -Q -o -g ./out/dbg64/SumatraPDF.exe`
## Build & Test

After making a change to .cpp, .c or .h file (and before running build.ts), run clang-format on those files to reformat them in place
- **Build**: `bun ./cmd/build.ts` → produces `./out/dbg64/SumatraPDF.exe`
- **Test**: `bun cmd/run-tests.ts`
- **Debug**: `windbgx -Q -o -g ./out/dbg64/SumatraPDF.exe`
- **Format**: After modifying `.cpp`, `.c`, or `.h` files, run `clang-format -i <file>` before building
- Visual Studio command-line tools (cl.exe, msbuild.exe) are available in PATH

Never commit changes automatically. Always wait for explicit command to commit changes.
## Generated Files (do not edit manually)

These files are generated by TypeScript scripts in `cmd/`:

| File | Generator | Purpose |
|------|-----------|---------|
| `src/Commands.h`, `src/Commands.cpp` | `bun cmd/gen-commands.ts` | Command IDs and metadata |
| `src/Settings.h`, `src/Settings.cpp` | `bun cmd/gen-settings.ts` | Settings structure |
| `src/Flags.h`, `src/Flags.cpp` | `bun cmd/gen-flags.ts` | Command-line flags |

## Adding a new advanced setting

To add a new advanced setting:
- add definition in cmd/gen-settings.ts
- run "bun cmd/gen-settings.ts" to regenerate src/Settings.h and src/Settings.cpp
- Add definition in `cmd/gen-settings.ts`
- Run `bun cmd/gen-settings.ts` to regenerate `src/Settings.h` and `src/Settings.cpp`

## Adding a new command

To add a new command:
- add to cmd/gen-commands.ts, always at the end of the list (before the "CmdNone" command)
- run "bun cmd/gen-commands.ts" to regenerate src/Commands.h and src/Commands.cpp
- document in docs/md/Commands.md
- document in docs/md/Version-history.md in **next** section
- Add to `cmd/gen-commands.ts`, always at the end of the list (before the `CmdNone` command)
- Run `bun cmd/gen-commands.ts` to regenerate `src/Commands.h` and `src/Commands.cpp`
- Document in `docs/md/Commands.md`
- Document in `docs/md/Version-history.md` in **next** section

## Adding a new cmd-line flag

To add a new cmd-line flag:
- add to cmd/gen-flags.ts
- run "bun cmd/gen-flags.ts" to regenerate src/Flags.h and src/Flags.cpp
- implement handling in Flags.cpp
- document in docs/md/Version-history.md in **next** section
- Add to `cmd/gen-flags.ts`
- Run `bun cmd/gen-flags.ts` to regenerate `src/Flags.h` and `src/Flags.cpp`
- Implement handling in `Flags.cpp`
- Document in `docs/md/Version-history.md` in **next** section

## Key Architecture

- **Engine layer**: `src/EngineBase.h` defines the abstract document engine interface; `src/EngineMupdf.h` implements PDF/XPS via MuPDF
- **Display**: `src/DisplayModel.h` manages page layout, zoom, scroll (MVC pattern)
- **Window**: `src/MainWindow.h` is the main app window; `src/Canvas.h` is the rendering surface
- **Settings**: `src/AppSettings.h` for runtime config; advanced settings in generated `src/Settings.h`
- **UI widgets**: `src/wingui/` wraps Win32 controls; `src/mui/` is the custom UI framework

## Documentation

- [docs/md/Build-system.md](docs/md/Build-system.md) — Build instructions
- [docs/md/Debugging-Sumatra.md](docs/md/Debugging-Sumatra.md) — Debugging guide
- [docs/md/Commands.md](docs/md/Commands.md) — Command reference
- [docs/md/Version-history.md](docs/md/Version-history.md) — Release notes
- [docs/md/Contribute-to-SumatraPDF.md](docs/md/Contribute-to-SumatraPDF.md) — Contribution guide

## Windows Shell Safety

Expand Down
31 changes: 31 additions & 0 deletions linux/dist/org.sumatrapdf.SumatraPDF.metainfo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>org.sumatrapdf.SumatraPDF</id>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<name>SumatraPDF</name>
<summary>Fast, minimal document viewer</summary>
<description>
<p>
SumatraPDF is a fast, lightweight document viewer for PDF, EPUB, XPS,
CBZ, and other formats. Originally Windows-only, this is the Linux port
built with GTK 4.
</p>
<p>Features:</p>
<ul>
<li>Fast PDF rendering via MuPDF engine</li>
<li>Support for PDF, EPUB, XPS, CBZ, MOBI, FB2 formats</li>
<li>Lightweight and low memory footprint</li>
<li>Keyboard-driven navigation</li>
</ul>
</description>
<url type="homepage">https://www.sumatrapdfreader.org</url>
<url type="bugtracker">https://github.com/nicekr/sumatrapdf/issues</url>
<launchable type="desktop-id">sumatrapdf.desktop</launchable>
<content_rating type="oars-1.1" />
<releases>
<release version="3.6-dev" date="2026-05-18">
<description><p>Initial Linux port (development preview).</p></description>
</release>
</releases>
</component>
142 changes: 142 additions & 0 deletions linux/dist/package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/bin/bash
# Build a distributable Linux package for SumatraPDF.
# Produces:
# out/sumatrapdf-<version>-linux-x86_64.tar.gz (portable archive)
# out/SumatraPDF-<version>-x86_64.AppImage (if appimagetool is available)
#
# Usage: ./linux/dist/package.sh [--release]
# --release: Build with optimizations (release mode)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
VERSION=$(grep "version:" "$PROJECT_ROOT/meson.build" | head -1 | sed "s/.*'\(.*\)'.*/\1/")
ARCH=$(uname -m)
BUILD_TYPE="debugoptimized"

if [[ "${1:-}" == "--release" ]]; then
BUILD_TYPE="release"
fi

BUILDDIR="$PROJECT_ROOT/linux/builddir-dist"
OUTDIR="$PROJECT_ROOT/out"
INSTALL_PREFIX="$BUILDDIR/install"

echo "=== SumatraPDF Linux Package Builder ==="
echo "Version: $VERSION"
echo "Arch: $ARCH"
echo "Build: $BUILD_TYPE"
echo ""

# ─── Configure & Build ────────────────────────────────────────────────────────

echo "[1/5] Configuring..."
if [[ -d "$BUILDDIR" && -f "$BUILDDIR/build.ninja" ]]; then
echo " Using existing build directory: $BUILDDIR"
else
meson setup "$BUILDDIR" \
--prefix=/usr \
--buildtype="$BUILD_TYPE" \
--strip \
-Db_lto=true 2>&1 | tail -3
fi

echo "[2/5] Building..."
meson compile -C "$BUILDDIR" -j"$(nproc)"

echo "[3/5] Installing to staging directory..."
rm -rf "$INSTALL_PREFIX"
DESTDIR="$INSTALL_PREFIX" meson install -C "$BUILDDIR" --no-rebuild 2>&1 | tail -5

# ─── Create tarball ───────────────────────────────────────────────────────────

echo "[4/5] Creating tarball..."
mkdir -p "$OUTDIR"

TARBALL_NAME="sumatrapdf-${VERSION}-linux-${ARCH}"
TARBALL_DIR="$BUILDDIR/$TARBALL_NAME"
rm -rf "$TARBALL_DIR"
mkdir -p "$TARBALL_DIR"

# Copy binary
cp "$INSTALL_PREFIX/usr/bin/sumatrapdf" "$TARBALL_DIR/"

# Copy desktop and icon
cp "$INSTALL_PREFIX/usr/share/applications/sumatrapdf.desktop" "$TARBALL_DIR/"
cp "$INSTALL_PREFIX/usr/share/icons/hicolor/256x256/apps/sumatrapdf.png" "$TARBALL_DIR/"

# Create a simple README
cat > "$TARBALL_DIR/README.txt" << 'EOF'
SumatraPDF for Linux
====================

A fast, lightweight document viewer for PDF, EPUB, XPS, CBZ and more.

Usage:
./sumatrapdf [file.pdf] [output.png]

Install (optional):
sudo cp sumatrapdf /usr/local/bin/
sudo cp sumatrapdf.desktop /usr/share/applications/
sudo cp sumatrapdf.png /usr/share/icons/hicolor/256x256/apps/

For more information: https://www.sumatrapdfreader.org
EOF

tar -czf "$OUTDIR/${TARBALL_NAME}.tar.gz" -C "$BUILDDIR" "$TARBALL_NAME"
echo " -> $OUTDIR/${TARBALL_NAME}.tar.gz"

# ─── Create AppImage (if appimagetool is available) ───────────────────────────

echo "[5/5] Creating AppImage..."

APPIMAGETOOL=""
if command -v appimagetool &>/dev/null; then
APPIMAGETOOL="appimagetool"
elif [[ -x "$PROJECT_ROOT/tools/appimagetool" ]]; then
APPIMAGETOOL="$PROJECT_ROOT/tools/appimagetool"
fi

if [[ -n "$APPIMAGETOOL" ]]; then
APPDIR="$BUILDDIR/AppDir"
rm -rf "$APPDIR"
mkdir -p "$APPDIR/usr/bin"
mkdir -p "$APPDIR/usr/share/applications"
mkdir -p "$APPDIR/usr/share/icons/hicolor/256x256/apps"
mkdir -p "$APPDIR/usr/share/metainfo"

cp "$INSTALL_PREFIX/usr/bin/sumatrapdf" "$APPDIR/usr/bin/"
cp "$INSTALL_PREFIX/usr/share/applications/sumatrapdf.desktop" "$APPDIR/"
cp "$INSTALL_PREFIX/usr/share/applications/sumatrapdf.desktop" "$APPDIR/usr/share/applications/"
cp "$INSTALL_PREFIX/usr/share/icons/hicolor/256x256/apps/sumatrapdf.png" "$APPDIR/"
cp "$INSTALL_PREFIX/usr/share/icons/hicolor/256x256/apps/sumatrapdf.png" "$APPDIR/usr/share/icons/hicolor/256x256/apps/"
cp "$PROJECT_ROOT/linux/dist/org.sumatrapdf.SumatraPDF.metainfo.xml" "$APPDIR/usr/share/metainfo/"

# AppRun launcher
cat > "$APPDIR/AppRun" << 'APPRUN'
#!/bin/bash
SELF="$(readlink -f "$0")"
HERE="${SELF%/*}"
exec "${HERE}/usr/bin/sumatrapdf" "$@"
APPRUN
chmod +x "$APPDIR/AppRun"

# Symlink icon
ln -sf usr/share/icons/hicolor/256x256/apps/sumatrapdf.png "$APPDIR/.DirIcon"

APPIMAGE_NAME="SumatraPDF-${VERSION}-${ARCH}.AppImage"
ARCH="$ARCH" "$APPIMAGETOOL" "$APPDIR" "$OUTDIR/$APPIMAGE_NAME" 2>&1 | tail -3
echo " -> $OUTDIR/$APPIMAGE_NAME"
else
echo " (skipped - appimagetool not found)"
echo " Install from: https://github.com/AppImage/appimagetool/releases"
echo " Or: wget -O tools/appimagetool https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage && chmod +x tools/appimagetool"
fi

# ─── Summary ──────────────────────────────────────────────────────────────────

echo ""
echo "=== Done ==="
echo "Outputs in: $OUTDIR/"
ls -lh "$OUTDIR"/sumatrapdf-* "$OUTDIR"/SumatraPDF-* 2>/dev/null || true
12 changes: 12 additions & 0 deletions linux/dist/sumatrapdf.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Desktop Entry]
Type=Application
Name=SumatraPDF
GenericName=Document Viewer
Comment=View PDF, EPUB, XPS, CBZ and other document formats
Exec=sumatrapdf %f
Icon=sumatrapdf
Terminal=false
Categories=Office;Viewer;Graphics;
MimeType=application/pdf;application/epub+zip;application/x-cbz;application/oxps;application/vnd.ms-xpsdocument;image/svg+xml;
Keywords=PDF;document;viewer;reader;
StartupNotify=true
Loading
Loading