|
Banjo API 1.0.0-rc.2
Low-level C99 game development API
|
Produce the Banjo library binaries from source, with or without CMake.
Banjo is not distributed as a package: there's no apt install banjo or equivalent. You either build from source (see below) or grab a pre-built release artifact from the Releases page. Either way the runtime side of every optional backend is dlopen'd, so a binary built on one machine can run on another that has the corresponding system shared object installed.
You need at least a C99-compliant compiler. Beyond that, Banjo's CMake auto-detects platform backends (window system, audio) and enables each one whose development headers are present at build time. To get a working out-of-the-box build, install the headers up-front.
Debian / Ubuntu / Mint:
Fedora / RHEL:
Arch:
macOS: no extra install. Cocoa and CoreAudio ship with Xcode / the Command Line Tools (xcode-select --install).
Windows: no extra install. Win32 and MME ship with the Windows SDK (MSVC) or the MinGW-w64 toolchain.
Emscripten: install the emsdk toolchain (https://emscripten.org/docs/getting_started/downloads.html).
Banjo's optional backends are loaded at runtime with dlopen so the resulting libbanjo has no link-time dependency on them. However, each backend still needs the matching development headers at build time to compile its source. CMake auto-detects these: if the headers are missing, that backend is simply not built (and BANJO_CONFIG_*_BACKEND defaults to OFF).
| Backend | Debian / Ubuntu / Mint | Fedora / RHEL | Arch |
|---|---|---|---|
| X11 | libx11-dev | libX11-devel | libx11 |
| Wayland | libwayland-dev + libxkbcommon-dev | wayland-devel + libxkbcommon-devel | wayland + libxkbcommon |
| ALSA | libasound2-dev | alsa-lib-devel | alsa-lib |
At runtime, the dynamic loader must be able to find the shared object matching whatever backend was enabled (libX11.so.6, libwayland-client.so.0, libxkbcommon.so.0, libasound.so.2, etc.). On a desktop Linux distribution these are present whenever the corresponding subsystem is in use, so this typically requires no extra action.
Banjo is designed to be built without any complex build system. You only need to feed your compiler with the source files and the correct include paths.
Compile all .c files in src/ and src/posix/ (on Unix) or src/win32/ (on Windows). Do not compile files in backend-specific subdirectories (src/x11/, src/cocoa/, etc.) unless you are enabling that specific backend.
Add inc/ and src/ to your include search path.
Output type:
Example (GCC/Clang static library):
See "Build options" below for the per-backend / per-option list of macros and linker flags.
Banjo provides a CMake configuration that aims to work out-of-the-box: CMake checks your system for libraries (X11, ALSA, …) and your platform (Windows, macOS), and enables matching backends by default.
Every manual option below has a corresponding CMake option. The naming convention is simple: replace the BJ_ prefix with BANJO_. For example the manual macro BJ_CONFIG_X11_BACKEND becomes the CMake option BANJO_CONFIG_X11_BACKEND.
You can force options ON or OFF to override auto-detection:
A CMakePresets.json is shipped at the project root with the configurations used by Banjo's CI/CD pipeline. Using a preset is optional (the manual cmake commands above work the same) but presets give you a shortcut to the exact build CI runs, handy for reproducing failures locally.
| Preset | Description |
|---|---|
| ci-linux | Linux x86_64 release build with examples and tests (used by the PR build job and the linux release artifact) |
Build artifacts land under build/ci-linux/ to keep preset outputs isolated from any build/ directory you use manually.
Banjo can be built and consumed as either a static or a shared library. The build type is set by CMake options and communicated to producing and consuming code through C macro definitions (in inc/banjo/api.h):
When using CMake you don't set these directly; CMake derives them from BUILD_SHARED_LIBS. The default (unset) is a static library.
You can customize the build by enabling backends or configuration options. To enable an option manually, define the corresponding C macro and compile any required additional sources.
| Option Name | Description |
|---|---|
| Win32 backend | Enable Win32 window support |
| X11 backend | Enable X11 window support |
| Wayland backend | Enable Wayland window support (Linux) |
| Cocoa backend | Enable Cocoa/macOS support |
| MME backend | Enable Windows Multimedia Extensions audio |
| ALSA backend | Enable ALSA audio support |
| CoreAudio backend | Enable CoreAudio support |
| Emscripten backend | Enable Emscripten/WebAssembly support |
| Fake backend | Always-available no-op fallback (default ON) |
| Coloured logs | Enable ANSI coloured log output |
| Log Checks | Failing checks are logged |
| Abort on Check | Failing checks call abort() |
| Pedantic Mode | Prioritise safety over performance |
| Fast Math | Enable fast-math optimisations |
Per-backend / per-option details:
Additional source files: src/win32/video.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| MSVC | /D BJ_CONFIG_WIN32_BACKEND | user32.lib gdi32.lib kernel32.lib |
| GCC/Clang | -D BJ_CONFIG_WIN32_BACKEND | -luser32 -lgdi32 -lkernel32 |
Banjo also calls LoadLibrary("dwmapi.dll") at runtime to resolve DwmFlush for vsync-paced event polling, so there is no link-time dependency on dwmapi. dwmapi.dll ships with every Windows Vista or newer install; on stripped SKUs where it is missing, the backend still works but poll runs uncapped.
Additional source files: src/x11/video.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| GCC/Clang | -D BJ_CONFIG_X11_BACKEND | (none, dlopen'd at runtime) |
Banjo loads libX11.so.6 with dlopen, so libbanjo has no link-time dependency on libX11. The X11 development headers are needed at build time only (see Prerequisites), and libX11.so.6 must be discoverable by the dynamic loader on the target machine. On glibc < 2.34, add -ldl when linking the final executable.
Additional source files: src/wayland/video_wayland.c, src/wayland/wayland-protocol.c, src/wayland/xdg-shell-protocol.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| GCC/Clang | -D BJ_CONFIG_WAYLAND_BACKEND | (none, dlopen'd at runtime) |
Banjo loads libwayland-client.so.0 and libxkbcommon.so.0 with dlopen, so libbanjo has no link-time dependency on either. The Wayland and xkbcommon development headers are needed at build time only (see Prerequisites), and both shared objects must be discoverable by the dynamic loader on the target machine. The Wayland protocol glue (core wayland and xdg-shell) is vendored into the project as pre-generated wayland-scanner output, so neither wayland-scanner nor wayland-protocols is needed at build time. On glibc < 2.34, add -ldl when linking the final executable.
Additional source files: src/cocoa/video.m
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| GCC/Clang | -D BJ_CONFIG_COCOA_BACKEND | -framework Cocoa -framework CoreVideo |
CoreVideo provides CVDisplayLink, which the backend uses for vsync-paced event polling. Both frameworks ship with every macOS install.
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| GCC/Clang | -D BJ_CONFIG_COREAUDIO_BACKEND | -framework AudioToolbox |
Additional source files: src/mme/audio.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| MSVC | /D BJ_CONFIG_MME_BACKEND | (none, loaded at runtime) |
| GCC/Clang | -D BJ_CONFIG_MME_BACKEND | (none, loaded at runtime) |
Banjo calls LoadLibrary("winmm.dll") at runtime and resolves waveOut* entry points dynamically, so there is no link-time dependency on winmm. winmm.dll ships with Windows.
Additional source files: src/alsa/audio.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| GCC/Clang | -D BJ_CONFIG_ALSA_BACKEND | (none, dlopen'd at runtime) |
Banjo loads libasound.so with dlopen, so libbanjo has no link-time dependency on libasound. The ALSA development headers are needed at build time only, and libasound.so.2 must be discoverable by the dynamic loader on the target machine.
Additional source files: src/emscripten/video.c and src/emscripten/audio.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| Emscripten | -D BJ_CONFIG_EMSCRIPTEN_BACKEND | ‘-sEXPORTED_RUNTIME_METHODS=['ccall’,'cwrap','_malloc','_free'] -sEXPORTED_FUNCTIONS=['_bj_emscripten_audio_process'] -sALLOW_MEMORY_GROWTH` |
The always-available no-op fallback. Implements the full video and audio vtables with in-memory bitmaps and silence, so initialisation cannot fail even on a headless host with no display server or sound card. Enabled by default; leaving it on is recommended.
Additional source files: src/fake/video_fake.c and src/fake/audio_fake.c
| Compiler | Compiler Flags | Linker Flags |
|---|---|---|
| Any | -D BJ_CONFIG_FAKE_BACKEND | (none) |
| Macro | Effect |
|---|---|
| BJ_CONFIG_LOG_COLOR | Enable ANSI colour codes in log output |
| BJ_CONFIG_CHECKS_LOG | A failing bj_check logs an error message |
| BJ_CONFIG_CHECKS_ABORT | A failing bj_check calls abort() |
| BJ_CONFIG_PEDANTIC | Enable extra runtime checks (slower, stricter) |
| BJ_CONFIG_FASTMATH | Enable floating-point optimisations that may violate IEEE 754 |
For fast math, GCC/Clang also need -ffast-math -ffp-contract=fast -fno-math-errno -fno-trapping-math; MSVC needs /fp:fast.
CMake says "X11 backend: OFF" on a box that has X11. The runtime library (libx11-6) is installed but the development headers are not. Install libx11-dev (or your distro's equivalent, see Prerequisites).
cmake --build asks for Ninja. You're using a preset that selects Ninja, or you passed -G Ninja. Banjo's presets pin Unix Makefiles. Use the shipped presets or pass -G "Unix Makefiles" explicitly.
clang-tidy fails with cert-err33-c. A return value is being silently discarded. Fold the return into your control flow rather than suppressing with (void): see the Error Management topic for the recipe.
Test binary reports "Potential leaks detected". The test harness's mock_allocators counts every bj_malloc / bj_free and fails the suite if the totals don't match. Look at the most recent TEST_CASE for a missing bj_destroy_* / bj_clear_error / matching bj_free.