BlinkGTK Portable Application Guide

Author: BlinkGTK Project
Last updated: 2026-07-03
Audience: Developers who want to build a self-contained (portable) application from the BlinkGTK binary distribution that runs from a single directory


1. What is a portable build?

A portable BlinkGTK application bundles your application executable together with the complete BlinkGTK / Chromium runtime in a single directory, so that it runs by simply copying the directory — no system installation (RPM/DEB) required. It relies on $ORIGIN-relative RPATH (paths resolved relative to the executable itself), so the directory keeps working wherever it is moved.

However, "self-contained" has a well-defined boundary: only the BlinkGTK and Chromium runtimes are bundled. GTK4, glibc, GPU drivers and similar components come from the host system. If you do not understand this boundary, you will run into "I copied it but it does not start" situations. Chapter 2 explains the constraints in detail.

2. Runtime environment and constraints (important)

A portable build does not run everywhere. Check the following constraints carefully.

2.1 CPU architecture

2.2 glibc version (the most important lower bound)

2.3 GTK4 comes from the host system (not bundled)

2.4 Wayland only (does not run on X11)

2.5 GPU / rendering paths

2.6 Chromium sandbox and kernel settings

2.7 Filesystem requirements

2.8 Resources

2.9 Fonts

2.10 Constraint checklist

Item Requirement Check command
CPU x86_64 uname -m
glibc build-era or newer ldd --version / ldd ... | grep "not found"
GTK4 4.6+ (system) pkg-config --modversion gtk4
Session Wayland echo $XDG_SESSION_TYPE
GPU (EGL) Mesa + dmabuf isolate with software path
user namespaces enabled check on sandbox startup failure
Filesystem ext4 etc. + exec allowed mount | grep noexec
Japanese fonts required on host fc-list | grep -i mincho etc.

3. Portable application layout

Recommended layout (single self-contained directory):

myapp-portable/
├── myapp                    # your application executable (RPATH=$ORIGIN/lib)
├── run.sh                   # launch script (optional, for environment variables)
├── lib/
│   ├── libblinkgtk-0.1.so.0.0.0
│   ├── libblinkgtk-0.1.so.0     -> libblinkgtk-0.1.so.0.0.0
│   └── chromium/            # complete Chromium runtime (from the binary distribution)
│       ├── *.so             # shared libraries
│       ├── icudtl.dat / snapshot_blob.bin / v8_context_snapshot.bin
│       ├── content_shell.pak
│       └── locales/ja.pak, en-US.pak
├── share/
│   └── myapp/               # your application resources
└── THIRD_PARTY_NOTICES.html # mandatory (Chapter 6)

The runtime set is obtained by copying usr/lib64/blinkgtk-0.1/ from the binary distribution (runtime tarball) into lib/ as-is. Do not cherry-pick files — every Chromium runtime .so, .pak, .dat, .bin, and locales/ file is required at startup (missing files are the classic cause of startup crashes).

4. Building

Build your application with pkg-config. Linking the PartitionAlloc allocator shim directly is mandatory (pkg-config includes it automatically). Without the shim, page loads fail and you get a black screen.

gcc -o myapp myapp.c \
  $(pkg-config --cflags --libs blinkgtk-0.1 gtk4)

If you link manually without pkg-config, you must add
-lbase_allocator_partition_allocator_src_partition_alloc_allocator_shim in addition to -lblinkgtk-0.1.

4.2 Setting RPATH (the core of portability)

Give the executable an $ORIGIN-relative RPATH:

gcc -o myapp myapp.c \
  $(pkg-config --cflags blinkgtk-0.1 gtk4) \
  -Wl,-rpath,'$ORIGIN/lib' -Wl,-rpath,'$ORIGIN/lib/chromium' \
  $(pkg-config --libs blinkgtk-0.1 gtk4)

As an alternative to RPATH, a launch script can set LD_LIBRARY_PATH:

#!/bin/sh
# run.sh — place directly under myapp-portable/
HERE="$(cd "$(dirname "$0")" && pwd)"
export LD_LIBRARY_PATH="$HERE/lib:$HERE/lib/chromium${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
exec "$HERE/myapp" "$@"

4.3 Verification

Always verify before distributing:

# 1. Dependency completeness (zero "not found" lines)
ldd ./myapp | grep "not found"

# 2. The shim is a direct NEEDED entry
readelf -d ./myapp | grep allocator_shim

# 3. V8 snapshot consistency (normally consistent when taken from one distribution)
# Never mix libv8.so / snapshot_blob.bin / v8_context_snapshot.bin from
# different distribution versions in lib/chromium/ (causes startup crashes)

# 4. Launch test on a real Wayland session
./run.sh

5. Distribution

6. License obligations (mandatory)

When you redistribute the BlinkGTK / Chromium runtime, the following are required:

  1. Bundle THIRD_PARTY_NOTICES.html — the aggregated license attributions included in the binary distribution. Bundle it in your portable app as-is (required by the license terms of the hundreds of third-party components contained in Chromium).
  2. About FFmpeg (LGPL) — the bundled libffmpeg.so is LGPL v2.1+. It is shipped as an independent shared library; keep it replaceable by users (do not statically link, remove or rename it).
  3. Also bundle the BlinkGTK LICENSE file.

7. Troubleshooting (portable-specific)

Symptom Likely cause Action
GLIBC_x.xx not found host glibc too old update host or use a same-generation environment (§2.2)
Crash right after startup (SIGTRAP) mixed V8 snapshots / shim not linked check items 2 and 3 in §4.3
No window appears X11 session / no compositor check $XDG_SESSION_TYPE (§2.4)
Page stays black shim not linked verify with readelf -d (§4.1)
Permission denied noexec mount / lost exec bits §2.7 (re-extract from tar.gz)
Starts but shows tofu/garbled text no Japanese fonts on host §2.9
Renderer fails to start user namespaces disabled §2.6