Skip to content

Commit bfaa650

Browse files
raylib: add headless backend (#93)
* raylib: add headless backend (EGL surfaceless, no display server) Third backend built from the new PLATFORM_HEADLESS raylib platform. Replaces xvfb for running raylib apps in CI: RAYLIB_BACKEND=headless renders offscreen to an EGL pbuffer via Mesa llvmpipe. Linux x86_64 wheels now ship desktop+headless, aarch64 ships all three backends. An explicit RAYLIB_BACKEND at build time still builds just that backend. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * raylib: bump to 6.0.0.1, EGL/GLES build deps for headless Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * raylib: pin merged headless commit Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 2e42cc9 commit bfaa650

7 files changed

Lines changed: 54 additions & 35 deletions

File tree

build.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ if [[ -n "${BUILD_SH_IN_MANYLINUX:-}" ]]; then
5454
if command -v dnf &>/dev/null; then
5555
dnf install -y -q \
5656
libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel libXi-devel \
57-
mesa-libGL-devel wayland-devel wayland-protocols-devel libxkbcommon-devel \
57+
mesa-libGL-devel mesa-libEGL-devel mesa-libGLES-devel \
58+
wayland-devel wayland-protocols-devel libxkbcommon-devel \
5859
xorg-x11-server-Xvfb xorg-x11-xkb-utils xkeyboard-config
5960
fi
6061
fi

raylib/build.sh

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -22,24 +22,19 @@ if [ -n "${RAYLIB_PLATFORM:-}" ]; then
2222
exit 1
2323
fi
2424

25+
# An explicit RAYLIB_BACKEND builds only that backend; otherwise all of the
26+
# host's backends are built (matches host_backends() in raylib/_backend.py)
2527
RAYLIB_BACKEND="${RAYLIB_BACKEND:-}"
26-
if [ -z "$RAYLIB_BACKEND" ]; then
27-
RAYLIB_BACKEND="desktop"
28-
if [ -f /AGNOS ] || [ -f /TICI ]; then
29-
RAYLIB_BACKEND="comma"
30-
fi
31-
fi
32-
3328
case "$RAYLIB_BACKEND" in
34-
desktop|comma) ;;
29+
""|desktop|comma|headless) ;;
3530
*)
36-
echo "Unsupported RAYLIB_BACKEND=$RAYLIB_BACKEND; expected desktop or comma" >&2
31+
echo "Unsupported RAYLIB_BACKEND=$RAYLIB_BACKEND; expected desktop, comma or headless" >&2
3732
exit 1
3833
;;
3934
esac
4035

4136
# Clone and build raylib C library
42-
RAYLIB_COMMIT="c2fb96ea0ebfceae28ccf7cb436a33a7d7857244"
37+
RAYLIB_COMMIT="caa64e15ac20a47804a8048029c921ac091fef12"
4338

4439
if [ ! -d "raylib-src/.git" ]; then
4540
rm -rf raylib-src
@@ -48,7 +43,9 @@ fi
4843

4944
cd raylib-src
5045
git remote set-url origin https://github.com/commaai/raylib.git
51-
git fetch --depth 1 origin "$RAYLIB_COMMIT"
46+
if ! git cat-file -e "$RAYLIB_COMMIT" 2>/dev/null; then
47+
git fetch --depth 1 origin "$RAYLIB_COMMIT"
48+
fi
5249
git reset --hard "$RAYLIB_COMMIT"
5350

5451
cd "$DIR"
@@ -70,20 +67,30 @@ build_raylib() {
7067
cd "$DIR"
7168
}
7269

73-
if is_linux_aarch64; then
74-
echo "Building desktop backend..."
75-
build_raylib PLATFORM_DESKTOP libraylib_desktop.a
70+
backend_platform() {
71+
case "$1" in
72+
desktop) echo PLATFORM_DESKTOP ;;
73+
comma) echo PLATFORM_COMMA ;;
74+
headless) echo PLATFORM_HEADLESS ;;
75+
esac
76+
}
7677

77-
echo "Building comma backend..."
78-
build_raylib PLATFORM_COMMA libraylib_comma.a
79-
else
80-
if [ "$RAYLIB_BACKEND" = "comma" ]; then
81-
build_raylib PLATFORM_COMMA libraylib_comma.a
82-
else
83-
build_raylib PLATFORM_DESKTOP libraylib_desktop.a
78+
if [ -n "$RAYLIB_BACKEND" ]; then
79+
BACKENDS="$RAYLIB_BACKEND"
80+
elif [ "$(uname)" == "Linux" ]; then
81+
BACKENDS="desktop headless"
82+
if is_linux_aarch64; then
83+
BACKENDS="$BACKENDS comma"
8484
fi
85+
else
86+
BACKENDS="desktop"
8587
fi
8688

89+
for backend in $BACKENDS; do
90+
echo "Building $backend backend..."
91+
build_raylib "$(backend_platform "$backend")" "libraylib_${backend}.a"
92+
done
93+
8794
# Download raygui header
8895
RAYGUI_COMMIT="1e03efca48c50c5ea4b4a053d5bf04bad58d3e43"
8996
curl -fsSLo "$INSTALL_DIR/include/raygui.h" \

