Compare commits

...

34 Commits

Author SHA1 Message Date
Adeeb Shihadeh
cf61c10458 xvfb: probe host DRI paths so GLX is advertised on non-EL distros (#78)
Some checks failed
ci / build (linux-x86_64) (push) Failing after 4s
ci / build (macos) (push) Failing after 42s
ci / build (linux-arm64) (push) Has been cancelled
ci / test distro (archlinux:latest) (push) Has been cancelled
ci / test distro (debian:bookworm-slim) (push) Has been cancelled
ci / test distro (fedora:41) (push) Has been cancelled
ci / test distro (ghcr.io/void-linux/void-glibc:latest) (push) Has been cancelled
ci / test distro (opensuse/tumbleweed:latest) (push) Has been cancelled
ci / test distro (ubuntu:20.04) (push) Has been cancelled
ci / test distro (ubuntu:24.04) (push) Has been cancelled
ci / publish wheels (push) Has been cancelled
Xvfb's bundled libGLdispatch is hardcoded to look for DRI drivers under
/usr/lib64/dri (the AlmaLinux 8 layout). On Debian/Ubuntu they live in
/usr/lib/x86_64-linux-gnu/dri, so the GL provider fails to load and the
server brings up without the GLX extension — which silently breaks any
GLX client (raylib/GLFW). Set LIBGL_DRIVERS_PATH from the wrapper to a
list of standard distro paths so the host's swrast driver is found.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 19:05:56 -07:00
Adeeb Shihadeh
975313a86f add xvfb package (#77) 2026-04-30 17:55:32 -07:00
Adeeb Shihadeh
19a9ed13c0 add acados package (#76) 2026-04-30 16:18:27 -07:00
Adeeb Shihadeh
f9dd627e57 support pure wheels in shim packages (#75) 2026-04-25 13:35:28 -07:00
Adeeb Shihadeh
058ed3c076 add catch2 package (#74) 2026-04-25 13:11:59 -07:00
Adeeb Shihadeh
9f9bc38a3e rm mdbook 2026-04-15 14:22:07 -07:00
Adeeb Shihadeh
79fefe6558 add mdbook package (#71) 2026-04-14 16:10:03 -07:00
Adeeb Shihadeh
2f5b981c19 fix git link: use CURL_LIBCURL for static deps (#66) 2026-03-24 11:20:08 -07:00
Adeeb Shihadeh
54dafe6c1b add git package (#63) 2026-03-23 18:13:19 -07:00
Adeeb Shihadeh
0fc2d13e50 ffmpeg: disable x86asm (nasm not needed for hw accel)
HW accel codecs bypass the CPU entirely — SIMD-optimized software
paths are irrelevant. Dropping x86asm removes ffmpeg's build-time
nasm dependency. nasm stays in setup.sh for x264 and libjpeg.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:13:05 -07:00
Adeeb Shihadeh
567fde8231 Revert "add shared library dependency check to distro tests"
This reverts commit d1af35e660.
2026-03-22 16:12:47 -07:00
Adeeb Shihadeh
d1af35e660 add shared library dependency check to distro tests
After installing wheels in clean containers, ldd all binaries and
.so files. Fails if any dependency is "not found", catching leaked
build-host deps that would break on end-user systems.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:40:40 -07:00
Adeeb Shihadeh
5457e99bb7 ffmpeg: add hardware-accelerated video decoders (#62) 2026-03-22 14:28:34 -07:00
Adeeb Shihadeh
0f28906d50 fix shim release 2026-03-21 10:53:26 -07:00
Adeeb Shihadeh
8b6c712f60 fix imgui 2026-03-21 10:39:33 -07:00
Adeeb Shihadeh
6ad06e2173 qt is always a mistake :( 2026-03-21 10:27:17 -07:00
Adeeb Shihadeh
577b731299 imgui: build static lib 2026-03-21 10:11:22 -07:00
Adeeb Shihadeh
6692e3d936 imgui: add libGL 2026-03-21 09:56:26 -07:00
Adeeb Shihadeh
6bc1fe9a9a split shim releases into per-package branches (#59) 2026-03-14 14:42:00 -07:00
Adeeb Shihadeh
14d916d054 Add libusb package (#56) 2026-03-14 14:06:40 -07:00
Adeeb Shihadeh
62afc9ea71 qt5: minimize build and wheel size (#57) 2026-03-14 14:04:16 -07:00
Adeeb Shihadeh
c55046f7f0 add qt5 package (#55)
Qt 5.15.18-lts-lgpl (QtBase + QtCharts) built from source as shared
libraries. Provides headers, shared libs, and tools (moc, rcc, uic)
for building cabana in openpilot without system Qt5 packages.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 21:43:06 -07:00
Adeeb Shihadeh
a78417ecd1 imgui: enable Wayland support in GLFW build (#54) 2026-03-13 16:57:56 -07:00
Adeeb Shihadeh
d14d45aef4 imgui: add statically linked GLFW 3.4 build (#53) 2026-03-13 16:47:36 -07:00
Adeeb Shihadeh
224cbbb783 imgui: add GLFW backend files (#52) 2026-03-13 15:23:30 -07:00
Adeeb Shihadeh
53271a60fa rm python3-dev (#51) 2026-03-13 13:49:24 -07:00
Adeeb Shihadeh
8d9b59b9d0 add nanosvg package (#50) 2026-03-13 13:40:12 -07:00
Adeeb Shihadeh
950d288e77 rm openssl3 package 2026-03-06 22:03:30 -08:00
Adeeb Shihadeh
331d94a683 Make builds incremental by preserving source/build dirs (#45) 2026-03-04 09:17:55 -08:00
Adeeb Shihadeh
2e9aed768a imgui: add OpenGL3 backend files (#43)
Include imgui_impl_opengl3.h, imgui_impl_opengl3.cpp, and
imgui_impl_opengl3_loader.h from the imgui backends/ directory.
These are needed for cabana's Qt/OpenGL-based ImGui integration.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:00:28 -08:00
Adeeb Shihadeh
65674ad817 add imgui package (#42) 2026-03-01 16:40:46 -08:00
Adeeb Shihadeh
61379f09ec shim: retry downloads on transient network errors (#41) 2026-03-01 16:26:21 -08:00
Adeeb Shihadeh
21bb9ab18e raylib: fix setup.py to also trigger offscreen variant build
setup.py had its own cache check that only looked for libraylib.a,
skipping build.sh entirely when the cache had the desktop variant.
Now also checks for libraylib_offscreen.a on x86_64.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:15:59 -08:00
Adeeb Shihadeh
2341b89849 raylib: fix idempotency check to include offscreen variant
The build cache had desktop-only libraylib.a, causing build.sh to skip
the offscreen variant entirely. Now requires libraylib_offscreen.a on
x86_64 before considering the build complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:07:25 -08:00
70 changed files with 1626 additions and 499 deletions

View File

@@ -23,13 +23,15 @@ jobs:
- uses: actions/checkout@v6 - uses: actions/checkout@v6
- uses: actions/cache@v4 - uses: actions/cache@v4
with: with:
key: build-cache-v1-${{ matrix.platform }}-${{ hashFiles('build.sh', 'setup.sh', '*/pyproject.toml', '*/setup.py', '*/build.sh') }} key: build-cache-v2-${{ matrix.platform }}-${{ hashFiles('build.sh', 'setup.sh', '*/pyproject.toml', '*/setup.py', '*/build.sh') }}
restore-keys: build-cache-v1-${{ matrix.platform }}- restore-keys: build-cache-v2-${{ matrix.platform }}-
path: | path: |
.uv-cache .uv-cache
*/*/install */*/install
*/*/toolchain */*/toolchain
*/*/bin */*/bin
*/*-src
*/build
- name: Build wheels - name: Build wheels
env: env:
MANYLINUX: ${{ runner.os == 'Linux' && '1' || '0' }} MANYLINUX: ${{ runner.os == 'Linux' && '1' || '0' }}
@@ -90,8 +92,8 @@ jobs:
path: dist path: dist
- uses: actions/cache/restore@v4 - uses: actions/cache/restore@v4
with: with:
key: build-cache-v1-${{ matrix.platform }}-${{ hashFiles('build.sh', 'setup.sh', '*/pyproject.toml', '*/setup.py', '*/build.sh') }} key: build-cache-v2-${{ matrix.platform }}-${{ hashFiles('build.sh', 'setup.sh', '*/pyproject.toml', '*/setup.py', '*/build.sh') }}
restore-keys: build-cache-v1-${{ matrix.platform }}- restore-keys: build-cache-v2-${{ matrix.platform }}-
path: | path: |
.uv-cache .uv-cache
*/*/install */*/install

10
.gitignore vendored
View File

@@ -2,6 +2,7 @@
repo/ repo/
.venv/ .venv/
__pycache__/ __pycache__/
uv.lock
# agents # agents
.claude/ .claude/
@@ -26,3 +27,12 @@ gcc-arm-none-eabi/gcc_arm_none_eabi/toolchain/
# downloaded git-lfs # downloaded git-lfs
git-lfs/git_lfs/bin/ git-lfs/git_lfs/bin/
# downloaded mdbook
mdbook/mdbook/bin/
# vendored at build time
acados/acados/acados_template/
acados/casadi/
acados/casadi-venv/
acados/casadi-wheel/

View File

@@ -42,9 +42,9 @@ contributions welcome for other platforms!
```python ```python
dependencies = [ dependencies = [
# use the releases branch for pre-built wheels # use per-package release branches for pre-built wheels
"capnproto @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=capnproto", "capnproto @ git+https://github.com/commaai/dependencies.git@release-capnproto#subdirectory=capnproto",
"ffmpeg @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=ffmpeg", "ffmpeg @ git+https://github.com/commaai/dependencies.git@release-ffmpeg#subdirectory=ffmpeg",
# use the master branch to build the package on pip install # use the master branch to build the package on pip install
"capnproto @ git+https://github.com/commaai/dependencies.git@master#subdirectory=capnproto", "capnproto @ git+https://github.com/commaai/dependencies.git@master#subdirectory=capnproto",
@@ -58,4 +58,4 @@ to add a new package:
* start a new top-level directory as a new package * start a new top-level directory as a new package
* `./test.sh` tests the building of all packages * `./test.sh` tests the building of all packages
* on pushes to `master`, wheels are built for our target platforms and pushed to a GitHub release * on pushes to `master`, wheels are built for our target platforms and pushed to a GitHub release
* the `releases` branch contains shim packages that allow pointing to a git branch and always getting the appropriate wheel for your platform * each `release-<package>` branch contains a single shim package, so old lockfiles keep resolving even as new packages are added

View File

@@ -1,8 +1,10 @@
"""Shim setup.py: downloads pre-built wheels from GitHub Releases at install time.""" """Shim setup.py: downloads pre-built wheels from GitHub Releases at install time."""
import os import os
import platform import platform
import time
import zipfile import zipfile
from io import BytesIO from io import BytesIO
from urllib.error import URLError
from urllib.request import urlopen from urllib.request import urlopen
try: try:
@@ -23,6 +25,17 @@ DATADIR = _cfg["tool"]["shim"]["datadir"]
VERSION = _cfg["project"]["version"] VERSION = _cfg["project"]["version"]
MODULE = _cfg["project"]["name"].replace("-", "_") MODULE = _cfg["project"]["name"].replace("-", "_")
# all top-level packages bundled in this wheel (e.g. acados + casadi).
# `packages` may be a flat list or a dict with find.include patterns.
_pkgs = _cfg.get("tool", {}).get("setuptools", {}).get("packages", [f"{MODULE}*"])
if isinstance(_pkgs, list):
_INCLUDE = _pkgs
elif isinstance(_pkgs, dict):
_INCLUDE = _pkgs.get("find", {}).get("include", [f"{MODULE}*"])
else:
_INCLUDE = [f"{MODULE}*"]
TOP_PACKAGES = sorted({p.rstrip("*").rstrip("/") for p in _INCLUDE if p.rstrip("*").rstrip("/")})
PLATFORM_MAP = { PLATFORM_MAP = {
("Linux", "x86_64"): "linux_x86_64", ("Linux", "x86_64"): "linux_x86_64",
("Linux", "aarch64"): "linux_aarch64", ("Linux", "aarch64"): "linux_aarch64",
@@ -41,50 +54,52 @@ class InstallPrebuilt(build_py):
if plat is None: if plat is None:
raise RuntimeError(f"unsupported platform: {key}") raise RuntimeError(f"unsupported platform: {key}")
whl_name = f"{MODULE}-{VERSION}-py3-none-{plat}.whl" whl_names = [
url = f"{REPO_URL}/releases/download/{TAG}/{whl_name}" f"{MODULE}-{VERSION}-py3-none-{plat}.whl",
f"{MODULE}-{VERSION}-py3-none-any.whl",
]
print(f"Downloading {url} ...") raw = None
raw = urlopen(url).read() for whl_name in whl_names:
url = f"{REPO_URL}/releases/download/{TAG}/{whl_name}"
print(f"Downloading {url} ...")
for attempt in range(3):
try:
raw = urlopen(url, timeout=60).read()
break
except (URLError, OSError) as e:
if attempt == 2:
if whl_name == whl_names[-1]:
raise
break
wait = 2 ** attempt
print(f"Download failed ({e}), retrying in {wait}s ...")
time.sleep(wait)
if raw is not None:
break
print(f"Extracting {DATADIR} ...") print("Extracting wheel ...")
with zipfile.ZipFile(BytesIO(raw)) as zf: with zipfile.ZipFile(BytesIO(raw)) as zf:
prefix = f"{MODULE}/{DATADIR}/" purelib_data = f"{MODULE}-{VERSION}.data/purelib/"
alt_prefix = f"{MODULE}-{VERSION}.data/purelib/{MODULE}/{DATADIR}/"
for info in zf.infolist(): for info in zf.infolist():
for p in (prefix, alt_prefix): if info.is_dir():
if info.filename.startswith(p):
rel = info.filename[len(p):]
if not rel:
continue
dest = os.path.join(data_dir, rel)
if info.is_dir():
os.makedirs(dest, exist_ok=True)
else:
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(dest, "wb") as f:
f.write(zf.read(info))
if info.external_attr >> 16 & 0o111:
os.chmod(dest, 0o755)
break
# Also extract compiled extension modules (.so)
ext_prefix = f"{MODULE}/"
ext_alt_prefix = f"{MODULE}-{VERSION}.data/purelib/{MODULE}/"
for info in zf.infolist():
if not info.filename.endswith('.so'):
continue continue
for p in (ext_prefix, ext_alt_prefix): name = info.filename
if info.filename.startswith(p): if name.startswith(purelib_data):
rel = info.filename[len(p):] rel = name[len(purelib_data):]
if rel and '/' not in rel: else:
dest = os.path.join(module_dir, rel) rel = name
os.makedirs(os.path.dirname(dest), exist_ok=True) if "/" not in rel:
with open(dest, "wb") as f: continue
f.write(zf.read(info)) top = rel.split("/", 1)[0]
if info.external_attr >> 16 & 0o111: if top not in TOP_PACKAGES:
os.chmod(dest, 0o755) continue
break dest = os.path.join(_HERE, rel)
os.makedirs(os.path.dirname(dest), exist_ok=True)
with open(dest, "wb") as f:
f.write(zf.read(info))
if info.external_attr >> 16 & 0o111:
os.chmod(dest, 0o755)
super().run() super().run()

48
acados/acados/__init__.py Normal file
View File

@@ -0,0 +1,48 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
LIB_DIR = os.path.join(DIR, "lib")
BIN_DIR = os.path.join(DIR, "bin")
TERA_PATH = os.path.join(BIN_DIR, "t_renderer")
TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), "acados_template")
def smoketest():
import sys
lib_ext = ".dylib" if sys.platform == "darwin" else ".so"
for lib in ("libacados", "libblasfeo", "libhpipm", "libqpOASES_e"):
path = os.path.join(LIB_DIR, lib + lib_ext)
assert os.path.isfile(path), f"missing lib: {path}"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "acados_c", "ocp_nlp_interface.h"))
assert os.path.isfile(os.path.join(INCLUDE_DIR, "blasfeo", "include", "blasfeo.h"))
assert os.path.isfile(os.path.join(INCLUDE_DIR, "hpipm", "include", "hpipm_common.h"))
assert os.path.isfile(TERA_PATH) and os.access(TERA_PATH, os.X_OK), f"t_renderer missing/not executable: {TERA_PATH}"
assert os.path.isfile(os.path.join(TEMPLATE_DIR, "__init__.py"))
assert os.path.isfile(os.path.join(TEMPLATE_DIR, "acados_layout.json"))
assert os.path.isdir(os.path.join(TEMPLATE_DIR, "c_templates_tera"))
# the vendored slim casadi shipped in this wheel is built against cpython 3.12
# and pulls in numpy; only exercise it when both are available (real consumers
# like openpilot install via the shim, which declares numpy as a dep).
try:
import numpy # noqa: F401
except ImportError:
return
if sys.version_info[:2] != (3, 12):
return
from casadi import SX, MX, DM, Function, CasadiMeta, vertcat, jacobian, sin, cos, n_nodes # noqa: F401
x = SX.sym("x")
y = SX.sym("y")
expr = vertcat(sin(x), cos(y))
J = jacobian(expr, vertcat(x, y))
assert J.shape == (2, 2)
assert n_nodes(J) > 0
assert isinstance(CasadiMeta.version(), str)

139
acados/build.sh Executable file
View File

@@ -0,0 +1,139 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
# v0.2.2
VERSION="8af9b0ad180940ef611884574a0b27a43504311d"
INSTALL_DIR="$DIR/acados/install"
TEMPLATE_DIR="$DIR/acados/acados_template"
CASADI_DIR="$DIR/casadi"
CASADI_VERSION="3.6.7"
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# pick BLAS target per host arch
ARCH="$(uname -m)"
if [[ "$OSTYPE" == "darwin"* ]]; then
# this BLASFEO version doesn't have an Apple Silicon target; Cortex-A57
# baseline ARMv8 SIMD compiles and runs fine on M1+.
BLAS_TARGET="ARMV8A_ARM_CORTEX_A57"
elif [[ "$ARCH" == "aarch64" ]]; then
# Cortex-A57 = TICI baseline; safe for any modern aarch64
BLAS_TARGET="ARMV8A_ARM_CORTEX_A57"
else
BLAS_TARGET="X64_AUTOMATIC"
fi
ACADOS_FLAGS=(
-DACADOS_WITH_QPOASES=ON
-UBLASFEO_TARGET
-DBLASFEO_TARGET="$BLAS_TARGET"
-DACADOS_INSTALL_DIR="$INSTALL_DIR"
# acados (and several of its submodules) still pin cmake_minimum_required <3.5;
# CMake 4 removed that compatibility, so re-enable it here.
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
# qpOASES + blasfeo both call malloc()/posix_memalign() without including
# <stdlib.h>. C99/C2x and modern gcc/clang reject implicit declarations as
# errors. qpOASES also has a real Constraints*/Constraints** pointer bug
# that gcc 14+ now flags as an error too. Downgrade both so the upstream
# (pinned) sources keep compiling.
"-DCMAKE_C_FLAGS=-Wno-implicit-function-declaration -Wno-incompatible-pointer-types"
)
if [[ "$OSTYPE" == "darwin"* ]]; then
ACADOS_FLAGS+=(
-DCMAKE_OSX_ARCHITECTURES=arm64
-DCMAKE_MACOSX_RPATH=1
)
fi
# clone/update source
if [ ! -d "acados-src/.git" ]; then
rm -rf acados-src
git clone https://github.com/acados/acados.git acados-src
fi
git -C acados-src fetch --all --tags
git -C acados-src checkout --force "$VERSION"
git -C acados-src submodule update --init --recursive --depth=1
# build acados
mkdir -p build
cd build
cmake "${ACADOS_FLAGS[@]}" "$DIR/acados-src"
make -j"$NJOBS" install
cd "$DIR"
# we don't ship sample json templates
rm -f "$INSTALL_DIR"/lib/*.json
# python interface package (acados_template)
rm -rf "$TEMPLATE_DIR"
cp -r acados-src/interfaces/acados_template/acados_template "$TEMPLATE_DIR"
# strip future_fstrings (avoids needing the compatibility package on py>=3.6).
# Cython chokes on the unknown encoding in .pyx/.pxd too, not just .py.
find "$TEMPLATE_DIR" -type f \( -name '*.py' -o -name '*.pyx' -o -name '*.pxd' \) \
-exec sed -i.bak '/future.fstrings/d' {} +
find "$TEMPLATE_DIR" -name '*.bak' -delete
# acados_template's gnsf/check_reformulation.py uses an absolute `from
# acados_template.utils import ...` that only worked when acados_template was
# itself a top-level package on the path. We ship it as `acados.acados_template`,
# so rewrite to the relative form the rest of gnsf already uses.
if [ -f "$TEMPLATE_DIR/gnsf/check_reformulation.py" ]; then
sed -i.bak 's/^from acados_template\.utils /from ..utils /' "$TEMPLATE_DIR/gnsf/check_reformulation.py"
rm -f "$TEMPLATE_DIR/gnsf/check_reformulation.py.bak"
fi
# build tera renderer (needs cargo)
if ! command -v cargo >/dev/null 2>&1; then
echo "installing rust toolchain (needed for tera_renderer)..."
curl -LsSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal
# shellcheck disable=SC1091
source "$HOME/.cargo/env"
fi
mkdir -p "$INSTALL_DIR/bin"
cd "$DIR/acados-src/interfaces/acados_template/tera_renderer/"
if [[ "$OSTYPE" == "darwin"* ]]; then
cargo build --release --target aarch64-apple-darwin
cp target/aarch64-apple-darwin/release/t_renderer "$INSTALL_DIR/bin/t_renderer"
else
cargo build --release
cp target/release/t_renderer "$INSTALL_DIR/bin/t_renderer"
fi
cd "$DIR"
# vendor a slim casadi: install the upstream wheel into a throwaway cp312 venv
# (uv resolves the right platform wheel automatically), then move the casadi/
# tree out and slim it.
echo "vendoring casadi $CASADI_VERSION ..."
rm -rf "$CASADI_DIR" casadi-venv
uv venv --python 3.12 --quiet casadi-venv
uv pip install --python casadi-venv/bin/python --no-deps --quiet "casadi==$CASADI_VERSION"
mv casadi-venv/lib/python3.12/site-packages/casadi "$CASADI_DIR"
rm -rf casadi-venv
# drop everything except the bits openpilot actually needs:
# - __init__.py, casadi.py, tools/ (Python wrapper)
# - _casadi.so (CPython extension; same name on linux+darwin)
# - libcasadi.{so,dylib}* (the C++ runtime that _casadi.so links to)
# openpilot only uses symbolic SX/MX/Function/jacobian etc., which live in
# libcasadi + _casadi. Solver plugins (conic_*, nlpsol_*, integrator_*, ...)
# and their third-party backends (ipopt, bonmin, hpipm, fatrop, ...) are
# loaded lazily via dlopen and never reached.
cd "$CASADI_DIR"
shopt -s extglob
# libc++.*.dylib only exists on darwin and is needed by _casadi.so via @rpath
rm -rf !(__init__.py|casadi.py|_casadi.so|tools|libcasadi.*|libc++.*)
shopt -u extglob
cd "$DIR"
rm -rf casadi-wheel
echo "Installed acados to $INSTALL_DIR"
du -sh "$INSTALL_DIR"
echo "Vendored casadi (slim) at $CASADI_DIR"
du -sh "$CASADI_DIR"

23
acados/pyproject.toml Normal file
View File

@@ -0,0 +1,23 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "acados"
version = "0.2.2"
description = "acados solvers + Python interface, with a slimmed casadi vendored alongside"
requires-python = ">=3.8"
dependencies = [
# the vendored casadi.py shim imports numpy at module load time
"numpy",
]
# `find` runs at setup() init time, before build.sh creates these dirs, so
# enumerate packages explicitly. acados.acados_template + casadi.tools are
# subpackages and ship via package-data.
[tool.setuptools]
packages = ["acados", "casadi"]
[tool.setuptools.package-data]
acados = ["install/**/*", "acados_template/**/*"]
casadi = ["**/*"]

68
acados/setup.py Normal file
View File

@@ -0,0 +1,68 @@
import os
import platform
import subprocess
from setuptools.command.build_py import build_py
# `casadi/` is generated by build.sh (vendored from the upstream wheel), but
# setuptools requires every declared package to have a directory + __init__.py
# *before* any command runs. Drop a stub if it isn't there yet — build.sh
# replaces it with the real slim casadi during build_py.
_HERE = os.path.dirname(os.path.abspath(__file__))
_casadi_init = os.path.join(_HERE, "casadi", "__init__.py")
if not os.path.exists(_casadi_init):
os.makedirs(os.path.dirname(_casadi_init), exist_ok=True)
open(_casadi_init, "w").close()
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
bdist_wheel = None
class BuildAcados(build_py):
"""Run build.sh to compile acados before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run()
cmdclass = {"build_py": BuildAcados}
if bdist_wheel is not None:
class PlatformWheel(bdist_wheel):
"""Produce a platform-specific, Python-version-agnostic wheel."""
def finalize_options(self):
super().finalize_options()
self.root_is_pure = False
def get_tag(self):
system = platform.system()
machine = platform.machine()
if system == "Linux":
plat = f"linux_{machine}"
elif system == "Darwin":
plat = "macosx_11_0_arm64"
else:
plat = f"{system.lower()}_{machine}"
return "py3", "none", plat
cmdclass["bdist_wheel"] = PlatformWheel
def setup():
from setuptools import setup as _setup
_setup(cmdclass=cmdclass)
if __name__ == "__main__":
setup()

View File

@@ -34,6 +34,9 @@ fi
if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
export PATH="/opt/python/cp312-cp312/bin:$PATH" export PATH="/opt/python/cp312-cp312/bin:$PATH"
# cached *-src repos may be owned by the host runner user; tell git to trust them
git config --global --add safe.directory '*'
./setup.sh ./setup.sh
if [[ -z "${BUILD_SH_REUSE_MANYLINUX_ARTIFACTS:-}" ]]; then if [[ -z "${BUILD_SH_REUSE_MANYLINUX_ARTIFACTS:-}" ]]; then
@@ -45,10 +48,15 @@ if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
fi fi
fi fi
export CMAKE_C_COMPILER_LAUNCHER=ccache
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
echo "Building workspace packages into dist" echo "Building workspace packages into dist"
START_SECS=$SECONDS START_SECS=$SECONDS
uv build --all-packages --wheel --out-dir dist --no-create-gitignore --no-build-logs mkdir -p dist/
rm -rf dist/*
uv build --all-packages --wheel --out-dir dist --no-create-gitignore
if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
VENV_DIR="$ROOT_DIR/.venv-manylinux" VENV_DIR="$ROOT_DIR/.venv-manylinux"

View File

@@ -4,24 +4,19 @@ set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR" cd "$DIR"
VERSION="1.0.8" VERSION="bzip2-1.0.8"
INSTALL_DIR="$DIR/bzip2/install" INSTALL_DIR="$DIR/bzip2/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libbz2.a" ]; then
echo "bzip2 already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
CC="ccache ${CC:-cc}"
# Download # Clone/update source
if [ ! -d "bzip2-src" ]; then if [ ! -d "bzip2-src/.git" ]; then
curl -L "https://sourceware.org/pub/bzip2/bzip2-${VERSION}.tar.gz" -o bzip2.tar.gz rm -rf bzip2-src
mkdir -p bzip2-src git clone --depth 1 https://gitlab.com/bzip2/bzip2.git bzip2-src
tar xzf bzip2.tar.gz -C bzip2-src --strip-components=1
rm bzip2.tar.gz
fi fi
git -C bzip2-src fetch --depth 1 origin "$VERSION"
git -C bzip2-src checkout --force FETCH_HEAD
# Build static library with -fPIC # Build static library with -fPIC
cd bzip2-src cd bzip2-src
@@ -38,8 +33,5 @@ cp bzip2-src/libbz2.a "$INSTALL_DIR/lib/"
# Headers # Headers
cp bzip2-src/bzlib.h "$INSTALL_DIR/include/" cp bzip2-src/bzlib.h "$INSTALL_DIR/include/"
# Clean up
rm -rf bzip2-src
echo "Installed bzip2 to $INSTALL_DIR" echo "Installed bzip2 to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildBzip2(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "bzip2", "install", "lib", "libbz2.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="1.0.1" VERSION="1.0.1"
INSTALL_DIR="$DIR/capnproto/install" INSTALL_DIR="$DIR/capnproto/install"
# Idempotent: skip if already built
if [ -x "$INSTALL_DIR/bin/capnp" ]; then
echo "capnproto already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Clone # Clone/update source
if [ ! -d "capnproto-src" ]; then if [ ! -d "capnproto-src/.git" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/capnproto/capnproto.git capnproto-src rm -rf capnproto-src
git clone --depth 1 https://github.com/capnproto/capnproto.git capnproto-src
fi fi
git -C capnproto-src fetch --depth 1 origin "v${VERSION}"
git -C capnproto-src checkout --force FETCH_HEAD
# Build # Build
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
@@ -64,8 +61,5 @@ for obj in filesystem.c++.o main.c++.o test-helpers.c++.o; do
ar d "$INSTALL_DIR/lib/libkj.a" "$obj" 2>/dev/null || true ar d "$INSTALL_DIR/lib/libkj.a" "$obj" 2>/dev/null || true
done done
# Clean up
rm -rf capnproto-src "$DIR/build"
echo "Installed capnproto to $INSTALL_DIR" echo "Installed capnproto to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildCapnproto(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "capnproto", "install", "bin", "capnp") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

22
catch2/build.sh Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
VERSION="v2.13.10"
INSTALL_DIR="$DIR/catch2/install"
if [ ! -d "catch2-src/.git" ]; then
rm -rf catch2-src
git clone --depth 1 https://github.com/catchorg/Catch2.git catch2-src
fi
git -C catch2-src fetch --depth 1 origin "$VERSION"
git -C catch2-src checkout --force FETCH_HEAD
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/include"
cp -r catch2-src/single_include/catch2 "$INSTALL_DIR/include/"
echo "Installed catch2 to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

@@ -0,0 +1,9 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
LIB_DIR = DIR # header-only; no libraries
def smoketest():
assert os.path.isfile(os.path.join(INCLUDE_DIR, "catch2", "catch.hpp")), "catch2/catch.hpp not found"

16
catch2/pyproject.toml Normal file
View File

@@ -0,0 +1,16 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "catch2"
version = "2.13.10"
description = "Catch2 C++ test framework headers"
requires-python = ">=3.8"
[tool.setuptools.packages.find]
include = ["catch2*"]
exclude = ["catch2-src*"]
[tool.setuptools.package-data]
catch2 = ["install/**/*"]

28
catch2/setup.py Normal file
View File

@@ -0,0 +1,28 @@
import os
import subprocess
from setuptools.command.build_py import build_py
class BuildCatch2(build_py):
"""Run build.sh to download Catch2 headers before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run()
cmdclass = {"build_py": BuildCatch2}
def setup():
from setuptools import setup as _setup
_setup(cmdclass=cmdclass)
if __name__ == "__main__":
setup()

View File

@@ -7,18 +7,16 @@ cd "$DIR"
VERSION="2.16.0" VERSION="2.16.0"
INSTALL_DIR="$DIR/cppcheck/install" INSTALL_DIR="$DIR/cppcheck/install"
# Idempotent: skip if already built
if [ -x "$INSTALL_DIR/cppcheck" ]; then
echo "cppcheck already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
CXX="ccache ${CXX:-c++}"
# Clone # Clone/update source
if [ ! -d "cppcheck-src" ]; then if [ ! -d "cppcheck-src/.git" ]; then
git clone --depth 1 --branch "$VERSION" https://github.com/danmar/cppcheck.git cppcheck-src rm -rf cppcheck-src
git clone --depth 1 https://github.com/danmar/cppcheck.git cppcheck-src
fi fi
git -C cppcheck-src fetch --depth 1 origin "$VERSION"
git -C cppcheck-src checkout --force FETCH_HEAD
# Build # Build
cd cppcheck-src cd cppcheck-src
@@ -35,8 +33,5 @@ cp -r cppcheck-src/cfg "$INSTALL_DIR/"
cp -r cppcheck-src/platforms "$INSTALL_DIR/" cp -r cppcheck-src/platforms "$INSTALL_DIR/"
strip "$INSTALL_DIR/cppcheck" 2>/dev/null || true strip "$INSTALL_DIR/cppcheck" 2>/dev/null || true
# Clean up
rm -rf cppcheck-src
echo "Installed cppcheck to $INSTALL_DIR" echo "Installed cppcheck to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildCppcheck(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "cppcheck", "install", "cppcheck") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -7,28 +7,19 @@ cd "$DIR"
VERSION="3.4.0" VERSION="3.4.0"
INSTALL_DIR="$DIR/eigen/install" INSTALL_DIR="$DIR/eigen/install"
# Idempotent: skip if already present # Clone/update source
if [ -d "$INSTALL_DIR/eigen3/Eigen" ]; then if [ ! -d "eigen-src/.git" ]; then
echo "eigen already present, skipping download." rm -rf eigen-src
exit 0 git clone --depth 1 https://gitlab.com/libeigen/eigen.git eigen-src
fi fi
git -C eigen-src fetch --depth 1 origin "$VERSION"
git -C eigen-src checkout --force FETCH_HEAD
TARBALL="eigen-${VERSION}.tar.gz" # Copy headers
URL="https://gitlab.com/libeigen/eigen/-/archive/${VERSION}/${TARBALL}"
echo "Downloading Eigen ${VERSION} ..."
curl -fSL -o "$TARBALL" "$URL"
echo "Extracting headers ..."
rm -rf "$INSTALL_DIR" rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/eigen3" mkdir -p "$INSTALL_DIR/eigen3"
cp -r eigen-src/Eigen "$INSTALL_DIR/eigen3/"
# Extract only the Eigen/ and unsupported/Eigen/ header directories cp -r eigen-src/unsupported "$INSTALL_DIR/eigen3/"
tar --strip-components=1 -xzf "$TARBALL" -C "$INSTALL_DIR/eigen3" \
"eigen-${VERSION}/Eigen" \
"eigen-${VERSION}/unsupported"
rm -f "$TARBALL"
echo "Installed eigen to $INSTALL_DIR" echo "Installed eigen to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildEigen(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "eigen", "install", "eigen3", "Eigen") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.isdir(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -4,24 +4,26 @@ set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR" cd "$DIR"
PLATFORM="$(uname -s)"
FFMPEG_VERSION="7.1" FFMPEG_VERSION="7.1"
ZLIB_VERSION="da607da739fa6047df13e66a2af6b8bec7c2a498" # v1.3.2
X264_BRANCH="stable"
LIBDRM_VERSION="libdrm-2.4.124"
LIBVA_VERSION="2.22.0"
INSTALL_DIR="$DIR/ffmpeg/install" INSTALL_DIR="$DIR/ffmpeg/install"
# Idempotent: skip if already built
if [ -x "$INSTALL_DIR/bin/ffmpeg" ]; then
echo "ffmpeg already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
CC="ccache ${CC:-cc}"
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
mkdir -p "$DIR/build" mkdir -p "$DIR/build"
# --- Build zlib (static) --- # --- Build zlib (static) ---
if [ ! -d "zlib-src" ]; then if [ ! -d "zlib-src/.git" ]; then
git clone https://github.com/madler/zlib.git zlib-src rm -rf zlib-src
git -C zlib-src checkout da607da739fa6047df13e66a2af6b8bec7c2a498 # pin to v1.3.2 git clone --depth 1 https://github.com/madler/zlib.git zlib-src
fi fi
git -C zlib-src fetch --depth 1 origin "$ZLIB_VERSION"
git -C zlib-src checkout --force "$ZLIB_VERSION"
cd zlib-src cd zlib-src
./configure --prefix="$PREFIX" --static ./configure --prefix="$PREFIX" --static
@@ -30,9 +32,12 @@ make install
cd "$DIR" cd "$DIR"
# --- Build x264 (static) --- # --- Build x264 (static) ---
if [ ! -d "x264-src" ]; then if [ ! -d "x264-src/.git" ]; then
git clone --depth 1 --branch stable https://code.videolan.org/videolan/x264.git x264-src rm -rf x264-src
git clone --depth 1 https://code.videolan.org/videolan/x264.git x264-src
fi fi
git -C x264-src fetch --depth 1 origin "$X264_BRANCH"
git -C x264-src checkout --force FETCH_HEAD
cd x264-src cd x264-src
CFLAGS="-fno-finite-math-only" ./configure \ CFLAGS="-fno-finite-math-only" ./configure \
@@ -46,14 +51,104 @@ make -j"$NJOBS"
make install make install
cd "$DIR" cd "$DIR"
# --- Build FFmpeg --- # --- Build nv-codec-headers (Linux only, for CUDA/NVDEC) ---
if [ ! -d "ffmpeg-src" ]; then if [ "$PLATFORM" = "Linux" ]; then
git clone --depth 1 --branch "n${FFMPEG_VERSION}" https://github.com/FFmpeg/FFmpeg.git ffmpeg-src if [ ! -d "nv-codec-headers-src/.git" ]; then
rm -rf nv-codec-headers-src
git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git nv-codec-headers-src
fi
make -C nv-codec-headers-src PREFIX="$PREFIX" install
fi fi
# --- Build Vulkan-Headers from source (Linux only, need >= 1.3.277 for FFmpeg 7.1) ---
if [ "$PLATFORM" = "Linux" ]; then
if [ ! -d "vulkan-headers-src/.git" ]; then
rm -rf vulkan-headers-src
git clone --depth 1 https://github.com/KhronosGroup/Vulkan-Headers.git vulkan-headers-src
fi
cmake -S vulkan-headers-src -B vulkan-headers-src/build -DCMAKE_INSTALL_PREFIX="$PREFIX" >/dev/null
cmake --install vulkan-headers-src/build >/dev/null
fi
# --- Build libdrm + libva statically (Linux only, for VAAPI without runtime deps) ---
if [ "$PLATFORM" = "Linux" ]; then
if ! command -v meson &>/dev/null; then
pip3 install --quiet meson ninja 2>/dev/null || python3 -m pip install --quiet meson ninja 2>/dev/null || true
command -v meson &>/dev/null || { echo "error: meson is required (apt install meson or pip install meson)" >&2; exit 1; }
fi
if [ ! -d "libdrm-src/.git" ]; then
rm -rf libdrm-src
git clone --depth 1 --branch "$LIBDRM_VERSION" https://gitlab.freedesktop.org/mesa/drm.git libdrm-src
fi
rm -rf libdrm-src/builddir
meson setup libdrm-src/builddir libdrm-src \
--prefix="$PREFIX" --libdir=lib --default-library=static \
-Dintel=disabled -Dradeon=disabled -Damdgpu=disabled -Dnouveau=disabled \
-Dvmwgfx=disabled -Dtests=false -Dman-pages=disabled -Dcairo-tests=disabled \
-Dvalgrind=disabled
ninja -C libdrm-src/builddir install
if [ ! -d "libva-src/.git" ]; then
rm -rf libva-src
git clone --depth 1 --branch "$LIBVA_VERSION" https://github.com/intel/libva.git libva-src
fi
rm -rf libva-src/builddir
# libva hardcodes shared_library(); patch to library() so --default-library=static works
sed -i 's/shared_library(/library(/g' libva-src/va/meson.build
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \
meson setup libva-src/builddir libva-src \
--prefix="$PREFIX" --libdir=lib --default-library=static \
-Ddisable_drm=false -Dwith_x11=no -Dwith_glx=no -Dwith_wayland=no \
-Dwith_win32=no -Denable_docs=false
ninja -C libva-src/builddir install
fi
# --- Build FFmpeg ---
if [ ! -d "ffmpeg-src/.git" ]; then
rm -rf ffmpeg-src
git clone --depth 1 https://github.com/FFmpeg/FFmpeg.git ffmpeg-src
fi
git -C ffmpeg-src fetch --depth 1 origin "n${FFMPEG_VERSION}"
git -C ffmpeg-src checkout --force FETCH_HEAD
cd ffmpeg-src cd ffmpeg-src
# Platform-specific hardware acceleration flags
HW_FLAGS=()
if [ "$PLATFORM" = "Linux" ]; then
HW_FLAGS+=(
# NVIDIA CUDA/NVDEC (uses dlopen at runtime)
--enable-ffnvcodec --enable-cuda --enable-cuvid --enable-nvdec
--enable-hwaccel=h264_nvdec,hevc_nvdec
--enable-decoder=h264_cuvid,hevc_cuvid
# VAAPI (Intel/AMD — libva linked statically, driver loaded via dlopen at runtime)
--enable-vaapi
--enable-hwaccel=h264_vaapi,hevc_vaapi
# V4L2 Memory-to-Memory (embedded: RPi, Qualcomm, Rockchip)
--enable-v4l2-m2m
--enable-decoder=h264_v4l2m2m,hevc_v4l2m2m
--enable-encoder=h264_v4l2m2m,hevc_v4l2m2m
# Vulkan video decode/encode (uses dlopen at runtime)
--enable-vulkan
--enable-hwaccel=h264_vulkan,hevc_vulkan
--enable-encoder=h264_vulkan,hevc_vulkan
)
elif [ "$PLATFORM" = "Darwin" ]; then
HW_FLAGS+=(
# VideoToolbox (Apple Silicon / macOS)
--enable-videotoolbox
--enable-hwaccel=h264_videotoolbox,hevc_videotoolbox
--enable-encoder=h264_videotoolbox,hevc_videotoolbox
)
fi
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \ PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \
./configure \ ./configure \
--cc="${CC:-cc}" \
--prefix="$PREFIX" \ --prefix="$PREFIX" \
--enable-gpl \ --enable-gpl \
--enable-static \ --enable-static \
@@ -64,6 +159,7 @@ PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \
--disable-doc \ --disable-doc \
--disable-ffplay \ --disable-ffplay \
--disable-autodetect \ --disable-autodetect \
--disable-x86asm \
--disable-everything \ --disable-everything \
--enable-encoder=libx264,aac,ffvhuff,rawvideo,png,mjpeg \ --enable-encoder=libx264,aac,ffvhuff,rawvideo,png,mjpeg \
--enable-decoder=h264,hevc,ffvhuff,aac,rawvideo,png,mjpeg,mp3,pcm_s16le \ --enable-decoder=h264,hevc,ffvhuff,aac,rawvideo,png,mjpeg,mp3,pcm_s16le \
@@ -74,7 +170,8 @@ PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \
--enable-filter=blend,vflip,format,scale,aformat,anull,aresample,null \ --enable-filter=blend,vflip,format,scale,aformat,anull,aresample,null \
--enable-bsf=extract_extradata,h264_mp4toannexb,hevc_mp4toannexb \ --enable-bsf=extract_extradata,h264_mp4toannexb,hevc_mp4toannexb \
--extra-cflags="-I$PREFIX/include" \ --extra-cflags="-I$PREFIX/include" \
--extra-ldflags="-L$PREFIX/lib" --extra-ldflags="-L$PREFIX/lib" \
"${HW_FLAGS[@]}"
make -j"$NJOBS" make -j"$NJOBS"
make install make install
cd "$DIR" cd "$DIR"
@@ -88,7 +185,11 @@ cp "$PREFIX/bin/ffmpeg" "$INSTALL_DIR/bin/"
cp "$PREFIX/bin/ffprobe" "$INSTALL_DIR/bin/" cp "$PREFIX/bin/ffprobe" "$INSTALL_DIR/bin/"
# Libraries # Libraries
for lib in libavformat.a libavcodec.a libavutil.a libswresample.a libx264.a libz.a; do LIBS="libavformat.a libavcodec.a libavutil.a libswresample.a libx264.a libz.a"
if [ "$PLATFORM" = "Linux" ]; then
LIBS="$LIBS libva.a libva-drm.a libdrm.a"
fi
for lib in $LIBS; do
cp "$PREFIX/lib/$lib" "$INSTALL_DIR/lib/" cp "$PREFIX/lib/$lib" "$INSTALL_DIR/lib/"
done done
@@ -100,8 +201,5 @@ done
# Strip binaries # Strip binaries
strip "$INSTALL_DIR/bin/ffmpeg" "$INSTALL_DIR/bin/ffprobe" 2>/dev/null || true strip "$INSTALL_DIR/bin/ffmpeg" "$INSTALL_DIR/bin/ffprobe" 2>/dev/null || true
# Clean up
rm -rf zlib-src x264-src ffmpeg-src "$DIR/build"
echo "Installed ffmpeg to $INSTALL_DIR" echo "Installed ffmpeg to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildFFmpeg(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "ffmpeg", "install", "bin", "ffmpeg") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -9,10 +9,11 @@ TOOLCHAIN_BASE="arm-gnu-toolchain-${TOOLCHAIN_VERSION}"
GCC_VERSION="13.2.1" GCC_VERSION="13.2.1"
INSTALL_DIR="$DIR/gcc_arm_none_eabi/toolchain" INSTALL_DIR="$DIR/gcc_arm_none_eabi/toolchain"
VERSION_FILE="$INSTALL_DIR/.version"
# Idempotent: skip if already built # Skip if already at correct version
if [ -x "$INSTALL_DIR/bin/arm-none-eabi-gcc" ]; then if [ -f "$VERSION_FILE" ] && [ "$(cat "$VERSION_FILE")" = "$TOOLCHAIN_VERSION" ]; then
echo "Toolchain already present, skipping download." echo "Toolchain $TOOLCHAIN_VERSION already present, skipping."
exit 0 exit 0
fi fi
@@ -112,6 +113,7 @@ find "$INSTALL_DIR" -type f \( -executable -o -name '*.so' \) -exec strip {} + 2
# --- clean up download artifacts --- # --- clean up download artifacts ---
rm -rf "$EXTRACT_DIR" rm -rf "$EXTRACT_DIR"
rm -f "$TARBALL" rm -f "$TARBALL"
echo "$TOOLCHAIN_VERSION" > "$VERSION_FILE"
echo "Installed to $INSTALL_DIR" echo "Installed to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -1,10 +1,8 @@
import os import os
import platform import platform
import subprocess import subprocess
import sys
from setuptools.command.build_py import build_py from setuptools.command.build_py import build_py
from setuptools.dist import Distribution
try: try:
from wheel.bdist_wheel import bdist_wheel from wheel.bdist_wheel import bdist_wheel
@@ -17,13 +15,8 @@ class BuildToolchain(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
toolchain_marker = os.path.join( build_script = os.path.join(pkg_dir, "build.sh")
pkg_dir, "gcc_arm_none_eabi", "toolchain", "bin", "arm-none-eabi-gcc" subprocess.check_call(["bash", build_script], cwd=pkg_dir)
)
if not os.path.exists(toolchain_marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -6,10 +6,11 @@ cd "$DIR"
VERSION="3.6.1" VERSION="3.6.1"
INSTALL_DIR="$DIR/git_lfs/bin" INSTALL_DIR="$DIR/git_lfs/bin"
VERSION_FILE="$INSTALL_DIR/.version"
# Idempotent: skip if already present # Skip if already at correct version
if [ -x "$INSTALL_DIR/git-lfs" ]; then if [ -f "$VERSION_FILE" ] && [ "$(cat "$VERSION_FILE")" = "$VERSION" ]; then
echo "git-lfs already present, skipping download." echo "git-lfs $VERSION already present, skipping."
exit 0 exit 0
fi fi
@@ -51,6 +52,7 @@ fi
chmod +x "$INSTALL_DIR/git-lfs" chmod +x "$INSTALL_DIR/git-lfs"
rm -f "$FILENAME" rm -f "$FILENAME"
echo "$VERSION" > "$VERSION_FILE"
echo "Installed git-lfs to $INSTALL_DIR" echo "Installed git-lfs to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildGitLfs(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "git_lfs", "bin", "git-lfs") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

189
git/build.sh Executable file
View File

@@ -0,0 +1,189 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
VERSION="2.47.1"
OPENSSL_VERSION="openssl-3.4.1"
CURL_VERSION="curl-8_12_1"
ZLIB_VERSION="v1.3.1"
INSTALL_DIR="$DIR/git/install"
VERSION_FILE="$INSTALL_DIR/.version"
# Skip if already at correct version
if [ -f "$VERSION_FILE" ] && [ "$(cat "$VERSION_FILE")" = "$VERSION" ]; then
echo "git $VERSION already present, skipping."
exit 0
fi
PLATFORM="$(uname -s)"
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
PREFIX="$DIR/build/prefix"
mkdir -p "$DIR/build"
# --- Build zlib (static) ---
if [ ! -d "zlib-src/.git" ]; then
rm -rf zlib-src
git clone --depth 1 https://github.com/madler/zlib.git zlib-src
fi
git -C zlib-src fetch --depth 1 origin "$ZLIB_VERSION"
git -C zlib-src checkout --force FETCH_HEAD
cd zlib-src
./configure --prefix="$PREFIX" --static
make -j"$NJOBS"
make install
cd "$DIR"
# --- Build OpenSSL (static) ---
if [ ! -d "openssl-src/.git" ]; then
rm -rf openssl-src
git clone --depth 1 https://github.com/openssl/openssl.git openssl-src
fi
git -C openssl-src fetch --depth 1 origin "$OPENSSL_VERSION"
git -C openssl-src checkout --force FETCH_HEAD
cd openssl-src
./Configure \
--prefix="$PREFIX" \
--libdir=lib \
no-shared \
no-tests \
no-docs
make -j"$NJOBS"
make install_sw
cd "$DIR"
# --- Build curl (static, with openssl+zlib) ---
if [ ! -d "curl-src/.git" ]; then
rm -rf curl-src
git clone --depth 1 https://github.com/curl/curl.git curl-src
fi
git -C curl-src fetch --depth 1 origin "$CURL_VERSION"
git -C curl-src checkout --force FETCH_HEAD
cd curl-src
autoreconf -fi
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig" \
./configure \
--prefix="$PREFIX" \
--with-openssl="$PREFIX" \
--with-zlib="$PREFIX" \
--disable-shared \
--enable-static \
--disable-ldap \
--disable-rtsp \
--disable-dict \
--disable-telnet \
--disable-tftp \
--disable-pop3 \
--disable-imap \
--disable-smb \
--disable-smtp \
--disable-gopher \
--disable-mqtt \
--disable-manual \
--disable-docs \
--without-libpsl \
--without-brotli \
--without-zstd \
--without-libidn2 \
--without-nghttp2 \
--without-librtmp
make -j"$NJOBS"
make install
cd "$DIR"
# --- Build git (with static curl+openssl+zlib) ---
if [ ! -d "git-src/.git" ]; then
rm -rf git-src
git clone --depth 1 https://github.com/git/git.git git-src
fi
git -C git-src fetch --depth 1 origin "v${VERSION}"
git -C git-src checkout --force FETCH_HEAD
# Gather static link flags for curl and openssl dependencies
# CURL_LIBCURL: used by git-remote-http, git-http-fetch, git-http-push
# LIB_4_CRYPTO: used by git-imap-send and other direct openssl consumers
# Both need transitive deps (-ldl, -lpthread) since we link statically
CRYPTO_DEPS="-lpthread"
CURL_EXTRA=""
if [ "$PLATFORM" = "Linux" ]; then
CRYPTO_DEPS="$CRYPTO_DEPS -ldl"
elif [ "$PLATFORM" = "Darwin" ]; then
CURL_EXTRA="-framework SystemConfiguration -framework Security -framework CoreFoundation"
fi
cd git-src
make prefix="$PREFIX" \
RUNTIME_PREFIX=YesPlease \
NO_GETTEXT=YesPlease \
NO_TCLTK=YesPlease \
NO_PERL=YesPlease \
NO_PYTHON=YesPlease \
NO_EXPAT=YesPlease \
INSTALL_SYMLINKS=1 \
CURLDIR="$PREFIX" \
CURL_LIBCURL="-L$PREFIX/lib -lcurl -lssl -lcrypto -lz $CRYPTO_DEPS $CURL_EXTRA" \
OPENSSL_LIBSSL="-L$PREFIX/lib -lssl" \
LIB_4_CRYPTO="-lcrypto $CRYPTO_DEPS" \
ZLIB_PATH="$PREFIX" \
-j"$NJOBS" \
all
make prefix="$PREFIX" \
RUNTIME_PREFIX=YesPlease \
NO_GETTEXT=YesPlease \
NO_TCLTK=YesPlease \
NO_PERL=YesPlease \
NO_PYTHON=YesPlease \
NO_EXPAT=YesPlease \
INSTALL_SYMLINKS=1 \
CURLDIR="$PREFIX" \
CURL_LIBCURL="-L$PREFIX/lib -lcurl -lssl -lcrypto -lz $CRYPTO_DEPS $CURL_EXTRA" \
OPENSSL_LIBSSL="-L$PREFIX/lib -lssl" \
LIB_4_CRYPTO="-lcrypto $CRYPTO_DEPS" \
ZLIB_PATH="$PREFIX" \
install
cd "$DIR"
# Assemble the package install directory
# Only copy real files from libexec to avoid bloating the wheel with
# copies of the main git binary (builtin commands are symlinks to git)
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/bin" "$INSTALL_DIR/libexec/git-core"
# Main binary
cp "$PREFIX/bin/git" "$INSTALL_DIR/bin/"
# libexec/git-core: copy real files, resolve non-git symlinks, skip git symlinks
cd "$PREFIX/libexec/git-core"
for f in *; do
if [ -L "$f" ]; then
target="$(readlink "$f")"
# Skip symlinks to the main git binary (these are builtins)
case "$target" in
git|../../bin/git) continue ;;
esac
# Resolve other symlinks (e.g., git-remote-https -> git-remote-http)
cp -L "$f" "$INSTALL_DIR/libexec/git-core/$f"
elif [ -f "$f" ]; then
cp "$f" "$INSTALL_DIR/libexec/git-core/$f"
fi
done
cd "$DIR"
# Copy git binary into libexec for builtin resolution
cp "$PREFIX/bin/git" "$INSTALL_DIR/libexec/git-core/git"
# Templates
cp -r "$PREFIX/share" "$INSTALL_DIR/"
# Strip binaries
strip "$INSTALL_DIR/bin/git" "$INSTALL_DIR/libexec/git-core/git" 2>/dev/null || true
find "$INSTALL_DIR/libexec/git-core" -maxdepth 1 -type f -perm /111 ! -name "*.sh" -exec strip {} \; 2>/dev/null || true
echo "$VERSION" > "$VERSION_FILE"
echo "Installed git to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

17
git/git/__init__.py Normal file
View File

@@ -0,0 +1,17 @@
import os
import sys
DIR = os.path.join(os.path.dirname(__file__), "install")
BIN_DIR = os.path.join(DIR, "bin")
def _run():
binary = os.path.join(BIN_DIR, "git")
os.execvp(binary, [binary] + sys.argv[1:])
def smoketest():
import subprocess
binary = os.path.join(BIN_DIR, "git")
subprocess.run([binary, "--version"], check=True)
subprocess.run([binary, "ls-remote", "https://github.com/commaai/openpilot.git", "HEAD"], check=True)

18
git/pyproject.toml Normal file
View File

@@ -0,0 +1,18 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "git"
version = "2.47.1"
description = "Git distributed version control system"
requires-python = ">=3.8"
[project.scripts]
git = "git:_run"
[tool.setuptools.packages.find]
include = ["git*"]
[tool.setuptools.package-data]
git = ["install/**/*"]

View File

@@ -10,21 +10,18 @@ except ImportError:
bdist_wheel = None bdist_wheel = None
class BuildOpenssl(build_py): class BuildGit(build_py):
"""Run build.sh to compile OpenSSL before collecting package data.""" """Run build.sh to build git before collecting package data."""
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "openssl3", "install", "lib", "libcrypto.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()
cmdclass = {"build_py": BuildOpenssl} cmdclass = {"build_py": BuildGit}
if bdist_wheel is not None: if bdist_wheel is not None:

124
imgui/build.sh Executable file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
INSTALL_DIR="$DIR/imgui/install"
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Dear ImGui (docking branch, version 1.92.7)
IMGUI_COMMIT="934c6a5f5ef2355d6df25395d555cb71f790c4e9"
# ImPlot
IMPLOT_COMMIT="93c801b4bb801c5c11031d880b6af1d1f70bd79d"
# GLFW 3.4
GLFW_COMMIT="7b6aead9fb88b3623e3b3725ebb42670cbe4c579"
# Clone/update imgui
if [ ! -d "imgui-src/.git" ]; then
rm -rf imgui-src
git clone --depth 1 https://github.com/ocornut/imgui.git imgui-src
fi
git -C imgui-src fetch --depth 1 origin "$IMGUI_COMMIT"
git -C imgui-src checkout --force "$IMGUI_COMMIT"
# Clone/update implot
if [ ! -d "implot-src/.git" ]; then
rm -rf implot-src
git clone --depth 1 https://github.com/epezent/implot.git implot-src
fi
git -C implot-src fetch --depth 1 origin "$IMPLOT_COMMIT"
git -C implot-src checkout --force "$IMPLOT_COMMIT"
# Clone/update GLFW
if [ ! -d "glfw-src/.git" ]; then
rm -rf glfw-src
git clone --depth 1 https://github.com/glfw/glfw.git glfw-src
fi
git -C glfw-src fetch --depth 1 origin "$GLFW_COMMIT"
git -C glfw-src checkout --force "$GLFW_COMMIT"
# Install GLFW build dependencies
if [[ "$(uname)" == "Linux" ]]; then
if command -v dnf &>/dev/null; then
dnf install -y libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel libXi-devel mesa-libGL-devel \
wayland-devel wayland-protocols-devel libxkbcommon-devel
elif command -v apt-get &>/dev/null; then
if [ "$(id -u)" -eq 0 ]; then
apt-get update && apt-get install -y libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev libgl-dev \
libwayland-dev wayland-protocols libxkbcommon-dev
else
sudo apt-get update && sudo apt-get install -y libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev libgl-dev \
libwayland-dev wayland-protocols libxkbcommon-dev
fi
fi
fi
# Build GLFW static library
cmake -B glfw-src/build -S glfw-src \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DGLFW_BUILD_EXAMPLES=OFF \
-DGLFW_BUILD_TESTS=OFF \
-DGLFW_BUILD_DOCS=OFF
cmake --build glfw-src/build --parallel "$NJOBS"
# Install headers
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/include" "$INSTALL_DIR/lib"
# imgui headers
cp imgui-src/imgui.h imgui-src/imgui_internal.h imgui-src/imconfig.h \
imgui-src/imstb_rectpack.h imgui-src/imstb_textedit.h imgui-src/imstb_truetype.h \
"$INSTALL_DIR/include/"
cp imgui-src/backends/imgui_impl_opengl3.h imgui-src/backends/imgui_impl_opengl3_loader.h \
imgui-src/backends/imgui_impl_glfw.h \
"$INSTALL_DIR/include/"
# implot headers
cp implot-src/implot.h implot-src/implot_internal.h "$INSTALL_DIR/include/"
# glfw
cp glfw-src/build/src/libglfw3.a "$INSTALL_DIR/lib/"
cp -r glfw-src/include/GLFW "$INSTALL_DIR/include/"
# Build libimgui.a (imgui core + backends + implot)
IMGUI_SRCS=(
imgui-src/imgui.cpp
imgui-src/imgui_draw.cpp
imgui-src/imgui_tables.cpp
imgui-src/imgui_widgets.cpp
imgui-src/imgui_demo.cpp
imgui-src/backends/imgui_impl_opengl3.cpp
imgui-src/backends/imgui_impl_glfw.cpp
implot-src/implot.cpp
implot-src/implot_items.cpp
)
OBJ_DIR="$(mktemp -d)"
for src in "${IMGUI_SRCS[@]}"; do
obj="$OBJ_DIR/$(basename "${src%.cpp}.o")"
c++ -c -O2 -fPIC -I"$INSTALL_DIR/include" "$src" -o "$obj" &
done
wait
ar rcs "$INSTALL_DIR/lib/libimgui.a" "$OBJ_DIR"/*.o
rm -rf "$OBJ_DIR"
# Bundle GLVND dispatchers so Linux users don't need system libGL
if [[ "$(uname)" == "Linux" ]]; then
MESA_DIR="$INSTALL_DIR/lib/mesa"
mkdir -p "$MESA_DIR"
ldconfig 2>/dev/null || true
for lib in libGL.so.1 libGLX.so.0 libEGL.so.1 libOpenGL.so.0 libGLdispatch.so.0; do
src="$(ldconfig -p 2>/dev/null | grep -F "$lib" | awk '{print $NF}' | head -1)"
if [ -n "$src" ] && [ -f "$src" ]; then
cp -L "$src" "$MESA_DIR/"
# Create unversioned symlink for the linker
base="${lib%%.so.*}"
ln -sf "$lib" "$MESA_DIR/${base}.so"
fi
done
fi
echo "Installed imgui to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

16
imgui/imgui/__init__.py Normal file
View File

@@ -0,0 +1,16 @@
import os
import platform as _platform
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
LIB_DIR = os.path.join(DIR, "lib")
MESA_DIR = os.path.join(DIR, "lib", "mesa")
def smoketest():
assert os.path.isfile(os.path.join(INCLUDE_DIR, "imgui.h")), "imgui.h not found"
assert os.path.isfile(os.path.join(LIB_DIR, "libimgui.a")), "libimgui.a not found"
assert os.path.isfile(os.path.join(LIB_DIR, "libglfw3.a")), "libglfw3.a not found"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "GLFW", "glfw3.h")), "GLFW/glfw3.h not found"
if _platform.system() == "Linux":
assert os.path.isfile(os.path.join(MESA_DIR, "libGL.so.1")), "libGL.so.1 not found"

15
imgui/pyproject.toml Normal file
View File

@@ -0,0 +1,15 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "imgui"
version = "1.92.7"
description = "Dear ImGui + ImPlot + GLFW 3.4 (static)"
requires-python = ">=3.8"
[tool.setuptools]
packages = ["imgui"]
[tool.setuptools.package-data]
imgui = ["install/**/*"]

58
imgui/setup.py Normal file
View File

@@ -0,0 +1,58 @@
import os
import platform
import subprocess
from setuptools.command.build_py import build_py
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
bdist_wheel = None
class BuildImgui(build_py):
"""Run build.sh to download imgui sources before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run()
cmdclass = {"build_py": BuildImgui}
if bdist_wheel is not None:
class PlatformWheel(bdist_wheel):
"""Produce a platform-specific, Python-version-agnostic wheel."""
def finalize_options(self):
super().finalize_options()
self.root_is_pure = False
def get_tag(self):
system = platform.system()
machine = platform.machine()
if system == "Linux":
plat = f"linux_{machine}"
elif system == "Darwin":
plat = "macosx_11_0_arm64"
else:
plat = f"{system.lower()}_{machine}"
return "py3", "none", plat
cmdclass["bdist_wheel"] = PlatformWheel
def setup():
from setuptools import setup as _setup
_setup(cmdclass=cmdclass)
if __name__ == "__main__":
setup()

View File

@@ -6,36 +6,26 @@ cd "$DIR"
VERSION="db00e9369a92aa74bf630a2ffb092a4b0b132c01" VERSION="db00e9369a92aa74bf630a2ffb092a4b0b132c01"
INSTALL_DIR="$DIR/json11/install" INSTALL_DIR="$DIR/json11/install"
VERSION_FILE="$INSTALL_DIR/VERSION" CXX="ccache ${CXX:-c++}"
# Idempotent: skip if already built at this source revision.
if [ -f "$INSTALL_DIR/lib/libjson11.a" ] && [ -f "$INSTALL_DIR/include/json11/json11.hpp" ] && \
[ -f "$VERSION_FILE" ] && [ "$(cat "$VERSION_FILE")" = "$VERSION" ]; then
echo "json11 already present, skipping build."
exit 0
fi
if [ ! -d "$DIR/json11-src/.git" ]; then if [ ! -d "$DIR/json11-src/.git" ]; then
git clone https://github.com/dropbox/json11.git json11-src git clone --depth 1 https://github.com/dropbox/json11.git json11-src
fi fi
git -C json11-src fetch --force origin git -C json11-src fetch --depth 1 origin "$VERSION"
git -C json11-src checkout --force "$VERSION" git -C json11-src checkout --force "$VERSION"
BUILD_DIR="$DIR/build" BUILD_DIR="$DIR/build"
rm -rf "$BUILD_DIR" "$INSTALL_DIR" mkdir -p "$BUILD_DIR"
mkdir -p "$BUILD_DIR" "$INSTALL_DIR/lib" "$INSTALL_DIR/include/json11" rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/lib" "$INSTALL_DIR/include/json11"
CXX="${CXX:-c++}" CXX="${CXX:-c++}"
AR="${AR:-ar}" AR="${AR:-ar}"
"$CXX" -std=c++11 -fPIC -O2 -c "$DIR/json11-src/json11.cpp" -o "$BUILD_DIR/json11.o" $CXX -std=c++11 -fPIC -O2 -c "$DIR/json11-src/json11.cpp" -o "$BUILD_DIR/json11.o"
"$AR" rcs "$INSTALL_DIR/lib/libjson11.a" "$BUILD_DIR/json11.o" "$AR" rcs "$INSTALL_DIR/lib/libjson11.a" "$BUILD_DIR/json11.o"
cp "$DIR/json11-src/json11.hpp" "$INSTALL_DIR/include/json11/json11.hpp" cp "$DIR/json11-src/json11.hpp" "$INSTALL_DIR/include/json11/json11.hpp"
echo "$VERSION" > "$VERSION_FILE"
# Keep workspace small and deterministic across builds.
rm -rf "$DIR/json11-src" "$BUILD_DIR"
echo "Installed json11 to $INSTALL_DIR" echo "Installed json11 to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildJson11(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "json11", "install", "lib", "libjson11.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="3.1.0" VERSION="3.1.0"
INSTALL_DIR="$DIR/libjpeg/install" INSTALL_DIR="$DIR/libjpeg/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libjpeg.a" ]; then
echo "libjpeg already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Clone # Clone/update source
if [ ! -d "libjpeg-turbo-src" ]; then if [ ! -d "libjpeg-turbo-src/.git" ]; then
git clone --depth 1 --branch "${VERSION}" https://github.com/libjpeg-turbo/libjpeg-turbo.git libjpeg-turbo-src rm -rf libjpeg-turbo-src
git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo.git libjpeg-turbo-src
fi fi
git -C libjpeg-turbo-src fetch --depth 1 origin "${VERSION}"
git -C libjpeg-turbo-src checkout --force FETCH_HEAD
# Build # Build
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
@@ -50,8 +47,5 @@ cp "$PREFIX/include/jconfig.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/jerror.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/jerror.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/jmorecfg.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/jmorecfg.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf libjpeg-turbo-src "$DIR/build"
echo "Installed libjpeg to $INSTALL_DIR" echo "Installed libjpeg to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildLibjpeg(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "libjpeg", "install", "lib", "libjpeg.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

52
libusb/build.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
VERSION="1.0.29"
ARCHIVE="libusb-${VERSION}.tar.bz2"
URL="https://github.com/libusb/libusb/releases/download/v${VERSION}/${ARCHIVE}"
INSTALL_DIR="$DIR/libusb/install"
SRC_DIR="$DIR/libusb-src"
VERSION_FILE="$SRC_DIR/.version"
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
export CC="ccache ${CC:-cc}"
if [ ! -f "$VERSION_FILE" ] || [ "$(cat "$VERSION_FILE")" != "$VERSION" ]; then
rm -rf "$SRC_DIR"
mkdir -p "$SRC_DIR"
curl -fSL "$URL" | tar xj --strip-components=1 -C "$SRC_DIR"
echo "$VERSION" > "$VERSION_FILE"
fi
PREFIX="$DIR/build/prefix"
rm -rf "$DIR/build"
mkdir -p "$DIR/build"
CONFIGURE_ARGS=(
--prefix="$PREFIX"
--disable-shared
--enable-static
)
if [ "$(uname)" = "Linux" ]; then
CONFIGURE_ARGS+=(--disable-udev)
fi
cd "$SRC_DIR"
CFLAGS="-O2 -fPIC" ./configure "${CONFIGURE_ARGS[@]}"
make -j"$NJOBS"
make install
cd "$DIR"
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/lib/pkgconfig" "$INSTALL_DIR/include/libusb-1.0"
cp "$PREFIX/lib/libusb-1.0.a" "$INSTALL_DIR/lib/"
cp "$PREFIX/lib/pkgconfig/libusb-1.0.pc" "$INSTALL_DIR/lib/pkgconfig/"
cp "$PREFIX/include/libusb-1.0/libusb.h" "$INSTALL_DIR/include/libusb-1.0/"
echo "Installed libusb to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

12
libusb/libusb/__init__.py Normal file
View File

@@ -0,0 +1,12 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
LIB_DIR = os.path.join(DIR, "lib")
INCLUDE_DIR = os.path.join(DIR, "include")
PKGCONFIG_DIR = os.path.join(LIB_DIR, "pkgconfig")
def smoketest():
assert os.path.isfile(os.path.join(LIB_DIR, "libusb-1.0.a")), "libusb-1.0.a not found"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "libusb-1.0", "libusb.h")), "libusb.h not found"
assert os.path.isfile(os.path.join(PKGCONFIG_DIR, "libusb-1.0.pc")), "libusb-1.0.pc not found"

View File

@@ -3,13 +3,13 @@ requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[project] [project]
name = "openssl3" name = "libusb"
version = "3.4.1" version = "1.0.29"
description = "OpenSSL cryptography library (static build)" description = "libusb USB device access library (static build)"
requires-python = ">=3.8" requires-python = ">=3.8"
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
include = ["openssl3*"] include = ["libusb*"]
[tool.setuptools.package-data] [tool.setuptools.package-data]
openssl3 = ["install/**/*"] libusb = ["install/**/*"]

58
libusb/setup.py Normal file
View File

@@ -0,0 +1,58 @@
import os
import platform
import subprocess
from setuptools.command.build_py import build_py
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
bdist_wheel = None
class BuildLibusb(build_py):
"""Run build.sh to compile libusb before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run()
cmdclass = {"build_py": BuildLibusb}
if bdist_wheel is not None:
class PlatformWheel(bdist_wheel):
"""Produce a platform-specific, Python-version-agnostic wheel."""
def finalize_options(self):
super().finalize_options()
self.root_is_pure = False
def get_tag(self):
system = platform.system()
machine = platform.machine()
if system == "Linux":
plat = f"linux_{machine}"
elif system == "Darwin":
plat = "macosx_11_0_arm64"
else:
plat = f"{system.lower()}_{machine}"
return "py3", "none", plat
cmdclass["bdist_wheel"] = PlatformWheel
def setup():
from setuptools import setup as _setup
_setup(cmdclass=cmdclass)
if __name__ == "__main__":
setup()

View File

@@ -6,25 +6,17 @@ cd "$DIR"
VERSION="6067afde563c3946eebd94f146b3824ab7a97a9c" VERSION="6067afde563c3946eebd94f146b3824ab7a97a9c"
INSTALL_DIR="$DIR/libyuv/install" INSTALL_DIR="$DIR/libyuv/install"
VERSION_FILE="$INSTALL_DIR/VERSION"
# Idempotent: skip if already built at this source revision.
if [ -f "$INSTALL_DIR/lib/libyuv.a" ] && [ -f "$VERSION_FILE" ] && [ "$(cat "$VERSION_FILE")" = "$VERSION" ]; then
echo "libyuv already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
if [ ! -d "libyuv-src/.git" ]; then if [ ! -d "libyuv-src/.git" ]; then
git clone https://chromium.googlesource.com/libyuv/libyuv libyuv-src git clone --depth 1 https://chromium.googlesource.com/libyuv/libyuv libyuv-src
fi fi
git -C libyuv-src fetch --force origin git -C libyuv-src fetch --depth 1 origin "$VERSION"
git -C libyuv-src checkout --force "$VERSION" git -C libyuv-src checkout --force "$VERSION"
BUILD_DIR="$DIR/build/build" BUILD_DIR="$DIR/build"
rm -rf "$DIR/build"
mkdir -p "$BUILD_DIR" mkdir -p "$BUILD_DIR"
cmake -S "$DIR/libyuv-src" -B "$BUILD_DIR" \ cmake -S "$DIR/libyuv-src" -B "$BUILD_DIR" \
@@ -47,10 +39,6 @@ rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{lib,include} mkdir -p "$INSTALL_DIR"/{lib,include}
cp "$LIBYUV_STATIC" "$INSTALL_DIR/lib/libyuv.a" cp "$LIBYUV_STATIC" "$INSTALL_DIR/lib/libyuv.a"
cp -r "$DIR/libyuv-src/include/." "$INSTALL_DIR/include/" cp -r "$DIR/libyuv-src/include/." "$INSTALL_DIR/include/"
echo "$VERSION" > "$VERSION_FILE"
# Keep workspace small and deterministic across builds.
rm -rf "$DIR/libyuv-src" "$DIR/build"
echo "Installed libyuv to $INSTALL_DIR" echo "Installed libyuv to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildLibyuv(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "libyuv", "install", "lib", "libyuv.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

25
nanosvg/build.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
COMMIT="5cefd9847949af6df13f65027fd43af5a7513633"
INSTALL_DIR="$DIR/nanosvg/install"
# Clone/update source
if [ ! -d "nanosvg-src/.git" ]; then
rm -rf nanosvg-src
git clone --depth 1 https://github.com/memononen/nanosvg.git nanosvg-src
fi
git -C nanosvg-src fetch --depth 1 origin "$COMMIT"
git -C nanosvg-src checkout --force FETCH_HEAD
# Copy headers
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/include"
cp nanosvg-src/src/nanosvg.h "$INSTALL_DIR/include/"
cp nanosvg-src/src/nanosvgrast.h "$INSTALL_DIR/include/"
echo "Installed nanosvg to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

@@ -0,0 +1,10 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
LIB_DIR = DIR # header-only; no libraries
def smoketest():
assert os.path.isfile(os.path.join(INCLUDE_DIR, "nanosvg.h")), "nanosvg.h not found"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "nanosvgrast.h")), "nanosvgrast.h not found"

View File

@@ -3,13 +3,13 @@ requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
[project] [project]
name = "python3-dev" name = "nanosvg"
version = "3.12.8" version = "0.0.1"
description = "CPython development headers" description = "NanoSVG: simple SVG parser and rasterizer"
requires-python = ">=3.8" requires-python = ">=3.8"
[tool.setuptools.packages.find] [tool.setuptools.packages.find]
include = ["python3_dev*"] include = ["nanosvg*"]
[tool.setuptools.package-data] [tool.setuptools.package-data]
python3_dev = ["install/**/*"] nanosvg = ["install/**/*"]

View File

@@ -10,21 +10,18 @@ except ImportError:
bdist_wheel = None bdist_wheel = None
class BuildPython3Dev(build_py): class BuildNanosvg(build_py):
"""Run build.sh to download CPython headers before collecting package data.""" """Run build.sh to download nanosvg headers before collecting package data."""
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "python3_dev", "install", "include", "Python.h") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()
cmdclass = {"build_py": BuildPython3Dev} cmdclass = {"build_py": BuildNanosvg}
if bdist_wheel is not None: if bdist_wheel is not None:

View File

@@ -6,31 +6,25 @@ cd "$DIR"
VERSION="6.5" VERSION="6.5"
INSTALL_DIR="$DIR/ncurses/install" INSTALL_DIR="$DIR/ncurses/install"
VERSION_FILE="$DIR/ncurses-src/.version"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libncurses.a" ]; then
echo "ncurses already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
export CC="ccache ${CC:-cc}"
# Download # Download tarball (v6.5 tag doesn't exist on the GitHub mirror)
TARBALL="ncurses-${VERSION}.tar.gz" if [ ! -f "$VERSION_FILE" ] || [ "$(cat "$VERSION_FILE")" != "$VERSION" ]; then
if [ ! -f "$TARBALL" ]; then rm -rf ncurses-src
curl -fsSL "https://ftp.gnu.org/gnu/ncurses/${TARBALL}" -o "$TARBALL" mkdir -p ncurses-src
fi curl -fSL "https://ftp.gnu.org/gnu/ncurses/ncurses-${VERSION}.tar.gz" \
| tar xz --strip-components=1 -C ncurses-src
# Extract echo "$VERSION" > "$VERSION_FILE"
if [ ! -d "ncurses-${VERSION}" ]; then
tar xf "$TARBALL"
fi fi
# Build # Build
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
mkdir -p "$DIR/build" mkdir -p "$DIR/build"
cd "ncurses-${VERSION}" cd ncurses-src
CFLAGS="-fPIC" ./configure \ CFLAGS="-fPIC" ./configure \
--prefix="$PREFIX" \ --prefix="$PREFIX" \
--without-shared \ --without-shared \
@@ -66,8 +60,5 @@ cp "$PREFIX/include/unctrl.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/term.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/term.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/termcap.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/termcap.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf "ncurses-${VERSION}" "$TARBALL" "$DIR/build"
echo "Installed ncurses to $INSTALL_DIR" echo "Installed ncurses to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildNcurses(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "ncurses", "install", "lib", "libncurses.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -1,75 +0,0 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
VERSION="3.4.1"
INSTALL_DIR="$DIR/openssl3/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libcrypto.a" ]; then
echo "openssl already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Download
TARBALL="openssl-${VERSION}.tar.gz"
if [ ! -d "openssl-src" ]; then
curl -fSL -o "$TARBALL" "https://github.com/openssl/openssl/releases/download/openssl-${VERSION}/${TARBALL}"
mkdir -p openssl-src
tar -xf "$TARBALL" -C openssl-src --strip-components=1
rm -f "$TARBALL"
fi
# Configure
PREFIX="$DIR/build/prefix"
cd openssl-src
if [ "$(uname)" = "Darwin" ]; then
TARGET="darwin64-arm64-cc"
else
MACHINE="$(uname -m)"
if [ "$MACHINE" = "x86_64" ]; then
TARGET="linux-x86_64"
elif [ "$MACHINE" = "aarch64" ]; then
TARGET="linux-aarch64"
else
TARGET="linux-${MACHINE}"
fi
fi
./Configure "$TARGET" \
--prefix="$PREFIX" \
--libdir=lib \
no-shared \
no-tests \
no-docs \
no-apps \
-fPIC \
-Os
# Build
make -j"$NJOBS"
make install_sw
cd "$DIR"
# Copy to package install dir
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{lib,include}
# Libraries
cp "$PREFIX/lib/libcrypto.a" "$INSTALL_DIR/lib/"
cp "$PREFIX/lib/libssl.a" "$INSTALL_DIR/lib/"
# Headers
cp -r "$PREFIX/include/openssl" "$INSTALL_DIR/include/"
# Clean up
rm -rf openssl-src "$DIR/build"
echo "Installed openssl to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

@@ -1,11 +0,0 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
LIB_DIR = os.path.join(DIR, "lib")
INCLUDE_DIR = os.path.join(DIR, "include")
def smoketest():
assert os.path.isfile(os.path.join(LIB_DIR, "libcrypto.a")), "libcrypto.a not found"
assert os.path.isfile(os.path.join(LIB_DIR, "libssl.a")), "libssl.a not found"
assert os.path.isdir(os.path.join(INCLUDE_DIR, "openssl")), "openssl headers not found"

View File

@@ -1,19 +1,25 @@
[tool.uv.workspace] [tool.uv.workspace]
members = [ members = [
"acados",
"bzip2", "bzip2",
"capnproto", "capnproto",
"catch2",
"cppcheck", "cppcheck",
"eigen", "eigen",
"ffmpeg", "ffmpeg",
"gcc-arm-none-eabi", "gcc-arm-none-eabi",
"git",
"git-lfs", "git-lfs",
"imgui",
"json11", "json11",
"libusb",
"libjpeg", "libjpeg",
"libyuv", "libyuv",
"nanosvg",
"ncurses", "ncurses",
"openssl3", "qt5",
"python3-dev",
"raylib", "raylib",
"xvfb",
"zeromq", "zeromq",
"zstd", "zstd",
] ]

View File

@@ -1,44 +0,0 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
VERSION="3.12.8"
INSTALL_DIR="$DIR/python3_dev/install"
# Idempotent: skip if already present
if [ -f "$INSTALL_DIR/include/Python.h" ]; then
echo "python3-dev headers already present, skipping."
exit 0
fi
TARBALL="Python-${VERSION}.tgz"
URL="https://www.python.org/ftp/python/${VERSION}/${TARBALL}"
echo "Downloading CPython ${VERSION} source ..."
curl -fSL -o "$TARBALL" "$URL"
echo "Extracting ..."
tar xzf "$TARBALL"
cd "Python-${VERSION}"
# Run configure to generate pyconfig.h for this platform
echo "Running configure to generate pyconfig.h ..."
./configure --disable-shared --without-ensurepip > /dev/null 2>&1
cd "$DIR"
# Copy headers
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/include"
cp -r "Python-${VERSION}/Include/"* "$INSTALL_DIR/include/"
cp "Python-${VERSION}/pyconfig.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf "Python-${VERSION}" "$TARBALL"
echo "Installed python3-dev headers to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

@@ -1,9 +0,0 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
def smoketest():
assert os.path.isfile(os.path.join(INCLUDE_DIR, "Python.h")), "Python.h not found"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "pyconfig.h")), "pyconfig.h not found"

View File

@@ -6,13 +6,8 @@ cd "$DIR"
INSTALL_DIR="$DIR/raylib/install" INSTALL_DIR="$DIR/raylib/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libraylib.a" ]; then
echo "raylib already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
CC="ccache ${CC:-cc}"
# Detect platform: PLATFORM_COMMA for comma devices, PLATFORM_DESKTOP otherwise # Detect platform: PLATFORM_COMMA for comma devices, PLATFORM_DESKTOP otherwise
RAYLIB_PLATFORM="${RAYLIB_PLATFORM:-PLATFORM_DESKTOP}" RAYLIB_PLATFORM="${RAYLIB_PLATFORM:-PLATFORM_DESKTOP}"
@@ -59,17 +54,18 @@ fi
# Clone and build raylib C library # Clone and build raylib C library
RAYLIB_COMMIT="d9d7cc1353ec0f73c97e84ddf0973983d1ee25e2" RAYLIB_COMMIT="d9d7cc1353ec0f73c97e84ddf0973983d1ee25e2"
if [ ! -d "raylib-src" ]; then if [ ! -d "raylib-src/.git" ]; then
git clone -b platform-offscreen --no-tags https://github.com/commaai/raylib.git raylib-src rm -rf raylib-src
git clone --depth 1 -b platform-offscreen --no-tags https://github.com/commaai/raylib.git raylib-src
fi fi
cd raylib-src cd raylib-src
git fetch origin "$RAYLIB_COMMIT" git fetch --depth 1 origin "$RAYLIB_COMMIT"
git reset --hard "$RAYLIB_COMMIT" git reset --hard "$RAYLIB_COMMIT"
git clean -xdff .
cd src cd src
make -j"$NJOBS" PLATFORM="$RAYLIB_PLATFORM" make clean
make -j"$NJOBS" PLATFORM="$RAYLIB_PLATFORM" CC="${CC:-gcc}"
cd "$DIR" cd "$DIR"
@@ -97,7 +93,7 @@ if [[ "$(uname)" == "Linux" && "$(uname -m)" == "x86_64" && "$RAYLIB_PLATFORM" !
cd raylib-src/src cd raylib-src/src
make clean make clean
make -j"$NJOBS" PLATFORM=PLATFORM_OFFSCREEN make -j"$NJOBS" PLATFORM=PLATFORM_OFFSCREEN CC="${CC:-gcc}"
cp libraylib.a "$INSTALL_DIR/lib/libraylib_offscreen.a" cp libraylib.a "$INSTALL_DIR/lib/libraylib_offscreen.a"
cd "$DIR" cd "$DIR"
@@ -121,8 +117,5 @@ RAYGUI_COMMIT="76b36b597edb70ffaf96f046076adc20d67e7827"
curl -fsSLo "$INSTALL_DIR/include/raygui.h" \ curl -fsSLo "$INSTALL_DIR/include/raygui.h" \
"https://raw.githubusercontent.com/raysan5/raygui/$RAYGUI_COMMIT/src/raygui.h" "https://raw.githubusercontent.com/raysan5/raygui/$RAYGUI_COMMIT/src/raygui.h"
# Clean up source
rm -rf raylib-src
echo "Installed raylib to $INSTALL_DIR" echo "Installed raylib to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "raylib" name = "raylib"
version = "5.5.0.6" version = "5.5.0.8"
description = "raylib + pyray Python bindings (commaai fork)" description = "raylib + pyray Python bindings (commaai fork)"
requires-python = ">=3.8" requires-python = ">=3.8"
dependencies = ["cffi>=1.17.1"] dependencies = ["cffi>=1.17.1"]

View File

@@ -1 +1 @@
__version__ = "5.5.0.6" __version__ = "5.5.0.8"

View File

@@ -18,11 +18,8 @@ class BuildRaylib(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "raylib", "install", "lib", "libraylib.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
# Build CFFI extension so it's included in the wheel # Build CFFI extension so it's included in the wheel
cffi_so = glob.glob(os.path.join(pkg_dir, "raylib", "_raylib_cffi*")) cffi_so = glob.glob(os.path.join(pkg_dir, "raylib", "_raylib_cffi*"))

View File

@@ -29,7 +29,7 @@ for toml in */pyproject.toml; do
done done
shopt -u nullglob shopt -u nullglob
TOKEN="$(gh auth token 2>/dev/null)" || { echo "set GH_TOKEN to publish shim branch" >&2; exit 1; } TOKEN="$(gh auth token 2>/dev/null)" || { echo "set GH_TOKEN to publish shim branches" >&2; exit 1; }
TMP_DIR="$(mktemp -d)" TMP_DIR="$(mktemp -d)"
python3 - "$TMP_DIR" "$REPO" <<'PY' python3 - "$TMP_DIR" "$REPO" <<'PY'
@@ -55,7 +55,8 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
datadir = patterns[0].split("/", 1)[0] if patterns and patterns[0] else "" datadir = patterns[0].split("/", 1)[0] if patterns and patterns[0] else ""
scripts = data.get("project", {}).get("scripts", {}) or {} scripts = data.get("project", {}).get("scripts", {}) or {}
pkg_dir = tmp_dir / pkg repo_dir = tmp_dir / pkg
pkg_dir = repo_dir / pkg
mod_dir = pkg_dir / module mod_dir = pkg_dir / module
mod_dir.mkdir(parents=True, exist_ok=True) mod_dir.mkdir(parents=True, exist_ok=True)
@@ -64,17 +65,37 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
for py_file in src_mod.glob("*.py"): for py_file in src_mod.glob("*.py"):
shutil.copy2(py_file, mod_dir / py_file.name) shutil.copy2(py_file, mod_dir / py_file.name)
# copy extra packages (e.g. pyray for raylib) # copy extra packages (e.g. pyray for raylib, slim casadi for acados)
include_patterns = data.get("tool", {}).get("setuptools", {}).get("packages", {}).get("find", {}).get("include", []) # binaries (.so/.dylib) are fetched from the wheel at install time, so the
# shim repo only carries Python sources to keep it small
def _ignore_binaries(_dir, names):
return [n for n in names if n.endswith((".so", ".dylib", ".a")) or ".so." in n or n == "__pycache__"]
# `packages` is either a flat list (["acados", "casadi"]) or a dict with
# `find.include` patterns (["acados*", "casadi*"]) — handle both
pkgs_val = data.get("tool", {}).get("setuptools", {}).get("packages", [])
if isinstance(pkgs_val, list):
include_patterns = list(pkgs_val)
elif isinstance(pkgs_val, dict):
include_patterns = pkgs_val.get("find", {}).get("include", [])
else:
include_patterns = []
extra_packages = [] extra_packages = []
for pattern in include_patterns: for pattern in include_patterns:
p = pattern.rstrip("*") p = pattern.rstrip("*")
if p and p != module and p != f"{module}/": if p and p != module and p != f"{module}/":
src_extra = pathlib.Path(pkg) / p src_extra = pathlib.Path(pkg) / p
dst_extra = pkg_dir / p
if src_extra.is_dir(): if src_extra.is_dir():
dst_extra = pkg_dir / p shutil.copytree(src_extra, dst_extra, dirs_exist_ok=True, ignore=_ignore_binaries)
shutil.copytree(src_extra, dst_extra, dirs_exist_ok=True) else:
extra_packages.append(pattern) # source not in the workspace (typically built lazily by build.sh and
# not cached into the publish job). Drop a placeholder __init__.py so
# setuptools.packages.find picks it up; the shim's setup.py overwrites
# it from the wheel at install time.
dst_extra.mkdir(parents=True, exist_ok=True)
(dst_extra / "__init__.py").write_text("")
extra_packages.append(pattern)
shutil.copy2(shim_setup, pkg_dir / "setup.py") shutil.copy2(shim_setup, pkg_dir / "setup.py")
@@ -100,14 +121,28 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
for name, target in scripts.items(): for name, target in scripts.items():
lines.append(f'"{name}" = {json.dumps(target)}') lines.append(f'"{name}" = {json.dumps(target)}')
find_include = [f"{module}*"] + extra_packages # propagate the workspace's package-data so the shim wheel knows to ship
# everything the upstream wheel ships (e.g. acados_template/, casadi/*.so).
workspace_pkgdata = data.get("tool", {}).get("setuptools", {}).get("package-data", {})
# extra_packages may be plain names (["casadi"]) or globs (["casadi*"]).
# Normalise to plain package names for both `packages` and `package-data`.
extra_pkg_names = [p.rstrip("*").rstrip("/") for p in extra_packages]
lines += [ lines += [
"", "",
"[tool.setuptools.packages.find]", "[tool.setuptools]",
f"include = {json.dumps(find_include)}", f"packages = {json.dumps([module] + extra_pkg_names)}",
"", "",
"[tool.setuptools.package-data]", "[tool.setuptools.package-data]",
f'{module} = ["{datadir}/**/*", "*.so"]', ]
module_data = sorted(set(workspace_pkgdata.get(module, [f"{datadir}/**/*"]) + ["*.so"]))
lines.append(f"{module} = {json.dumps(module_data)}")
for name in extra_pkg_names:
extra_data = workspace_pkgdata.get(name, ["**/*"])
lines.append(f"{name} = {json.dumps(list(extra_data))}")
lines += [
"", "",
"[tool.shim]", "[tool.shim]",
f'repo_url = "{repo_url}"', f'repo_url = "{repo_url}"',
@@ -118,14 +153,25 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
(pkg_dir / "pyproject.toml").write_text("\n".join(lines) + "\n") (pkg_dir / "pyproject.toml").write_text("\n".join(lines) + "\n")
PY PY
( shopt -s nullglob
cd "$TMP_DIR" for repo_dir in "$TMP_DIR"/*; do
git init [[ -d "$repo_dir" ]] || continue
git checkout -b releases
git add . pkg="$(basename "$repo_dir")"
git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" commit -m "update shim packages" branch="release-$pkg"
git remote add origin "https://x-access-token:${TOKEN}@github.com/${REPO}.git"
git push -f origin releases echo "[$pkg] Publishing shim branch $branch"
)
(
cd "$repo_dir"
git init
git checkout -b "$branch"
git add "$pkg"
git -c user.name="github-actions[bot]" -c user.email="github-actions[bot]@users.noreply.github.com" commit -m "update $pkg shim"
git remote add origin "https://x-access-token:${TOKEN}@github.com/${REPO}.git"
git push -f origin "$branch"
)
done
shopt -u nullglob
rm -rf "$TMP_DIR" rm -rf "$TMP_DIR"

View File

@@ -15,12 +15,12 @@ run_as_root() {
} }
if [ "$(uname)" = "Darwin" ]; then if [ "$(uname)" = "Darwin" ]; then
brew install nasm pkg-config brew install nasm pkg-config ccache autoconf automake libtool
elif command -v dnf &>/dev/null; then elif command -v dnf &>/dev/null; then
dnf install -y nasm cmake gcc-c++ pkgconfig git perl-IPC-Cmd dnf install -y nasm cmake gcc-c++ pkgconfig git perl-IPC-Cmd ccache autoconf automake libtool
elif command -v apt-get &>/dev/null; then elif command -v apt-get &>/dev/null; then
run_as_root apt-get update run_as_root apt-get update
run_as_root apt-get install -y nasm cmake g++ pkg-config curl run_as_root apt-get install -y nasm cmake g++ pkg-config curl ccache autoconf automake libtool
fi fi
if ! command -v uv &>/dev/null; then if ! command -v uv &>/dev/null; then

133
xvfb/build.sh Executable file
View File

@@ -0,0 +1,133 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
INSTALL_DIR="$DIR/xvfb/install"
# macOS: Xvfb is Linux-only. Ship an empty install dir so the wheel still
# builds; smoketest() is a no-op on Darwin.
if [[ "$OSTYPE" == "darwin"* ]]; then
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{bin,lib,share/X11/xkb}
echo "xvfb: macOS not supported, shipping empty install dir"
exit 0
fi
# Linux: bundle the Xvfb binary, xkbcomp, xkb keymap data, and the closure
# of shared libraries it needs (minus libc/libpthread/etc which the host
# always provides). For CI/manylinux we pull from AlmaLinux 8 so the wheel
# works on any glibc >= 2.28 distro; on a Debian/Ubuntu dev host we accept
# whatever the system has (the local wheel just won't be as portable).
if command -v dnf >/dev/null 2>&1; then
dnf install -y -q xorg-x11-server-Xvfb xorg-x11-xkb-utils xkeyboard-config >/dev/null
elif command -v apt-get >/dev/null 2>&1; then
if [[ "$(id -u)" -eq 0 ]]; then SUDO=""
elif command -v sudo >/dev/null 2>&1; then SUDO=sudo
else echo "xvfb: need sudo or root to apt-get install" >&2; exit 1; fi
export DEBIAN_FRONTEND=noninteractive
$SUDO apt-get update -qq
$SUDO apt-get install -y -qq --no-install-recommends \
xvfb x11-xkb-utils xkb-data patchelf
else
echo "xvfb: need dnf or apt-get to fetch upstream Xvfb" >&2
exit 1
fi
if ! command -v patchelf >/dev/null 2>&1; then
echo "xvfb: patchelf is required but not found" >&2
exit 1
fi
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{bin,lib,share/X11/xkb}
# Xvfb may live in /usr/bin (RPM/Debian) — just locate it.
XVFB_SRC="$(command -v Xvfb || true)"
XKBCOMP_SRC="$(command -v xkbcomp || true)"
if [[ -z "$XVFB_SRC" || -z "$XKBCOMP_SRC" ]]; then
echo "xvfb: Xvfb or xkbcomp not found after install" >&2
exit 1
fi
cp "$XVFB_SRC" "$INSTALL_DIR/bin/Xvfb"
cp "$XKBCOMP_SRC" "$INSTALL_DIR/bin/xkbcomp"
chmod u+w "$INSTALL_DIR/bin/Xvfb" "$INSTALL_DIR/bin/xkbcomp"
cp -a /usr/share/X11/xkb/. "$INSTALL_DIR/share/X11/xkb/"
# Two binary patches to make Xvfb relocatable:
#
# 1. "/usr/bin" -> "" (null bytes)
# Xvfb's compile-time XkbBinDirectory points at /usr/bin and is used to
# build an absolute path to xkbcomp. Blanking it makes the spawned
# command just "xkbcomp", which popen() then resolves via PATH. Our
# Python wrapper prepends the bundled bin/ to PATH.
#
# 2. "-R%s" -> "-I%s" (in the xkbcomp argv format string)
# Xvfb passes its XkbBaseDirectory to xkbcomp via -R, expecting xkbcomp
# to chdir there *and* add "." to the include path. xkbcomp 1.4.x only
# chdirs — the include-path side was added later. Switching to -I makes
# 1.4.2 actually search the path we hand it via -xkbdir.
python3 - "$INSTALL_DIR/bin/Xvfb" <<'PY'
import sys
path = sys.argv[1]
with open(path, "r+b") as f:
data = bytearray(f.read())
def replace_unique(needle: bytes, replacement: bytes):
assert len(needle) == len(replacement)
idx = data.find(needle)
if idx < 0:
sys.exit(f"could not find {needle!r} in Xvfb binary")
if data.find(needle, idx + 1) >= 0:
sys.exit(f"multiple {needle!r} matches; refusing to patch")
data[idx:idx + len(needle)] = replacement
replace_unique(b"/usr/bin\x00", b"\x00" * 9)
replace_unique(b'"-R%s"\x00', b'"-I%s"\x00')
with open(path, "wb") as f:
f.write(data)
PY
# bundle the shared library closure. Recursively walk ldd output to catch
# libs-of-libs (e.g. libXfont2 -> libfontenc -> libbz2). Skip core glibc
# pieces; everything else gets copied alongside the binary.
declare -A SEEN
collect_libs() {
local target="$1"
while IFS= read -r line; do
local lib
lib=$(echo "$line" | awk '{print $3}')
[[ -z "$lib" || "$lib" == "not" ]] && continue
[[ ! -e "$lib" ]] && continue
local base
base=$(basename "$lib")
case "$base" in
libc.so.*|libpthread.so.*|libm.so.*|librt.so.*|libdl.so.*|libgcc_s.so.*|libresolv.so.*|libutil.so.*|ld-linux-*.so.*|linux-vdso.so.*|linux-gate.so.*)
continue ;;
esac
[[ -n "${SEEN[$base]:-}" ]] && continue
SEEN[$base]=1
cp -L "$lib" "$INSTALL_DIR/lib/$base"
chmod u+w "$INSTALL_DIR/lib/$base"
collect_libs "$INSTALL_DIR/lib/$base"
done < <(ldd "$target" 2>/dev/null || true)
}
collect_libs "$INSTALL_DIR/bin/Xvfb"
collect_libs "$INSTALL_DIR/bin/xkbcomp"
# point the binaries (and the bundled libs) at our private lib dir so they
# don't accidentally resolve against an incompatible host copy.
patchelf --set-rpath '$ORIGIN/../lib' "$INSTALL_DIR/bin/Xvfb"
patchelf --set-rpath '$ORIGIN/../lib' "$INSTALL_DIR/bin/xkbcomp"
for so in "$INSTALL_DIR"/lib/*.so*; do
patchelf --set-rpath '$ORIGIN' "$so" 2>/dev/null || true
done
strip --strip-unneeded "$INSTALL_DIR/bin/Xvfb" "$INSTALL_DIR/bin/xkbcomp" 2>/dev/null || true
find "$INSTALL_DIR/lib" -name '*.so*' -exec strip --strip-unneeded {} + 2>/dev/null || true
echo "Installed xvfb to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

18
xvfb/pyproject.toml Normal file
View File

@@ -0,0 +1,18 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "xvfb"
version = "1.20.11.post1"
description = "Xvfb (X virtual framebuffer) headless X server"
requires-python = ">=3.8"
[project.scripts]
Xvfb = "xvfb:_run_xvfb"
[tool.setuptools.packages.find]
include = ["xvfb*"]
[tool.setuptools.package-data]
xvfb = ["install/**/*"]

58
xvfb/setup.py Normal file
View File

@@ -0,0 +1,58 @@
import os
import platform
import subprocess
from setuptools.command.build_py import build_py
try:
from wheel.bdist_wheel import bdist_wheel
except ImportError:
bdist_wheel = None
class BuildXvfb(build_py):
"""Run build.sh to fetch and bundle Xvfb before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run()
cmdclass = {"build_py": BuildXvfb}
if bdist_wheel is not None:
class PlatformWheel(bdist_wheel):
"""Produce a platform-specific, Python-version-agnostic wheel."""
def finalize_options(self):
super().finalize_options()
self.root_is_pure = False
def get_tag(self):
system = platform.system()
machine = platform.machine()
if system == "Linux":
plat = f"linux_{machine}"
elif system == "Darwin":
plat = "macosx_11_0_arm64"
else:
plat = f"{system.lower()}_{machine}"
return "py3", "none", plat
cmdclass["bdist_wheel"] = PlatformWheel
def setup():
from setuptools import setup as _setup
_setup(cmdclass=cmdclass)
if __name__ == "__main__":
setup()

57
xvfb/xvfb/__init__.py Normal file
View File

@@ -0,0 +1,57 @@
import os
import sys
DIR = os.path.join(os.path.dirname(__file__), "install")
BIN_DIR = os.path.join(DIR, "bin")
LIB_DIR = os.path.join(DIR, "lib")
XKB_DIR = os.path.join(DIR, "share", "X11", "xkb")
XVFB_BIN = os.path.join(BIN_DIR, "Xvfb")
XKBCOMP_BIN = os.path.join(BIN_DIR, "xkbcomp")
# Common host paths where Mesa DRI drivers (e.g. swrast_dri.so) live. Xvfb
# was built on AlmaLinux 8 with /usr/lib64/dri baked in; on other distros
# (Debian/Ubuntu in particular) the drivers are elsewhere, and without them
# Xvfb fails to bring up a GL provider and silently disables the GLX
# extension. Probing the standard locations lets the host's drivers be
# found regardless of distro.
_DRI_PATHS = (
"/usr/lib64/dri",
"/usr/lib/x86_64-linux-gnu/dri",
"/usr/lib/aarch64-linux-gnu/dri",
"/usr/lib/dri",
)
def _run_xvfb():
# The bundled Xvfb has its compile-time XkbBinDirectory blanked out so it
# invokes xkbcomp via PATH lookup; prepend our bin dir so the bundled
# xkbcomp wins. -xkbdir points the server at the bundled keymap data.
env = os.environ.copy()
env["PATH"] = BIN_DIR + os.pathsep + env.get("PATH", "")
if "LIBGL_DRIVERS_PATH" not in env:
found = [p for p in _DRI_PATHS if os.path.isdir(p)]
if found:
env["LIBGL_DRIVERS_PATH"] = os.pathsep.join(found)
args = sys.argv[1:]
if not any(a == "-xkbdir" for a in args):
args = ["-xkbdir", XKB_DIR] + args
os.execvpe(XVFB_BIN, [XVFB_BIN] + args, env)
def smoketest():
if sys.platform == "darwin":
return
assert os.path.isfile(XVFB_BIN), f"Xvfb not found at {XVFB_BIN}"
assert os.path.isfile(XKBCOMP_BIN), f"xkbcomp not found at {XKBCOMP_BIN}"
assert os.path.isdir(XKB_DIR), f"xkb data not found at {XKB_DIR}"
import subprocess
# Xvfb prints usage to stderr and exits non-zero on `-help`; the banner
# mentions Xvfb-specific flags like -screen and -fbdir. If those appear,
# the binary loaded its bundled libs and ran far enough to print help.
result = subprocess.run([XVFB_BIN, "-help"], capture_output=True, text=True)
output = result.stderr + result.stdout
assert "-screen scrn WxHxD" in output, \
f"Xvfb -help did not produce expected output: {output}"

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="4.3.5" VERSION="4.3.5"
INSTALL_DIR="$DIR/zeromq/install" INSTALL_DIR="$DIR/zeromq/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libzmq.a" ]; then
echo "zeromq already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Clone # Clone/update source
if [ ! -d "libzmq-src" ]; then if [ ! -d "libzmq-src/.git" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/zeromq/libzmq.git libzmq-src rm -rf libzmq-src
git clone --depth 1 https://github.com/zeromq/libzmq.git libzmq-src
fi fi
git -C libzmq-src fetch --depth 1 origin "v${VERSION}"
git -C libzmq-src checkout --force FETCH_HEAD
# Build # Build
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
@@ -54,8 +51,5 @@ cp "$PREFIX/lib/libzmq.a" "$INSTALL_DIR/lib/"
cp "$PREFIX/include/zmq.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/zmq.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/zmq_utils.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/zmq_utils.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf libzmq-src "$DIR/build"
echo "Installed zeromq to $INSTALL_DIR" echo "Installed zeromq to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildZeromq(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "zeromq", "install", "lib", "libzmq.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="1.5.6" VERSION="1.5.6"
INSTALL_DIR="$DIR/zstd/install" INSTALL_DIR="$DIR/zstd/install"
# Idempotent: skip if already built
if [ -f "$INSTALL_DIR/lib/libzstd.a" ]; then
echo "zstd already present, skipping build."
exit 0
fi
NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)" NJOBS="$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 2)"
# Clone # Clone/update source
if [ ! -d "zstd-src" ]; then if [ ! -d "zstd-src/.git" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/facebook/zstd.git zstd-src rm -rf zstd-src
git clone --depth 1 https://github.com/facebook/zstd.git zstd-src
fi fi
git -C zstd-src fetch --depth 1 origin "v${VERSION}"
git -C zstd-src checkout --force FETCH_HEAD
# Build # Build
PREFIX="$DIR/build/prefix" PREFIX="$DIR/build/prefix"
@@ -52,8 +49,5 @@ cp "$PREFIX/include/zstd.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/zstd_errors.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/zstd_errors.h" "$INSTALL_DIR/include/"
cp "$PREFIX/include/zdict.h" "$INSTALL_DIR/include/" cp "$PREFIX/include/zdict.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf zstd-src "$DIR/build"
echo "Installed zstd to $INSTALL_DIR" echo "Installed zstd to $INSTALL_DIR"
du -sh "$INSTALL_DIR" du -sh "$INSTALL_DIR"

View File

@@ -15,11 +15,8 @@ class BuildZstd(build_py):
def run(self): def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__)) pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "zstd", "install", "lib", "libzstd.a") build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
if not os.path.exists(marker):
build_script = os.path.join(pkg_dir, "build.sh")
subprocess.check_call(["bash", build_script], cwd=pkg_dir)
super().run() super().run()