Status: scaffolding landed, C module pending. This spec records
how the C-accelerated runtime is built, installed, and exercised in
CI. The opt-in hook in runtime/pb/init.lua, the just build-c
recipe, and the CI manifests under .builds/ land alongside this
doc; the actual C source they refer to arrives with bd-ra6.
Closes bd-wky.
runtime/pb/
├── c/ (NEW — C runtime sources)
│ ├── Makefile (mirrors bench/c_accel/Makefile)
│ ├── c_runtime.c (entry points + plan struct)
│ ├── plan.c (descriptor -> plan compiler, bd-mq7)
│ ├── encode.c (bd-3b)
│ ├── decode.c (bd-3g)
│ ├── buf.c (4 KB stack-backed buffer)
│ ├── wkt.c (override dispatch, bd-3k)
│ └── ...
├── c_runtime.so (built output — gitignored)
├── c_runtime.dylib (macOS build output — gitignored)
├── init.lua
├── codec.lua
└── ...
The build output sits alongside the Lua files at runtime/pb/c_runtime.{so,dylib}
so require('pb.c_runtime') resolves it via Lua's package.cpath once
the test runner adds ./runtime/?.so to LUA_CPATH (see Test runner).
just build-c$ just build-c
make -C runtime/pb/c
cc -O2 -fPIC -Wall -Wextra -std=c99 -I/usr/include/tarantool ... \
-o runtime/pb/c_runtime.dylib runtime/pb/c/c_runtime.c ...
Mirrors bench/c_accel/Makefile: same TT_INC auto-detection (env
override, brew prefix, common system dirs), same -fPIC -O2, same
platform-aware extension (.dylib bundle on macOS, .so on Linux).
The recipe is a stub today — it runs make -C runtime/pb/c and
errors out cleanly with "no C runtime source yet" until bd-mq7
lands the first source files.
just clean-cRemoves runtime/pb/c_runtime.so and runtime/pb/c_runtime.dylib.
Folded into just clean.
just build and just testUnchanged. Building the C module is not part of the default
flow. Users who care about C must invoke just build-c explicitly.
This keeps the default contributor experience identical for anyone
not working on the C path — just test continues to work without
a C compiler.
The single switch is the environment variable PB_ENABLE_C. See
c_accel_compat.md § Activation for
the full contract.
runtime/pb/init.lua does:
local c_runtime
if os.getenv('PB_ENABLE_C') == '1' then
local ok, mod = pcall(require, 'pb.c_runtime')
if ok then c_runtime = mod end
end
When c_runtime is non-nil, pb.finalize_message(desc) calls into
it to compile a desc.c_plan userdata. When c_runtime is nil,
nothing changes — the pure-Lua path runs unchanged.
This hook is wired today; the finalize-time compile call is
deferred to bd-mq7.
The Justfile's lua_path constant covers Lua module resolution.
For the C module, the test recipe also sets LUA_CPATH:
lua_cpath := "./runtime/?.so;./runtime/?.dylib;./runtime/?/init.so;;"
test: gen
LUA_PATH="{{lua_path}}" LUA_CPATH="{{lua_cpath}}" {{luatest}} -v test/
This is added by the wky landing PR. With runtime/pb/c_runtime.so
built, require('pb.c_runtime') resolves to that path.
tt rocks install puts compiled modules under .rocks/lib/tarantool/,
which is already on the default cpath; the wky changes only affect
the local dev workflow, not installed rocks.
The current rockspec uses build.type = "builtin" which copies Lua
files only. To optionally build the C module, the rockspec gains:
external_dependencies = {
TARANTOOL = { header = "module.h" },
}
build = {
type = "builtin",
modules = {
["pb"] = "runtime/pb/init.lua",
-- ... existing Lua modules ...
-- The C module is listed as a buildable source:
["pb.c_runtime"] = {
sources = {
"runtime/pb/c/c_runtime.c",
"runtime/pb/c/plan.c",
"runtime/pb/c/encode.c",
"runtime/pb/c/decode.c",
},
incdirs = { "$(TARANTOOL_INCDIR)" },
},
},
}
Behavior:
tt rocks install (or luarocks install) detects the C compiler
and module.h via external_dependencies. If both are present,
the C module compiles. If module.h is missing (older Tarantool,
no -dev package), the install fails because the rockspec
declares it as a hard dependency.module.h), we'd need to use luarocks-specific
build.platforms or two separate rockspec variants. Deferred:
for now, if the user installs and doesn't have tarantool-dev,
installation fails with a clear error message — acceptable
because every supported Tarantool environment ships module.h.The rockspec change lands when the first C sources exist (bd-mq7
or bd-ra6). The wky scaffolding leaves the rockspec at "builtin
Lua only" for now and documents the change here.
Two manifests under .builds/:
.builds/pure-lua.yml — full test suite with PB_ENABLE_C
unset. Validates the pure-Lua path and the silent-fallback case
(env var unset means C is dormant even when present)..builds/c-enabled.yml — same test suite plus just build-c
and PB_ENABLE_C=1. Validates the C path end-to-end.Both run on ubuntu/noble. Sourcehut submits both per push (no
matrix; each .builds/*.yml is an independent job).
Until the repo is pushed to a sourcehut-compatible host (or a
webhook from sourcecraft.dev fires hut builds submit), the
manifests sit idle. They start producing value the day the remote
lands. No CI-side configuration is required beyond the manifests
themselves.
A third manifest at .sourcehut/conformance.yml (deliberately
outside .builds/ so it doesn't auto-submit) runs the Google
proto3 conformance suite inside the Docker harness. Submit it
manually with hut builds submit .sourcehut/conformance.yml before
a release or after wire-format changes. Skipping it from every-push
CI is a deliberate cost-control choice — the suite pulls a multi-GB
Docker image and runs ~7000 tests; it doesn't belong on the
fast-feedback path.
The bench/c_accel/Makefile patterns we mirror in runtime/pb/c/Makefile:
-shared, output is .so.-bundle -undefined dynamic_lookup,
output is .dylib. The dynamic_lookup flag is what lets the
module use lua_* symbols without linking against a specific
Lua/Tarantool binary.bd-wky todayruntime/pb/init.lua — PB_ENABLE_C pcall hook (lines added at
module load; exposes c_runtime field on the returned table for
introspection).Justfile — build-c, clean-c recipes; updated lua_cpath
variable; test recipe sources LUA_CPATH..builds/pure-lua.yml, .builds/c-enabled.yml — CI matrix..sourcehut/conformance.yml — manual conformance trigger..gitignore — runtime/pb/c_runtime.{so,dylib} ignored.bd-wkyruntime/pb/c/ doesn't exist; just build-c
errors with a clear message until bd-ra6 populates the
directory.bd-mq7 or
bd-ra6).finalize_message C-plan compile call. Lives with bd-mq7.bench/c_accel/Makefile — reference build, the patterns here are
the patterns there.builds/{pure-lua,c-enabled}.yml — CI manifests.sourcehut/conformance.yml — manual conformance manifest