raylib/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "raylib"
7-
version = "6.0.0.0"
7+
version = "6.0.0.1"
88
description = "raylib + pyray Python bindings (commaai fork)"
99
requires-python = ">=3.8"
1010
dependencies = ["cffi>=1.17.1"]

raylib/raylib/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import importlib
22
import os
33

4-
from ._backend import BACKEND_ARCHIVES, BACKEND_CFFI_MODULES, detect_backend, is_dual_backend_host
4+
from ._backend import BACKEND_ARCHIVES, BACKEND_CFFI_MODULES, detect_backend, host_backends
55
from .version import __version__
66

77
DIR = os.path.join(os.path.dirname(__file__), "install")
@@ -12,9 +12,10 @@
1212

1313

1414
def _expected_archives():
15-
if is_dual_backend_host():
16-
return BACKEND_ARCHIVES.values()
17-
return (BACKEND_ARCHIVES[_BACKEND],)
15+
# explicit RAYLIB_BACKEND also selects a single-backend build (see setup.py)
16+
if os.environ.get("RAYLIB_BACKEND"):
17+
return (BACKEND_ARCHIVES[_BACKEND],)
18+
return tuple(BACKEND_ARCHIVES[b] for b in host_backends())
1819

1920

2021
def smoketest():

raylib/raylib/_backend.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,49 @@
33

44
DESKTOP = "desktop"
55
COMMA = "comma"
6-
BACKENDS = (DESKTOP, COMMA)
6+
HEADLESS = "headless"
7+
BACKENDS = (DESKTOP, COMMA, HEADLESS)
78
DEFAULT_BACKEND = DESKTOP
89

910
BACKEND_CFFI_MODULES = {
1011
DESKTOP: "_raylib_cffi_desktop",
1112
COMMA: "_raylib_cffi_comma",
13+
HEADLESS: "_raylib_cffi_headless",
1214
}
1315

1416
BACKEND_ARCHIVES = {
1517
DESKTOP: "libraylib_desktop.a",
1618
COMMA: "libraylib_comma.a",
19+
HEADLESS: "libraylib_headless.a",
1720
}
1821

1922
BACKEND_LINK_ARGS = {
2023
DESKTOP: ("-lGL", "-lX11"),
2124
COMMA: ("-lGLESv2", "-lEGL", "-lgbm", "-ldrm"),
25+
HEADLESS: ("-lGLESv2", "-lEGL"),
2226
}
2327

2428
COMMA_DEVICE_MARKERS = ("/AGNOS", "/TICI")
2529

2630

27-
def is_dual_backend_host():
28-
return platform.system() == "Linux" and platform.machine() in ("aarch64", "arm64")
31+
def host_backends():
32+
"""Backends built into this host's wheels."""
33+
if platform.system() != "Linux":
34+
return (DESKTOP,) # headless needs EGL, which macOS doesn't have
35+
if platform.machine() in ("aarch64", "arm64"):
36+
return (DESKTOP, COMMA, HEADLESS)
37+
return (DESKTOP, HEADLESS)
2938

3039

3140
def detect_backend(environ=None, exists=os.path.exists):
3241
environ = os.environ if environ is None else environ
3342
if environ.get("RAYLIB_PLATFORM"):
34-
raise ValueError("RAYLIB_PLATFORM is no longer supported; use RAYLIB_BACKEND=comma|desktop")
43+
raise ValueError(f"RAYLIB_PLATFORM is no longer supported; use RAYLIB_BACKEND={'|'.join(BACKENDS)}")
3544

3645
explicit = environ.get("RAYLIB_BACKEND", "").strip().lower()
3746
if explicit:
3847
if explicit not in BACKENDS:
39-
raise ValueError("RAYLIB_BACKEND must be 'comma' or 'desktop'")
48+
raise ValueError(f"RAYLIB_BACKEND must be one of {', '.join(repr(b) for b in BACKENDS)}")
4049
return explicit
4150

4251
if any(exists(marker) for marker in COMMA_DEVICE_MARKERS):

raylib/raylib/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "6.0.0.0"
1+
__version__ = "6.0.0.1"

raylib/setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
PKG_DIR = os.path.dirname(os.path.abspath(__file__))
1313
sys.path.insert(0, os.path.join(PKG_DIR, "raylib"))
14-
from _backend import BACKENDS, BACKEND_CFFI_MODULES, detect_backend, is_dual_backend_host # noqa: E402
14+
from _backend import BACKEND_CFFI_MODULES, detect_backend, host_backends # noqa: E402
1515

1616

1717
class BuildRaylib(build_py):
@@ -30,7 +30,8 @@ def run(self):
3030
# Always regenerate CFFI extensions: the cached raylib source pin may have changed.
3131
for old_cffi in glob.glob(os.path.join(PKG_DIR, "raylib", "_raylib_cffi*")):
3232
os.remove(old_cffi)
33-
backends = BACKENDS if is_dual_backend_host() else (detect_backend(),)
33+
# explicit RAYLIB_BACKEND builds only that backend (matches build.sh)
34+
backends = (detect_backend(),) if os.environ.get("RAYLIB_BACKEND") else host_backends()
3435
for backend in backends:
3536
self._build_cffi(backend)
3637

0 commit comments

Comments
 (0)