Compare commits

..

16 Commits

Author SHA1 Message Date
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
Adeeb Shihadeh
7d158432af raylib: bump to 5.5.0.6 (re-publish with offscreen libs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:00:47 -08:00
Adeeb Shihadeh
c81badf4a5 raylib: install EGL/GL dev packages for offscreen variant build
The manylinux container doesn't have Mesa packages pre-installed.
Install them before building the offscreen variant and bundling GLVND.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:54:54 -08:00
Adeeb Shihadeh
122939fdf2 raylib: add PLATFORM_OFFSCREEN support (#38)
* raylib: add PLATFORM_OFFSCREEN support for headless CI rendering

- build.sh: use commaai/raylib platform-offscreen commit, build offscreen
  variant (libraylib_offscreen.a) alongside desktop for x86_64, bundle
  GLVND dispatchers (libEGL, libOpenGL, libGLdispatch) in install/lib/mesa/
- build.py: add PLATFORM_OFFSCREEN elif — uses offscreen lib + bundled
  GLVND with RPATH, links -lOpenGL -lEGL instead of -lGL -lX11
- __init__.py: auto-rebuild CFFI when RAYLIB_PLATFORM env changes
  (tracks built platform in .raylib_platform marker file)
- Bump version to 5.5.0.5

This lets openpilot CI render headlessly via EGL surfaceless + Mesa
llvmpipe without needing xvfb or any additional apt packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* raylib: auto-detect CI and use PLATFORM_OFFSCREEN

__init__.py now auto-detects CI on Linux x86_64 and uses
PLATFORM_OFFSCREEN + LIBGL_ALWAYS_SOFTWARE=1 automatically.
No env vars needed in the consuming CI workflow.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:44:19 -08:00
Adeeb Shihadeh
9690fd5160 raylib: use stable ABI for CFFI extension (#37)
The CFFI extension was built with py_limited_api=False, producing
version-specific .so files (e.g., cpython-312 on Linux, cpython-314
on macOS). This caused import failures when the build Python version
didn't match the runtime version.

Switch to py_limited_api=True to produce _raylib_cffi.abi3.so which
works across Python 3.x versions.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:07:15 -08:00
Adeeb Shihadeh
c835b206c6 release: include compiled extensions (*.so) in shim package-data (#36)
The shim setup.py extracts .so files from the wheel, but the
generated pyproject.toml didn't include them in package-data, so
they were excluded when uv built a local wheel from the source.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:50:07 -08:00
Adeeb Shihadeh
70b6bf1c40 raylib: include pre-compiled CFFI extension in wheel (#35)
Build the CFFI Python extension (_raylib_cffi.so) during wheel build
instead of deferring to first import. This eliminates the need for
libgl-dev and libx11-dev on the target system.

- setup.py: run build.py after build.sh to compile CFFI extension
- pyproject.toml: include _raylib_cffi*.so in package-data, bump to 5.5.0.3
- _shim_setup.py: extract .so files from wheel alongside data directory

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:36:30 -08:00
Adeeb Shihadeh
d67b3e906e release: copy all Python sources and deps to shim branch (#34)
The shim branch was only copying __init__.py from each package,
which dropped Python source files needed for CFFI builds (build.py,
colors.py, defines.py, enums.py, version.py) and extra packages
like pyray. It also dropped project dependencies like cffi.

- Copy all .py files from the main module, not just __init__.py
- Copy extra packages listed in packages.find.include
- Preserve project dependencies in generated pyproject.toml
2026-03-01 12:04:48 -08:00
51 changed files with 452 additions and 445 deletions

View File

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

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
repo/
.venv/
__pycache__/
uv.lock
# agents
.claude/

View File

@@ -1,8 +1,10 @@
"""Shim setup.py: downloads pre-built wheels from GitHub Releases at install time."""
import os
import platform
import time
import zipfile
from io import BytesIO
from urllib.error import URLError
from urllib.request import urlopen
try:
@@ -32,7 +34,8 @@ PLATFORM_MAP = {
class InstallPrebuilt(build_py):
def run(self):
data_dir = os.path.join(_HERE, MODULE, DATADIR)
module_dir = os.path.join(_HERE, MODULE)
data_dir = os.path.join(module_dir, DATADIR)
if not os.path.exists(os.path.join(data_dir, "bin")):
key = (platform.system(), platform.machine())
@@ -44,7 +47,16 @@ class InstallPrebuilt(build_py):
url = f"{REPO_URL}/releases/download/{TAG}/{whl_name}"
print(f"Downloading {url} ...")
raw = urlopen(url).read()
for attempt in range(3):
try:
raw = urlopen(url, timeout=60).read()
break
except (URLError, OSError) as e:
if attempt == 2:
raise
wait = 2 ** attempt
print(f"Download failed ({e}), retrying in {wait}s ...")
time.sleep(wait)
print(f"Extracting {DATADIR} ...")
with zipfile.ZipFile(BytesIO(raw)) as zf:
@@ -67,6 +79,24 @@ class InstallPrebuilt(build_py):
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
for p in (ext_prefix, ext_alt_prefix):
if info.filename.startswith(p):
rel = info.filename[len(p):]
if rel and '/' not in rel:
dest = os.path.join(module_dir, 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)
break
super().run()

View File

@@ -34,6 +34,9 @@ fi
if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
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
if [[ -z "${BUILD_SH_REUSE_MANYLINUX_ARTIFACTS:-}" ]]; then
@@ -45,10 +48,15 @@ if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
fi
fi
export CMAKE_C_COMPILER_LAUNCHER=ccache
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
echo "Building workspace packages into dist"
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
VENV_DIR="$ROOT_DIR/.venv-manylinux"

View File

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

View File

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

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="1.0.1"
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)"
# Clone
if [ ! -d "capnproto-src" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/capnproto/capnproto.git capnproto-src
# Clone/update source
if [ ! -d "capnproto-src/.git" ]; then
rm -rf capnproto-src
git clone --depth 1 https://github.com/capnproto/capnproto.git capnproto-src
fi
git -C capnproto-src fetch --depth 1 origin "v${VERSION}"
git -C capnproto-src checkout --force FETCH_HEAD
# Build
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
done
# Clean up
rm -rf capnproto-src "$DIR/build"
echo "Installed capnproto to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

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

View File

@@ -7,18 +7,16 @@ cd "$DIR"
VERSION="2.16.0"
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)"
CXX="ccache ${CXX:-c++}"
# Clone
if [ ! -d "cppcheck-src" ]; then
git clone --depth 1 --branch "$VERSION" https://github.com/danmar/cppcheck.git cppcheck-src
# Clone/update source
if [ ! -d "cppcheck-src/.git" ]; then
rm -rf cppcheck-src
git clone --depth 1 https://github.com/danmar/cppcheck.git cppcheck-src
fi
git -C cppcheck-src fetch --depth 1 origin "$VERSION"
git -C cppcheck-src checkout --force FETCH_HEAD
# Build
cd cppcheck-src
@@ -35,8 +33,5 @@ cp -r cppcheck-src/cfg "$INSTALL_DIR/"
cp -r cppcheck-src/platforms "$INSTALL_DIR/"
strip "$INSTALL_DIR/cppcheck" 2>/dev/null || true
# Clean up
rm -rf cppcheck-src
echo "Installed cppcheck to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

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

View File

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

View File

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

View File

@@ -5,23 +5,22 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
FFMPEG_VERSION="7.1"
ZLIB_VERSION="da607da739fa6047df13e66a2af6b8bec7c2a498" # v1.3.2
X264_BRANCH="stable"
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)"
CC="ccache ${CC:-cc}"
PREFIX="$DIR/build/prefix"
mkdir -p "$DIR/build"
# --- Build zlib (static) ---
if [ ! -d "zlib-src" ]; then
git clone https://github.com/madler/zlib.git zlib-src
git -C zlib-src checkout da607da739fa6047df13e66a2af6b8bec7c2a498 # pin to v1.3.2
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 "$ZLIB_VERSION"
cd zlib-src
./configure --prefix="$PREFIX" --static
@@ -30,9 +29,12 @@ make install
cd "$DIR"
# --- Build x264 (static) ---
if [ ! -d "x264-src" ]; then
git clone --depth 1 --branch stable https://code.videolan.org/videolan/x264.git x264-src
if [ ! -d "x264-src/.git" ]; then
rm -rf x264-src
git clone --depth 1 https://code.videolan.org/videolan/x264.git x264-src
fi
git -C x264-src fetch --depth 1 origin "$X264_BRANCH"
git -C x264-src checkout --force FETCH_HEAD
cd x264-src
CFLAGS="-fno-finite-math-only" ./configure \
@@ -47,13 +49,17 @@ make install
cd "$DIR"
# --- Build FFmpeg ---
if [ ! -d "ffmpeg-src" ]; then
git clone --depth 1 --branch "n${FFMPEG_VERSION}" https://github.com/FFmpeg/FFmpeg.git ffmpeg-src
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
PKG_CONFIG_PATH="$PREFIX/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" \
./configure \
--cc="${CC:-cc}" \
--prefix="$PREFIX" \
--enable-gpl \
--enable-static \
@@ -100,8 +106,5 @@ done
# Strip binaries
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"
du -sh "$INSTALL_DIR"

View File

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

View File

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

View File

@@ -1,10 +1,8 @@
import os
import platform
import subprocess
import sys
from setuptools.command.build_py import build_py
from setuptools.dist import Distribution
try:
from wheel.bdist_wheel import bdist_wheel
@@ -17,11 +15,6 @@ class BuildToolchain(build_py):
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
toolchain_marker = os.path.join(
pkg_dir, "gcc_arm_none_eabi", "toolchain", "bin", "arm-none-eabi-gcc"
)
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)

View File

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

View File

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

67
imgui/build.sh Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd "$DIR"
INSTALL_DIR="$DIR/imgui/install"
# Dear ImGui (docking branch, version 1.92.7)
IMGUI_COMMIT="934c6a5f5ef2355d6df25395d555cb71f790c4e9"
# ImPlot
IMPLOT_COMMIT="93c801b4bb801c5c11031d880b6af1d1f70bd79d"
# rlImGui
RLIMGUI_COMMIT="286e11acd6c785004c9550c7ed3762add2ae3d47"
# 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 rlimgui
if [ ! -d "rlimgui-src/.git" ]; then
rm -rf rlimgui-src
git clone --depth 1 https://github.com/raylib-extras/rlImGui.git rlimgui-src
fi
git -C rlimgui-src fetch --depth 1 origin "$RLIMGUI_COMMIT"
git -C rlimgui-src checkout --force "$RLIMGUI_COMMIT"
# Install
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/include/extras" "$INSTALL_DIR/src"
# imgui
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/imgui.cpp imgui-src/imgui_draw.cpp imgui-src/imgui_tables.cpp \
imgui-src/imgui_widgets.cpp imgui-src/imgui_demo.cpp \
"$INSTALL_DIR/src/"
cp imgui-src/backends/imgui_impl_opengl3.h imgui-src/backends/imgui_impl_opengl3_loader.h \
"$INSTALL_DIR/include/"
cp imgui-src/backends/imgui_impl_opengl3.cpp "$INSTALL_DIR/src/"
# implot
cp implot-src/implot.h implot-src/implot_internal.h "$INSTALL_DIR/include/"
cp implot-src/implot.cpp implot-src/implot_items.cpp "$INSTALL_DIR/src/"
# rlimgui
cp rlimgui-src/rlImGui.h rlimgui-src/rlImGuiColors.h rlimgui-src/imgui_impl_raylib.h \
"$INSTALL_DIR/include/"
cp rlimgui-src/extras/FA6FreeSolidFontData.h rlimgui-src/extras/IconsFontAwesome6.h \
"$INSTALL_DIR/include/extras/"
cp rlimgui-src/rlImGui.cpp "$INSTALL_DIR/src/"
echo "Installed imgui to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

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

@@ -0,0 +1,10 @@
import os
DIR = os.path.join(os.path.dirname(__file__), "install")
INCLUDE_DIR = os.path.join(DIR, "include")
SRC_DIR = os.path.join(DIR, "src")
def smoketest():
assert os.path.isfile(os.path.join(INCLUDE_DIR, "imgui.h")), "imgui.h not found"
assert os.path.isfile(os.path.join(SRC_DIR, "imgui.cpp")), "imgui.cpp not found"

View File

@@ -3,13 +3,13 @@ requires = ["setuptools>=64", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "openssl3"
version = "3.4.1"
description = "OpenSSL cryptography library (static build)"
name = "imgui"
version = "1.92.7"
description = "Dear ImGui + ImPlot + rlImGui (source distribution)"
requires-python = ">=3.8"
[tool.setuptools.packages.find]
include = ["openssl3*"]
include = ["imgui*"]
[tool.setuptools.package-data]
openssl3 = ["install/**/*"]
imgui = ["install/**/*"]

View File

@@ -10,21 +10,18 @@ except ImportError:
bdist_wheel = None
class BuildOpenssl(build_py):
"""Run build.sh to compile OpenSSL before collecting package data."""
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__))
marker = os.path.join(pkg_dir, "openssl3", "install", "lib", "libcrypto.a")
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()
cmdclass = {"build_py": BuildOpenssl}
cmdclass = {"build_py": BuildImgui}
if bdist_wheel is not None:

View File

@@ -6,36 +6,26 @@ cd "$DIR"
VERSION="db00e9369a92aa74bf630a2ffb092a4b0b132c01"
INSTALL_DIR="$DIR/json11/install"
VERSION_FILE="$INSTALL_DIR/VERSION"
# 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
CXX="ccache ${CXX:-c++}"
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
git -C json11-src fetch --force origin
git -C json11-src fetch --depth 1 origin "$VERSION"
git -C json11-src checkout --force "$VERSION"
BUILD_DIR="$DIR/build"
rm -rf "$BUILD_DIR" "$INSTALL_DIR"
mkdir -p "$BUILD_DIR" "$INSTALL_DIR/lib" "$INSTALL_DIR/include/json11"
mkdir -p "$BUILD_DIR"
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR/lib" "$INSTALL_DIR/include/json11"
CXX="${CXX:-c++}"
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"
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"
du -sh "$INSTALL_DIR"

View File

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

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="3.1.0"
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)"
# Clone
if [ ! -d "libjpeg-turbo-src" ]; then
git clone --depth 1 --branch "${VERSION}" https://github.com/libjpeg-turbo/libjpeg-turbo.git libjpeg-turbo-src
# Clone/update source
if [ ! -d "libjpeg-turbo-src/.git" ]; then
rm -rf libjpeg-turbo-src
git clone --depth 1 https://github.com/libjpeg-turbo/libjpeg-turbo.git libjpeg-turbo-src
fi
git -C libjpeg-turbo-src fetch --depth 1 origin "${VERSION}"
git -C libjpeg-turbo-src checkout --force FETCH_HEAD
# Build
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/jmorecfg.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf libjpeg-turbo-src "$DIR/build"
echo "Installed libjpeg to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

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

View File

@@ -6,25 +6,17 @@ cd "$DIR"
VERSION="6067afde563c3946eebd94f146b3824ab7a97a9c"
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)"
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
git -C libyuv-src fetch --force origin
git -C libyuv-src fetch --depth 1 origin "$VERSION"
git -C libyuv-src checkout --force "$VERSION"
BUILD_DIR="$DIR/build/build"
rm -rf "$DIR/build"
BUILD_DIR="$DIR/build"
mkdir -p "$BUILD_DIR"
cmake -S "$DIR/libyuv-src" -B "$BUILD_DIR" \
@@ -47,10 +39,6 @@ rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"/{lib,include}
cp "$LIBYUV_STATIC" "$INSTALL_DIR/lib/libyuv.a"
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"
du -sh "$INSTALL_DIR"

View File

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

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"
[project]
name = "python3-dev"
version = "3.12.8"
description = "CPython development headers"
name = "nanosvg"
version = "0.0.1"
description = "NanoSVG: simple SVG parser and rasterizer"
requires-python = ">=3.8"
[tool.setuptools.packages.find]
include = ["python3_dev*"]
include = ["nanosvg*"]
[tool.setuptools.package-data]
python3_dev = ["install/**/*"]
nanosvg = ["install/**/*"]

View File

@@ -10,21 +10,18 @@ except ImportError:
bdist_wheel = None
class BuildPython3Dev(build_py):
"""Run build.sh to download CPython headers before collecting package data."""
class BuildNanosvg(build_py):
"""Run build.sh to download nanosvg headers before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "python3_dev", "install", "include", "Python.h")
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()
cmdclass = {"build_py": BuildPython3Dev}
cmdclass = {"build_py": BuildNanosvg}
if bdist_wheel is not None:

View File

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

View File

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

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

@@ -7,12 +7,12 @@ members = [
"ffmpeg",
"gcc-arm-none-eabi",
"git-lfs",
"imgui",
"json11",
"libjpeg",
"libyuv",
"nanosvg",
"ncurses",
"openssl3",
"python3-dev",
"raylib",
"zeromq",
"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"
# 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)"
CC="ccache ${CC:-cc}"
# Detect platform: PLATFORM_COMMA for comma devices, PLATFORM_DESKTOP otherwise
RAYLIB_PLATFORM="${RAYLIB_PLATFORM:-PLATFORM_DESKTOP}"
@@ -33,6 +28,15 @@ if [[ "$(uname)" == "Linux" ]]; then
sudo apt-get update && sudo apt-get install -y libdrm-dev libgbm-dev libgles2-mesa-dev libegl1-mesa-dev || true
fi
fi
elif [ "$RAYLIB_PLATFORM" = "PLATFORM_OFFSCREEN" ]; then
# offscreen (CI): needs EGL/GL dev packages (no X11)
if command -v apt-get &>/dev/null; then
if [ "$(id -u)" -eq 0 ]; then
apt-get update && apt-get install -y libegl-dev libgl-dev
else
sudo apt-get update && sudo apt-get install -y libegl-dev libgl-dev
fi
fi
else
# desktop: needs X11/GL dev packages
if command -v dnf &>/dev/null; then
@@ -48,19 +52,20 @@ if [[ "$(uname)" == "Linux" ]]; then
fi
# Clone and build raylib C library
RAYLIB_COMMIT="aa6ade09ac4bfb2847a356535f2d9f87e49ab089"
RAYLIB_COMMIT="d9d7cc1353ec0f73c97e84ddf0973983d1ee25e2"
if [ ! -d "raylib-src" ]; then
git clone -b master --no-tags https://github.com/commaai/raylib.git raylib-src
if [ ! -d "raylib-src/.git" ]; then
rm -rf raylib-src
git clone --depth 1 -b platform-offscreen --no-tags https://github.com/commaai/raylib.git raylib-src
fi
cd raylib-src
git fetch origin "$RAYLIB_COMMIT"
git fetch --depth 1 origin "$RAYLIB_COMMIT"
git reset --hard "$RAYLIB_COMMIT"
git clean -xdff .
cd src
make -j"$NJOBS" PLATFORM="$RAYLIB_PLATFORM"
make clean
make -j"$NJOBS" PLATFORM="$RAYLIB_PLATFORM" CC="${CC:-gcc}"
cd "$DIR"
@@ -71,13 +76,46 @@ mkdir -p "$INSTALL_DIR"/{lib,include}
cp raylib-src/src/libraylib.a "$INSTALL_DIR/lib/"
cp raylib-src/src/raylib.h raylib-src/src/raymath.h raylib-src/src/rlgl.h "$INSTALL_DIR/include/"
# On x86_64 Linux, also build the offscreen variant for CI headless rendering
if [[ "$(uname)" == "Linux" && "$(uname -m)" == "x86_64" && "$RAYLIB_PLATFORM" != "PLATFORM_OFFSCREEN" ]]; then
echo "Building offscreen variant..."
# Install EGL/GL dev packages needed for offscreen build + bundling
if command -v dnf &>/dev/null; then
dnf install -y mesa-libEGL-devel mesa-libGL-devel libglvnd-opengl libglvnd-core-devel 2>/dev/null || true
elif command -v apt-get &>/dev/null; then
if [ "$(id -u)" -eq 0 ]; then
apt-get update && apt-get install -y libegl-dev libgl-dev
else
sudo apt-get update && sudo apt-get install -y libegl-dev libgl-dev
fi
fi
cd raylib-src/src
make clean
make -j"$NJOBS" PLATFORM=PLATFORM_OFFSCREEN CC="${CC:-gcc}"
cp libraylib.a "$INSTALL_DIR/lib/libraylib_offscreen.a"
cd "$DIR"
# Bundle GLVND dispatchers so offscreen rendering works without extra system packages
MESA_DIR="$INSTALL_DIR/lib/mesa"
mkdir -p "$MESA_DIR"
ldconfig 2>/dev/null || true
for lib in libEGL.so.1 libOpenGL.so.0 libGLdispatch.so.0; do
src="$(ldconfig -p 2>/dev/null | grep "$lib" | grep -E 'x86.64|libc6,' | 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
# Download raygui header
RAYGUI_COMMIT="76b36b597edb70ffaf96f046076adc20d67e7827"
curl -fsSLo "$INSTALL_DIR/include/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"
du -sh "$INSTALL_DIR"

View File

@@ -1,10 +1,10 @@
[build-system]
requires = ["setuptools>=64", "wheel"]
requires = ["setuptools>=64", "wheel", "cffi>=1.17.1"]
build-backend = "setuptools.build_meta"
[project]
name = "raylib"
version = "5.5.0.2"
version = "5.5.0.8"
description = "raylib + pyray Python bindings (commaai fork)"
requires-python = ">=3.8"
dependencies = ["cffi>=1.17.1"]
@@ -13,4 +13,4 @@ dependencies = ["cffi>=1.17.1"]
include = ["raylib*", "pyray*"]
[tool.setuptools.package-data]
raylib = ["install/**/*"]
raylib = ["install/**/*", "_raylib_cffi*.so"]

View File

@@ -1,26 +1,60 @@
import os
import platform as _platform
DIR = os.path.join(os.path.dirname(__file__), "install")
LIB_DIR = os.path.join(DIR, "lib")
INCLUDE_DIR = os.path.join(DIR, "include")
def _detect_platform():
"""Auto-detect the raylib platform. In CI on Linux x86_64, use offscreen EGL rendering."""
explicit = os.environ.get("RAYLIB_PLATFORM", "")
if explicit:
return explicit
if os.environ.get("CI") and _platform.system() == "Linux" and _platform.machine() == "x86_64":
return "PLATFORM_OFFSCREEN"
return ""
def smoketest():
assert os.path.isfile(os.path.join(LIB_DIR, "libraylib.a")), "libraylib.a not found"
assert os.path.isfile(os.path.join(INCLUDE_DIR, "raylib.h")), "raylib.h not found"
# Build CFFI extension on first import if not already compiled
# Build CFFI extension on first import if not already compiled,
# or rebuild if the target platform changed since last build.
def _ensure_cffi_built():
import glob
import subprocess
import sys
pkg_dir = os.path.dirname(__file__)
if not glob.glob(os.path.join(pkg_dir, "_raylib_cffi*")):
platform_marker = os.path.join(pkg_dir, ".raylib_platform")
requested = _detect_platform()
# Export so build.py picks it up
if requested:
os.environ["RAYLIB_PLATFORM"] = requested
# Mesa llvmpipe for software rendering in headless CI
if requested == "PLATFORM_OFFSCREEN":
os.environ.setdefault("LIBGL_ALWAYS_SOFTWARE", "1")
cffi_files = glob.glob(os.path.join(pkg_dir, "_raylib_cffi*"))
# Rebuild if platform changed
if cffi_files and requested:
built_for = open(platform_marker).read().strip() if os.path.isfile(platform_marker) else ""
if built_for != requested:
for f in cffi_files:
os.remove(f)
cffi_files = []
if not cffi_files:
build_script = os.path.join(pkg_dir, "build.py")
if os.path.isfile(build_script) and os.path.isfile(os.path.join(LIB_DIR, "libraylib.a")):
try:
subprocess.check_call([sys.executable, build_script], cwd=os.path.dirname(pkg_dir))
with open(platform_marker, "w") as f:
f.write(requested)
except subprocess.CalledProcessError:
pass

View File

@@ -93,7 +93,7 @@ def build_ffi():
'-framework', 'CoreVideo',
]
libraries = []
extra_compile_args = ["-Wno-error=incompatible-function-pointer-types", "-D_CFFI_NO_LIMITED_API"]
extra_compile_args = ["-Wno-error=incompatible-function-pointer-types"]
else:
print("BUILDING FOR LINUX")
extra_link_args = [
@@ -104,15 +104,26 @@ def build_ffi():
if RAYLIB_PLATFORM == "PLATFORM_COMMA":
extra_link_args.remove('-lGL')
extra_link_args += ['-lGLESv2', '-lEGL', '-lgbm', '-ldrm']
elif RAYLIB_PLATFORM == "PLATFORM_OFFSCREEN":
# Use offscreen variant if available, otherwise fall back to default
offscreen_lib = os.path.join(RAYLIB_LIB_PATH, 'libraylib_offscreen.a')
if os.path.isfile(offscreen_lib):
extra_link_args[extra_link_args.index('-lraylib')] = '-lraylib_offscreen'
extra_link_args.remove('-lGL')
# Use bundled GLVND dispatchers if available, with RPATH for runtime
mesa_dir = os.path.join(RAYLIB_LIB_PATH, 'mesa')
if os.path.isdir(mesa_dir):
extra_link_args += [f'-L{mesa_dir}', f'-Wl,-rpath,$ORIGIN/install/lib/mesa']
extra_link_args += ['-lOpenGL', '-lEGL']
else:
extra_link_args += ['-lX11']
extra_compile_args = ["-Wno-incompatible-pointer-types", "-D_CFFI_NO_LIMITED_API"]
extra_compile_args = ["-Wno-incompatible-pointer-types"]
libraries = []
print("extra_link_args: " + str(extra_link_args))
ffibuilder.set_source("raylib._raylib_cffi",
ffi_includes,
py_limited_api=False,
py_limited_api=True,
include_dirs=[RAYLIB_INCLUDE_PATH],
extra_link_args=extra_link_args,
extra_compile_args=extra_compile_args,

View File

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

View File

@@ -1,6 +1,8 @@
import glob
import os
import platform
import subprocess
import sys
from setuptools import setup
from setuptools.command.build_py import build_py
@@ -12,16 +14,20 @@ except ImportError:
class BuildRaylib(build_py):
"""Run build.sh to compile the C library before collecting package data."""
"""Run build.sh to compile the C library and CFFI extension before collecting package data."""
def run(self):
pkg_dir = os.path.dirname(os.path.abspath(__file__))
marker = os.path.join(pkg_dir, "raylib", "install", "lib", "libraylib.a")
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
cffi_so = glob.glob(os.path.join(pkg_dir, "raylib", "_raylib_cffi*"))
if not cffi_so:
build_cffi = os.path.join(pkg_dir, "raylib", "build.py")
if os.path.isfile(build_cffi):
subprocess.check_call([sys.executable, build_cffi], cwd=pkg_dir)
super().run()

View File

@@ -58,9 +58,28 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
pkg_dir = tmp_dir / pkg
mod_dir = pkg_dir / module
mod_dir.mkdir(parents=True, exist_ok=True)
shutil.copy2(pathlib.Path(pkg) / module / "__init__.py", mod_dir / "__init__.py")
# copy all .py files from the main module
src_mod = pathlib.Path(pkg) / module
for py_file in src_mod.glob("*.py"):
shutil.copy2(py_file, mod_dir / py_file.name)
# copy extra packages (e.g. pyray for raylib)
include_patterns = data.get("tool", {}).get("setuptools", {}).get("packages", {}).get("find", {}).get("include", [])
extra_packages = []
for pattern in include_patterns:
p = pattern.rstrip("*")
if p and p != module and p != f"{module}/":
src_extra = pathlib.Path(pkg) / p
if src_extra.is_dir():
dst_extra = pkg_dir / p
shutil.copytree(src_extra, dst_extra, dirs_exist_ok=True)
extra_packages.append(pattern)
shutil.copy2(shim_setup, pkg_dir / "setup.py")
deps = data.get("project", {}).get("dependencies", [])
lines = [
"[build-system]",
'requires = ["setuptools>=64", "wheel", \'tomli; python_version < \"3.11\"\']',
@@ -73,18 +92,22 @@ for toml in sorted(pathlib.Path(".").glob("*/pyproject.toml")):
'requires-python = ">=3.8"',
]
if deps:
lines.append(f"dependencies = {json.dumps(deps)}")
if scripts:
lines += ["", "[project.scripts]"]
for name, target in scripts.items():
lines.append(f'"{name}" = {json.dumps(target)}')
find_include = [f"{module}*"] + extra_packages
lines += [
"",
"[tool.setuptools.packages.find]",
f'include = ["{module}*"]',
f"include = {json.dumps(find_include)}",
"",
"[tool.setuptools.package-data]",
f'{module} = ["{datadir}/**/*"]',
f'{module} = ["{datadir}/**/*", "*.so"]',
"",
"[tool.shim]",
f'repo_url = "{repo_url}"',

View File

@@ -15,12 +15,12 @@ run_as_root() {
}
if [ "$(uname)" = "Darwin" ]; then
brew install nasm pkg-config
brew install nasm pkg-config ccache
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
elif command -v apt-get &>/dev/null; then
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
fi
if ! command -v uv &>/dev/null; then

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="4.3.5"
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)"
# Clone
if [ ! -d "libzmq-src" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/zeromq/libzmq.git libzmq-src
# Clone/update source
if [ ! -d "libzmq-src/.git" ]; then
rm -rf libzmq-src
git clone --depth 1 https://github.com/zeromq/libzmq.git libzmq-src
fi
git -C libzmq-src fetch --depth 1 origin "v${VERSION}"
git -C libzmq-src checkout --force FETCH_HEAD
# Build
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_utils.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf libzmq-src "$DIR/build"
echo "Installed zeromq to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

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

View File

@@ -7,18 +7,15 @@ cd "$DIR"
VERSION="1.5.6"
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)"
# Clone
if [ ! -d "zstd-src" ]; then
git clone --depth 1 --branch "v${VERSION}" https://github.com/facebook/zstd.git zstd-src
# Clone/update source
if [ ! -d "zstd-src/.git" ]; then
rm -rf zstd-src
git clone --depth 1 https://github.com/facebook/zstd.git zstd-src
fi
git -C zstd-src fetch --depth 1 origin "v${VERSION}"
git -C zstd-src checkout --force FETCH_HEAD
# Build
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/zdict.h" "$INSTALL_DIR/include/"
# Clean up
rm -rf zstd-src "$DIR/build"
echo "Installed zstd to $INSTALL_DIR"
du -sh "$INSTALL_DIR"

View File

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