Files
DarkRoom/tools/fetch-bundled-runtimes.sh
T
dtourolle cb97ebe7ac Ship the OpenVINO and WebGPU runtimes in every desktop package
The Windows installer and the Flatpak carried no ONNX Runtime, so they
ran every model on tract's one core; the Arch package left it to an
optional dependency. Each now installs two builds under runtimes/ —
Intel's OpenVINO build and the generic WebGPU one, both with the CPU
provider — fetched by tools/fetch-bundled-runtimes.sh from PyPI wheels
pinned by SHA-256, pruned to the native libraries (81 + 31 MB on Linux,
67 + 42 MB on Windows), licence texts beside them.

darkroom-desktop searches runtimes/openvino and runtimes/webgpu under
each place a package installs to; the engine opens all it finds and
keeps the one that fits the GPU, so a CUDA or ROCm runtime installed
beside them still wins on its vendor's card. On Windows the chosen
runtime's directory goes on PATH, because Intel's build leaves OpenVINO's
DLLs for the loader to find there.

The Windows image gains unzip; the installer smoke test checks both
runtimes landed.
2026-10-04 21:00:15 -04:00

133 lines
6.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Fetch the two ONNX Runtime builds a desktop package ships
# (docs/dev/inference.md §3.2), each into its own directory:
#
# DEST/openvino Intel's build: the OpenVINO rung on an Intel GPU
# DEST/webgpu Microsoft's WebGPU build: the generic rung on any other
#
# ./tools/fetch-bundled-runtimes.sh {linux|windows} DEST
#
# Only one runtime loads per process; the app opens every one it finds and
# keeps the one that fits the device's GPU (`dr_inference_engine::api`).
# Both carry ONNX Runtime's CPU provider, which is the floor either way.
# A CUDA or ROCm runtime is never bundled (§3.1) — the user's own, found
# beside these, outranks both on its vendor's GPU.
#
# The wheels are PyPI's, pinned by SHA-256: the option names the engine
# sets were read from these versions' source (CLAUDE.md, "Providers").
# Only the native libraries are kept — not the Python bindings, not
# OpenVINO's CPU plugin (ONNX Runtime's CPU provider is the floor), not
# the duplicate versioned copies a wheel holds as files.
#
# Licences: ONNX Runtime MIT, OpenVINO Apache-2.0, oneTBB Apache-2.0, the
# DirectX shader compiler (Windows WebGPU) LLVM/MIT; the texts go beside
# the libraries.
set -euo pipefail
PLATFORM="${1:?usage: fetch-bundled-runtimes.sh linux|windows DEST}"
DEST="${2:?usage: fetch-bundled-runtimes.sh linux|windows DEST}"
PYPI="https://files.pythonhosted.org/packages"
case "${PLATFORM}" in
linux)
ORT_OPENVINO="${PYPI}/08/07/f225999919f56506b603aaa3ff837ad563ab26f86906ed7fa7e5abcd849e/onnxruntime_openvino-1.24.1-cp313-cp313-manylinux_2_28_x86_64.whl"
ORT_OPENVINO_SHA=2c3bb73e68ac27f4891af8a595c1faf574ec68b772e6583c90a0b997a1822782
ORT_WEBGPU="${PYPI}/7a/4e/782b2457b863e1748866b82d918323e61c2d0108a01906a278e7a86a3a55/onnxruntime_webgpu-1.27.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl"
ORT_WEBGPU_SHA=3eb30b487d2b428d2e5c1ac538177ab6336cce9b204197135dc5a16753b0258e
# The Linux wheel carries OpenVINO itself, under the names the provider
# was linked against.
OPENVINO_KEEP=(libonnxruntime.so.1.24.1 libonnxruntime_providers_shared.so
libonnxruntime_providers_openvino.so libopenvino.so.2541
libopenvino_onnx_frontend.so.2541 libopenvino_intel_gpu_plugin.so
libtbb.so.12 libtbbmalloc.so)
WEBGPU_KEEP=(libonnxruntime.so.1.27.0 libonnxruntime_providers_shared.so)
;;
windows)
ORT_OPENVINO="${PYPI}/3e/92/46ae2cd565961a89189900f385bb2f13a9fa731ea4674001d23720fbb1e0/onnxruntime_openvino-1.24.1-cp313-cp313-win_amd64.whl"
ORT_OPENVINO_SHA=434bf49aa71393c577a456c9d76c98e6d6958a833fa0876793e3d5437b5a511a
ORT_WEBGPU="${PYPI}/dd/f3/6294f9617e97035771593d604729a420a848150054cc1c422a47a4915412/onnxruntime_webgpu-1.27.0-cp313-cp313-win_amd64.whl"
ORT_WEBGPU_SHA=c45377099fcf23ae87427eb52e2b1d35415cabb4e3419dc645f9ee08f730e9aa
# The Windows wheel leaves OpenVINO to the `openvino` wheel; its DLLs
# go in the same directory, which the engine puts on the DLL search
# path when it chooses this runtime.
OPENVINO_LIBS="${PYPI}/3c/e5/da52a86cc5f1c86871002712429cdcca0c0dbff12dfbce730b05db60340b/openvino-2025.4.1-20426-cp313-cp313-win_amd64.whl"
OPENVINO_LIBS_SHA=a28eef35e3ed497c3238eb8f3d1ee90647c449707a8b0a7630758cd15555d8dd
OPENVINO_KEEP=(onnxruntime.dll onnxruntime_providers_shared.dll
onnxruntime_providers_openvino.dll openvino.dll
openvino_onnx_frontend.dll openvino_intel_gpu_plugin.dll
tbb12.dll tbbmalloc.dll)
WEBGPU_KEEP=(onnxruntime.dll onnxruntime_providers_shared.dll dxcompiler.dll dxil.dll)
;;
*)
echo "error: platform is linux or windows, not ${PLATFORM}" >&2
exit 2
;;
esac
WORK="$(mktemp -d)"
trap 'rm -rf "${WORK}"' EXIT
# fetch URL SHA256 DIR: download a wheel, check it, unpack it into DIR.
fetch() {
local url="$1" sha="$2" dir="$3" whl
whl="${WORK}/$(basename "${url}")"
echo "==> $(basename "${url}")"
curl -fsSL -o "${whl}" "${url}"
echo "${sha} ${whl}" | sha256sum -c --quiet - || {
echo "error: $(basename "${url}") does not match its pinned SHA-256" >&2
exit 1
}
mkdir -p "${dir}"
unzip -q -o "${whl}" -d "${dir}"
}
# keep FROM TO NAMES...: copy only NAMES, every one of which must exist.
keep() {
local from="$1" to="$2" name
shift 2
mkdir -p "${to}"
for name in "$@"; do
local src
src="$(find "${from}" -name "${name}" -type f | head -1)"
[[ -n "${src}" ]] || {
echo "error: ${name} is not in the wheel" >&2
exit 1
}
install -m755 "${src}" "${to}/${name}"
done
}
fetch "${ORT_OPENVINO}" "${ORT_OPENVINO_SHA}" "${WORK}/openvino"
if [[ -n "${OPENVINO_LIBS:-}" ]]; then
fetch "${OPENVINO_LIBS}" "${OPENVINO_LIBS_SHA}" "${WORK}/openvino"
fi
fetch "${ORT_WEBGPU}" "${ORT_WEBGPU_SHA}" "${WORK}/webgpu"
rm -rf "${DEST}/openvino" "${DEST}/webgpu"
keep "${WORK}/openvino" "${DEST}/openvino" "${OPENVINO_KEEP[@]}"
keep "${WORK}/webgpu" "${DEST}/webgpu" "${WEBGPU_KEEP[@]}"
# The wheels' own licence and notice files — ONNX Runtime keeps its in the
# package directory, OpenVINO in `dist-info` — beside what they cover,
# each under the name of the directory it came from: two wheels unpacked
# into one directory both carry a `LICENSE`.
for rt in openvino webgpu; do
find "${WORK}/${rt}" -maxdepth 3 -type f \
\( -iname 'LICENSE*' -o -iname 'NOTICE*' -o -iname 'ThirdPartyNotices*' \) |
while IFS= read -r f; do
wheel="$(basename "$(dirname "${f}")" .dist-info)"
[[ "${wheel}" == licenses ]] && wheel="$(basename "$(dirname "$(dirname "${f}")")" .dist-info)"
install -m644 "${f}" "${DEST}/${rt}/${wheel}.$(basename "${f}")"
done
done
# The Linux wheel bundles OpenVINO without its licence; Apache-2.0 asks
# for the text beside the binaries. From the tag the libraries were built at.
if [[ "${PLATFORM}" == linux ]]; then
curl -fsSL -o "${DEST}/openvino/openvino-2025.4.1.LICENSE" \
"https://raw.githubusercontent.com/openvinotoolkit/openvino/2025.4.1/LICENSE"
echo "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4 ${DEST}/openvino/openvino-2025.4.1.LICENSE" |
sha256sum -c --quiet -
fi
du -sh "${DEST}/openvino" "${DEST}/webgpu"