Building and packaging¶
Prerequisites¶
| Platform | Toolchain | Packages |
|---|---|---|
| Linux | GCC 11+ / Clang 14+, CMake 3.20+, Ninja | build-essential cmake ninja-build libuv1-dev zlib1g-dev libssl-dev libsqlite3-dev |
| Windows | MinGW-w64 GCC (MSYS2 MINGW64) | mingw-w64-x86_64-toolchain, cmake, ninja, openssl, libuv, sqlite3, zlib, git |
| macOS | Xcode CLT, CMake, Ninja | brew install libuv openssl@3 sqlite |
Node.js 20+ is required for the frontend.
The libuvcpp SDK¶
uvscope requires the libuvcpp 1.8.2 release SDK. Earlier releases lack the fixes uvscope used
to carry as local patches (TLS SNI, POSIX blocking-I/O timeouts, a complete cmake --install
tree and the SOCKS5 proxy failure stage); those are all part of 1.8.1/1.8.2. Configure fails
early when the detected SDK is older than 1.8.2.
Build the SDK from the release tag:
./scripts/build-libuvcpp.sh
This clones v1.8.2 into .deps/libuvcpp-src, applies the patches in
patches/upstream/ (currently the WebSocket handshake-header patch),
builds a lean runtime (HTTP/1.1 + HTTP/2, WebSocket, webapp, SSL, SQLite, WSDL, brotli) and
installs it to .deps/libuvcpp. A cached source
tree on an older tag is moved to the requested release automatically. Set LIBUVCPP_TAG=vX.Y.Z to
pin another release, UVCPP_ENABLE_NGHTTP2=OFF to build without HTTP/2, or
UVCPP_ENABLE_BROTLI=OFF to build without brotli (the daemon then advertises and decodes only
gzip/deflate; the smoke test skips its brotli assertion).
Experimental HTTP/3 and QUIC¶
libuvcpp's QUIC and HTTP/3 modules need an OpenSSL with SSL_set_quic_tls_cbs; that API is
only in OpenSSL 3.6+. The OpenSSL shipped by Ubuntu 22.04/24.04 (3.0.x), mainline 3.4/3.5
and quictls do not have it, and the bundled ngtcp2 1.25 backend rejects them. Release builds
therefore keep UVCPP_ENABLE_QUIC=OFF. To build an experimental SDK, compile OpenSSL 3.6+ into
a prefix and point both the SDK and uvscope at it:
export UVCPP_ENABLE_QUIC=ON UVCPP_ENABLE_HTTP3=ON
export OPENSSL_ROOT_DIR=/path/to/openssl-3.6
./scripts/build-libuvcpp.sh .deps/libuvcpp-src .deps/libuvcpp-quic
cmake -S . -B build-quic -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DUVCPP_ROOT="$PWD/.deps/libuvcpp-quic" -DOPENSSL_ROOT_DIR="$OPENSSL_ROOT_DIR" \
-DCMAKE_BUILD_RPATH="$OPENSSL_ROOT_DIR/lib"
On Unix the build script passes CMAKE_INSTALL_RPATH_USE_LINK_PATH=ON, which appends the
custom OpenSSL lib directory to libuvcpp.so's installed RUNPATH. This is required because the
dynamic linker resolves libuvcpp.so's libssl dependency with libuvcpp.so's own RUNPATH, not
the uvscope executable's; without it the process loads the system OpenSSL 3.0 and fails with
OPENSSL_3.5.0 not found. No LD_LIBRARY_PATH is needed for an SDK built by the current script.
If you reuse an older QUIC SDK, either rebuild it or set
LD_LIBRARY_PATH="$OPENSSL_ROOT_DIR/lib:$LD_LIBRARY_PATH" when running the daemon.
The resulting daemon reports http3: true / quic: true from /api/health; packages built this
way must ship or require that OpenSSL. Do not mix a custom OpenSSL with the system one in release
artifacts.
The experimental end-to-end check uses a local HTTP/3 origin, so it does not depend on a public endpoint:
g++ -std=c++17 -O2 -pthread scripts/h3-test-server.cpp \
-o build-quic/h3-test-server \
-I.deps/libuvcpp-quic/include -I.deps/openssl-3.6/include \
-L.deps/libuvcpp-quic/lib -L.deps/openssl-3.6/lib \
-luvcpp -lssl -lcrypto -luv -lz \
-Wl,-rpath,"$PWD/.deps/libuvcpp-quic/lib:$PWD/.deps/openssl-3.6/lib"
bash ./scripts/quic-smoke-test.sh ./build-quic/uvscope ./build-quic/h3-test-server
The QUIC experimental workflow (.github/workflows/quic.yml) runs the same check on Linux,
weekly, on demand, and when QUIC-related files change. It builds OpenSSL 3.6.5 from source and
caches the prefix between runs.
To use an existing SDK:
export UVCPP_ROOT=/path/to/libuvcpp
The SDK must expose include/uvcpp/uvcpp_config.h and lib/libuvcpp.so (or libuvcpp.dll.a on
Windows).
Build¶
./scripts/build.sh
# or manually:
npm --prefix web ci
npm --prefix web run build
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DUVCPP_ROOT="$UVCPP_ROOT"
cmake --build build -j
./build/uvscope --self-check
--self-check does not touch the network. It verifies:
- PBKDF2 hash and verification;
- SQLite migration, setup, login and session lookup;
- a real libuvcpp HTTP server + client round-trip.
Run¶
./build/uvscope --host 127.0.0.1 --port 8787 --open
Data directory defaults:
- Linux:
$XDG_DATA_HOME/uvscopeor~/.local/share/uvscope - macOS:
~/Library/Application Support/uvscope - Windows:
%APPDATA%\uvscope
Override with --data-dir or UVSCOPE_DATA_DIR.
Linux packages¶
cmake --install build --prefix /tmp/uvscope-stage
cpack --config build/CPackConfig.cmake -G DEB -B build/packages
cpack --config build/CPackConfig.cmake -G RPM -B build/packages
The CPack install rules include:
/usr/bin/uvscope/usr/share/uvscope/web/usr/share/applications/uvscope.desktop(Icon=uvscope)/usr/share/icons/hicolor/{16..512}x{...}/apps/uvscope.pngand/usr/share/icons/hicolor/scalable/apps/uvscope.svg/usr/lib/<arch>/uvscope/libuvcpp.so(andlibllhttp.so*when present)
Runtime dependencies: libc6, libstdc++6, libssl3, libuv1, zlib1g, libsqlite3-0.
The RPM equivalent is openssl-libs, libuv, zlib, sqlite-libs.
Windows¶
Build in an MSYS2 MINGW64 shell. Use the SDK from scripts/build-libuvcpp.sh (adapt paths
for MSYS2) and configure with the MinGW generator:
cmake -S . -B build-mingw -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DUVCPP_ROOT=/c/uvscope-sdk/libuvcpp \
-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
cmake --build build-mingw -j
cmake --install build-mingw --prefix stage
The install tree must contain:
stage/bin/uvscope.exe
stage/bin/libuvcpp.dll
stage/bin/libssl-3-x64.dll
stage/bin/libcrypto-3-x64.dll
stage/bin/libgcc_s_seh-1.dll
stage/bin/libstdc++-6.dll
stage/bin/libwinpthread-1.dll
stage/web/index.html
The CI workflow copies the MinGW runtime DLLs from the MSYS2 prefix. The Inno Setup script is
packaging/windows/uvscope.iss.
packaging/windows/uvscope.rc.in embeds packaging/icons/uvscope.ico into uvscope.exe, and the
installer uses the same file for SetupIconFile and its shortcuts. The .ico, .icns, PNG sizes
and SVG all derive from the web favicon (web/public/favicon.svg).
Build the installer:
iscc packaging\windows\uvscope.iss
macOS¶
brew install libuv openssl@3 sqlite
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DUVCPP_ROOT="$PWD/.deps/libuvcpp" \
-DOPENSSL_ROOT_DIR="$(brew --prefix openssl@3)"
cmake --build build -j
macOS builds are source-oriented in 1.0.x. The install tree carries share/uvscope/uvscope.icns,
but a Finder-visible icon needs a signed/notarized .app, which is later work. Windows arm64 is
not part of the 1.x matrix; MSYS2 CLANGARM64 is still preview.
Verification scripts¶
./build/uvscope --self-check # offline crypto/IPC/CA/server checks
bash ./scripts/smoke-test.sh ./build/uvscope 18787 18788
bash ./scripts/h2-smoke.sh ./build/uvscope 18820 18821
./scripts/bench.sh ./build/uvscope --requests 500
npm --prefix web run check:i18n
h2-smoke.sh starts a throwaway daemon and a local Node.js HTTP/2 server, then verifies a real
ALPN h2 probe (version, stream id, frame summary). It requires curl, openssl, node and
python3 (or python); set OPENSSL_BIN when Homebrew's keg-only OpenSSL is needed.
CI¶
.github/workflows/ci.ymlbuilds the frontend and the daemon on Linux x64, Windows x64 (MinGW) and macOS arm64. Linux runs ctest and the full smoke suite; Windows runs--self-check, a ConPTY terminal smoke and the HTTP/2 runtime smoke; macOS runs--self-checkand the HTTP/2 runtime smoke..github/workflows/docs.ymlbuilds the MkDocs site and deploys it to GitHub Pages frommain..github/workflows/release.ymlruns on tagsv*and publishes:- Linux x64 / arm64 tar.gz and deb/rpm where supported;
- Windows x64 zip and Inno Setup installer;
- macOS arm64 tar.gz;
SHA256SUMS, a Sigstore keyless signature over the checksums and a generated SPDX SBOM.
Documentation site¶
The site is MkDocs Material with docs/ as the source directory:
python3 -m pip install mkdocs-material
mkdocs serve # http://127.0.0.1:8000
mkdocs build # static site in site/
Navigation is in mkdocs.yml; project-level files (roadmap, changelog, contributing, security)
are linked to GitHub because they live outside docs/.
Troubleshooting¶
libllhttp.so.9.2: cannot open shared object file
The SDK's lib directory is not on the runtime path. Export it:
export LD_LIBRARY_PATH="$UVCPP_ROOT/lib:$LD_LIBRARY_PATH"
The installed uvscope binary uses $ORIGIN/../lib/uvscope, so packages do not need this.
HTTPS handshake fails
The CA bundle is not reachable, or the target presents a certificate that does not validate. Set
UVSCOPE_CA_FILE=/path/to/cacert.pem or SSL_CERT_FILE.
Frontend is a 503 page
web/dist/index.html was not built before install. Run npm --prefix web run build and
reinstall, or pass --web-root web/dist.