JBrowser Source Docs
You are reading the documentation for JBrowser 1.4.0. The newest release is 1.5.4. Go to the latest documentation

Building the app

The short version: .\tools\build_installer.ps1 builds the app and then the installer.

Output Script Result
The app (PyInstaller, one folder) .\tools\build_app.ps1 dist\JBrowser\JBrowser.exe and its _internal\ folder
The installer (Inno Setup) .\tools\build_installer.ps1 dist\installer\JBrowser-Setup-<version>.exe and .exe.sha256

The PowerShell scripts share tools/common.ps1: $Root, $Py (the .venv Python), the Step helper, and where output goes.

Where the output goes#

  • normally dist\ (and build\ for PyInstaller's temporary files) inside the repository, ignored by git;
  • %LOCALAPPDATA%\JBrowser-build\ when the repository is inside OneDrive, because OneDrive would upload about 450 MB per build and lock files while PyInstaller is still writing them;
  • anywhere you like: set JBROWSER_BUILD_DIR.

tools\build_app.ps1#

.\tools\build_app.ps1              # one-folder build (the one the installer uses)
.\tools\build_app.ps1 -SkipDeps    # don't update packages first
.\tools\build_app.ps1 -OneFile     # a single JBrowser.exe (slow to start; not used for releases)
  1. tools\update_deps.py updates and verifies the packages (skipped with -SkipDeps).
  2. It refuses to continue if JBrowser is running from the build folder, because open files would break the build.
  3. tools\make_icon.py renders assets\jbrowser.ico from the vector logo, and tools\version.py --sync writes the exe's version resource (tools\version_info.txt).
  4. PyInstaller builds with JBrowser.spec.

The spec#

Choice Why
one folder (COLLECT) starts much faster than one file: Qt WebEngine is about 500 MB unpacked
console=False a GUI app: no console window
icon, version the icon and the details in the file's Properties
collect_submodules("jbrowser") dialogs are imported lazily, so PyInstaller must be told about them
PyQt6.QtWebChannel provides qwebchannel.js for the isolated autofill bridge
PyQt6.QtPrintSupport, PyQt6.QtMultimedia + assets\sounds printing, and the welcome sounds (the FFmpeg plugin is filtered out: sounds use the native backend)
upx=False UPX corrupts Qt WebEngine binaries

PyInstaller's PyQt6 hooks bundle QtWebEngineProcess.exe, the Chromium .pak resources, locales and ICU data. Keep the whole dist\JBrowser folder together.

Checking a build#

Run the built JBrowser.exe with a throw-away profile and look at: a page loads, DevTools open, a download works, the welcome sound plays, and it exits cleanly (exit code 0, no QtWebEngineProcess.exe left behind). The log is in <profile-dir>\Logs\jbrowser.log.

& "$env:LOCALAPPDATA\JBrowser-build\dist\JBrowser\JBrowser.exe" --profile-dir "$env:TEMP\jb-build-test"

Code signing (optional)#

Unsigned installers trigger a SmartScreen warning until they build up a reputation. With a code-signing certificate, sign JBrowser.exe before building the installer, then sign the installer and recompute its .sha256:

signtool sign /fd SHA256 /tr http://timestamp.digicert.com /td SHA256 /a dist\JBrowser\JBrowser.exe