This guide gives the steps to build pandite from source and to make the
release packages on your computer. The GitHub workflows in
.github/workflows/ use the same commands and scripts.
Get the source:
git clone https://github.com/xls/pandite.git
cd pandite
If you build for ARM64, also select the component “MSVC C++ ARM64 build tools”. Then add the Rust target:
rustup target add aarch64-pc-windows-msvc
If you make a package for other computers, link the C runtime statically. Then the program does not need the Visual C++ Redistributable. In PowerShell:
$env:RUSTFLAGS = "-C target-feature=+crt-static"
Build the release binary:
cargo build --release -p pandite-app
target\release\pandite.exe.--target aarch64-pc-windows-msvc. The
program is then at target\aarch64-pc-windows-msvc\release\pandite.exe.The release workflow always sets this RUSTFLAGS value for Windows.
When you change RUSTFLAGS, cargo builds everything again.
Make the zip with PowerShell 7:
pwsh packaging/windows/build-zip.ps1 -Exe target/release/pandite.exe -Version 0.1.0 -Target x86_64-pc-windows-msvc -OutDir dist
Find the zip at dist\pandite-0.1.0-x86_64-windows-portable.zip.
The script needs Inno Setup 6.3 or later. It finds ISCC.exe in the
standard Inno Setup 6 folders and on PATH. If ISCC.exe is in a
different folder, set PANDITE_ISCC to its full path.
Make the setup program with PowerShell 7:
pwsh packaging/windows/build-setup.ps1 -Exe target/release/pandite.exe -Version 0.1.0 -Target x86_64-pc-windows-msvc -OutDir dist
dist\pandite-0.1.0-x86_64-windows-setup.exe.-Target aarch64-pc-windows-msvc.The setup program installs the files of the portable zip for the current
user in %LOCALAPPDATA%\Programs\Pandite. It needs no administrator
rights. The task “Associate image files with Pandite” runs
pandite.exe --register. Before an upgrade or an uninstall, the setup
program runs pandite.exe --quit. The uninstall runs
pandite.exe --unregister. The x64 setup program also installs on
Windows 11 on ARM64. The ARM64 setup program installs on ARM64 only. The
setup program is unsigned.
The script needs makeappx.exe and makepri.exe from the Windows SDK. It
finds them in C:\Program Files (x86)\Windows Kits\10\bin\<version>\x64\.
If the SDK is in a different folder, set PANDITE_MAKEAPPX and
PANDITE_MAKEPRI to the full paths of the two tools.
Build the binary and the package in one step:
node packaging/windows/build-msix.mjs --build
dist\pandite-<version>-x86_64-windows.msix.--target aarch64-pc-windows-msvc.--exe <path> instead of
--build.--require-static-crt, the script stops instead.To bundle the x64 and ARM64 packages into one file, run:
node packaging/windows/build-msix.mjs --bundle dist/pandite-0.1.0-x86_64-windows.msix dist/pandite-0.1.0-aarch64-windows.msix
The package is unsigned. The Microsoft Store signs the packages that it accepts. For the Store identity values and for signing, see store-submission.md.
Install the Xcode command line tools:
xcode-select --install
Add both Apple targets to Rust:
rustup target add aarch64-apple-darwin x86_64-apple-darwin
Build both architectures. The deployment target matches
LSMinimumSystemVersion in packaging/macos/Info.plist.
MACOSX_DEPLOYMENT_TARGET=11.0 cargo build --release -p pandite-app --target aarch64-apple-darwin --target x86_64-apple-darwin
Make the universal app, the disk image and the zip:
bash packaging/macos/build-app.sh 0.1.0 dist target
Find pandite-0.1.0-universal-macos.dmg in dist.
Without more settings, the script signs the app ad hoc and does not notarize it. macOS then warns the user before the first start.
For the Mac App Store package and the App Sandbox test build, see mac-app-store.md.
To sign with a Developer ID, set PANDITE_MACOS_SIGN_IDENTITY to the name of
a “Developer ID Application” identity in your keychain. To notarize also, set
PANDITE_APPLE_ID, PANDITE_APPLE_TEAM_ID and PANDITE_APPLE_APP_PASSWORD
(an app-specific password of that Apple ID). The script then sends the app
and the disk image to the Apple notary service and staples the tickets.
The Release workflow does the same when these repository secrets exist:
| Secret | Value |
|---|---|
PANDITE_MACOS_CERT_BASE64 |
The Developer ID Application certificate with its private key, exported as a .p12 file and encoded with base64 |
PANDITE_MACOS_CERT_PASSWORD |
The password of the .p12 file |
PANDITE_APPLE_ID |
The Apple ID of the developer account |
PANDITE_APPLE_TEAM_ID |
Optional. The team identifier (10 characters). Without it, the build reads it from the certificate name |
PANDITE_APPLE_APP_PASSWORD |
An app-specific password of the Apple ID |
To change the
bundle identifier, set PANDITE_BUNDLE_ID before you run the
script.
Install a C toolchain and pkg-config. On Debian and Ubuntu:
sudo apt install build-essential pkg-config
Install the window system and graphics libraries. On Debian and Ubuntu:
sudo apt install libx11-dev libxkbcommon-dev libwayland-dev libvulkan-dev mesa-vulkan-drivers
pandite draws with Vulkan or with OpenGL ES. The Mesa drivers supply both.
Build the release binary:
cargo build --release -p pandite-app
target/release/pandite.Make the tarball:
bash packaging/linux/build-tarball.sh 0.1.0 dist target/release/pandite
dist/pandite-0.1.0-x86_64-linux.tar.gz.The release workflow builds the Linux binary on Ubuntu 22.04. That binary needs glibc 2.35 or later.
The scripts make the packages from the tarball. The packages hold the same
program, desktop entry and icons under /usr.
Install the tools. On Debian and Ubuntu:
sudo apt install dpkg-dev rpm
Make the Debian package:
bash packaging/linux/build-deb.sh 0.1.0 dist dist/pandite-0.1.0-x86_64-linux.tar.gz
Make the RPM package:
bash packaging/linux/build-rpm.sh 0.1.0 dist dist/pandite-0.1.0-x86_64-linux.tar.gz
dist/pandite_0.1.0_amd64.deb and
dist/pandite-0.1.0-1.x86_64.rpm.dpkg-shlibdeps and rpmbuild write the dependencies from the libraries
that the program links. The program loads Vulkan, EGL, X11 and Wayland at
run time. packaging/linux/debian/control and
packaging/linux/pandite.spec list these libraries as recommended
packages.
The npm package pandite in packaging/npm is an installer for Node.js 18
or later. It is a separate Node.js script. The program itself has no
network code. npx pandite reads the releases from the GitHub API. It
downloads the setup program, the macOS disk image or the Linux tarball of a
release. It checks the file against SHA256SUMS.txt of the same release
and installs it. See packaging/npm/README.md for the commands.
The installer has its own version in packaging/npm/package.json. This
version is independent of the Pandite version. A Pandite release does not
change the installer. Publish the installer only when its code changes.
version in packaging/npm/package.json. npm does not accept
the same version two times.If you are not logged in to npm, log in:
npm login
Go to the package folder:
cd packaging/npm
Run the offline test. Make sure that the last line is
NPM INSTALLER VERIFIED:
node test.mjs
Optional: show the files of the package. The list holds bin/, lib/,
LICENSE, README.md and package.json only:
npm pack --dry-run
Publish the package:
npm publish
Run the tests:
cargo test --workspace
Run the linter:
cargo clippy --workspace --all-targets -- -D warnings
Check the formatting:
cargo fmt --all -- --check
Check the packaging files:
node packaging/check.mjs
Test the npm installer. The test uses no network:
node packaging/npm/test.mjs
The GPU tests need a GPU adapter. When the computer has no adapter, these
tests print a notice and pass. To make a missing adapter fail the tests,
set PANDITE_REQUIRE_GPU=1.
On Windows, the text recognition tests in crates/pandite-ocr/tests need
the Windows OCR engine and an OCR language. Without them, these tests print
a notice and pass. To make a missing engine fail the tests, set
PANDITE_REQUIRE_OCR=1. The GitHub runners can have no OCR language, so
the CI does not set it. On macOS and Linux, these tests use the built-in
recognizer and always run.
The unit tests of the built-in recognizer run on every system, also on
Windows. They compare its results with the results of its reference
implementation, in crates/pandite-ocr/tests/fixtures.
To measure Windows OCR time against the size limit for large images, run:
cargo run --release -p pandite-ocr --example ocr_bench
To read image files with the recognizer of the system and print the text and the time for each file, run:
cargo run --release -p pandite-ocr --example ocr_file -- <image file>...
The GitHub runners have no GPU. The CI runs the unit tests only. It sets
WGPU_BACKEND to a backend that the build does not contain, so the GPU
tests skip there. Run the GPU tests on a computer with a real GPU.
| File | Purpose |
|---|---|
packaging/extensions.txt |
The file extensions pandite opens. It must equal the output of cargo run -p pandite-codecs --example extensions. |
packaging/windows/AppxManifest.xml |
MSIX manifest with the file associations. |
packaging/windows/assets/ |
MSIX logos at every scale. |
packaging/macos/Info.plist |
App bundle keys and document types. |
packaging/macos/pandite.icns |
macOS icon. |
packaging/linux/pandite.desktop |
Desktop entry with the MIME types. |
packaging/linux/icons/ |
Linux icons. |
packaging/windows/pandite.iss |
Inno Setup script of the Windows setup program. |
packaging/windows/build-setup.ps1 |
Builds the setup program with ISCC.exe. |
packaging/linux/debian/ |
Debian control template, postinst and postrm. |
packaging/linux/build-deb.sh, build-rpm.sh |
Build the .deb and the .rpm from the tarball. |
packaging/linux/pandite.spec |
RPM spec. |
packaging/npm/ |
npm installer package and its offline test. |
docs/THIRD-PARTY-NOTICES.md |
Licenses of the dependencies. |
After you change a file in this table, do the related step:
packaging/extensions.txt,
the manifest, Info.plist and pandite.desktop. Then run
node packaging/check.mjs.node packaging/make-assets.mjs.node packaging/third-party-notices.mjs.build-deb.sh,
pandite.spec and the LAYOUT table in packaging/check.mjs.[Files] in
pandite.iss.[workspace.package] in Cargo.toml.main.Make a tag that is v plus the version, and push it:
git tag v0.1.0
git push origin v0.1.0
SHA256SUMS.txt and publishes the GitHub release.If the tag and the Cargo.toml version are different, the workflow stops
before it builds. To test the packaging without a release, start the
Release workflow manually on a branch (Actions, Release, Run workflow). The
packages are then workflow artifacts.
The release does not publish the npm installer. npx pandite finds the new
release on GitHub. The release must keep the file names of the build
scripts and SHA256SUMS.txt. node packaging/check.mjs compares these
names with the names that the installer uses.
The workflow builds the setup program with Inno Setup. If the runner has no
Inno Setup 6, the workflow downloads the version in INNO_SETUP_VERSION
and compares it with INNO_SETUP_SHA256 in release.yml. To change the
version, change both values.
When the repository is private, GitHub counts the Actions minutes against the quota of the account. Windows minutes cost more than Linux minutes, and macOS minutes cost the most. Each CI run uses two Windows jobs and two macOS jobs. Public repositories do not pay for minutes on these standard runners.