# Justfile — canonical entry point for build / gen / test / bench / conformance.
#
# `just` is required (https://github.com/casey/just). On macOS: brew install just
# On Linux: cargo install just
#
# Quick map of common targets:
# just show available recipes
# just build build both plugins
# just gen regenerate examples/expected/{full,runtime}/*
# just test run the luatest suite
# just bench alloc + throughput per op
# just conformance run Google's conformance suite in Docker
# just examples per-example runners (see examples/Justfile)
#
# Sub-recipes live in examples/Justfile (one target per runnable example).
set shell := ["bash", "-cu"]
# ---------------------------------------------------------------------------
# Paths and constants
# ---------------------------------------------------------------------------
plugin := "protoc-gen-tarantool"
doc_plugin := "protoc-gen-tarantool-doc"
gen_dir := "examples/expected"
docs_dir := "examples/docs"
proto_dir := "examples/proto"
conformance_proto := "test/conformance/proto"
proto2_test_dir := "test/proto"
luatest := ".rocks/bin/luatest"
image := "tarantool-protobuf-conformance:latest"
# Semicolon-joined LUA_PATH for the luatest suite. Trailing `;;` defers to the
# standard package.path for everything not explicitly listed.
lua_path := "./runtime/?/init.lua;./runtime/?.lua;./" + gen_dir + "/?.lua;./" + gen_dir + "/?/init.lua;./?.lua;./?/init.lua;./test/?.lua;;"
# LUA_CPATH for the optional C runtime (require('pb.c_runtime')). Trailing
# `;;` defers to the standard cpath. The C module is built into
# runtime/pb/c_runtime.{so,dylib} by `just build-c` when PB_ENABLE_C=1 is
# in play; absent without it. See docs/specs/c_accel_build_packaging.md.
lua_cpath := "./runtime/?.so;./runtime/?.dylib;./runtime/?/init.so;./runtime/?/init.dylib;;"
# ---------------------------------------------------------------------------
# Default
# ---------------------------------------------------------------------------
# Show available recipes.
default:
@just --list
# Build everything from scratch and run the test suite.
all: build gen test
# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------
# Build the Lua codegen plugin (./protoc-gen-tarantool).
build:
go build -o {{plugin}} ./cmd/protoc-gen-tarantool
# Build the Markdown doc plugin (./protoc-gen-tarantool-doc).
build-doc:
go build -o {{doc_plugin}} ./cmd/protoc-gen-tarantool-doc
# Build the optional C-acceleration runtime into runtime/pb/c_runtime.{so,dylib}.
# Source lives under runtime/pb/c/ once bd-ra6 lands; until then this recipe
# prints a helpful error and exits 1. The runtime is opt-in via PB_ENABLE_C=1
# — see docs/specs/c_accel_build_packaging.md for the full contract.
build-c:
@if [ ! -d runtime/pb/c ]; then \
echo "build-c: runtime/pb/c/ does not exist yet."; \
echo " The C runtime arrives with bd-ra6 (generic C codec)."; \
echo " See docs/specs/c_accel_build_packaging.md."; \
exit 1; \
fi
$(MAKE) -C runtime/pb/c
# Remove built C-runtime artifacts.
clean-c:
rm -f runtime/pb/c_runtime.so runtime/pb/c_runtime.dylib
@if [ -d runtime/pb/c ]; then $(MAKE) -C runtime/pb/c clean; fi
# ---------------------------------------------------------------------------
# Codegen
# ---------------------------------------------------------------------------
# Regenerate examples/expected/{full,runtime}/* + conformance protos.
gen: gen-full gen-runtime gen-conformance gen-proto2-tests
# Generate full-mode Lua (inline encode/decode bodies).
gen-full: build
mkdir -p {{gen_dir}}
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=full,prefix=full \
-I {{proto_dir}} -I options \
{{proto_dir}}/*.proto
# Generate runtime-mode Lua (delegates to pb.encode / pb.decode).
gen-runtime: build
mkdir -p {{gen_dir}}
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=runtime,prefix=runtime \
-I {{proto_dir}} -I options \
{{proto_dir}}/*.proto
# Generate the Google conformance protos (TestAllTypesProto3) in both modes.
gen-conformance: build
mkdir -p {{gen_dir}}
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=full,prefix=full \
-I {{conformance_proto}} -I options \
{{conformance_proto}}/*.proto
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=runtime,prefix=runtime \
-I {{conformance_proto}} -I options \
{{conformance_proto}}/*.proto
# Generate the proto2 test fixtures (test/proto/*.proto) in both modes.
# Lives outside examples/ because proto2 is exercised through the luatest
# suite, not the per-example runners.
gen-proto2-tests: build
mkdir -p {{gen_dir}}
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=full,prefix=full \
-I {{proto2_test_dir}} -I options \
{{proto2_test_dir}}/*.proto
protoc \
--plugin=./{{plugin}} \
--tarantool_out={{gen_dir}} \
--tarantool_opt=mode=runtime,prefix=runtime \
-I {{proto2_test_dir}} -I options \
{{proto2_test_dir}}/*.proto
# Regenerate Markdown reference docs (examples/docs/*.md) — committed output.
gen-docs: build-doc
mkdir -p {{docs_dir}}
protoc \
--plugin=./{{doc_plugin}} \
--tarantool-doc_out={{docs_dir}} \
-I {{proto_dir}} -I options \
{{proto_dir}}/*.proto
# Regenerate test/interop/fixtures/*.bin via mainline `protoc --encode`.
goldens:
@for f in test/interop/fixtures/*.txtpb; do \
type=$(awk '/^# type:/ {print $3; exit}' "$f"); \
out="${f%.txtpb}.bin"; \
echo " protoc --encode=$type < $f > $out"; \
protoc --encode="$type" -I {{proto_dir}} -I options {{proto_dir}}/hello.proto < "$f" > "$out" || exit $?; \
done
# ---------------------------------------------------------------------------
# Test
# ---------------------------------------------------------------------------
# Run the luatest suite (639 tests, parametrized over both codegen modes).
test: gen
LUA_PATH="{{lua_path}}" LUA_CPATH="{{lua_cpath}}" {{luatest}} -v test/
# Run a single luatest group or test. Example:
# just test-one protobuf_test.lua::hello.full.test_packed_repeated_int32
test-one filter: gen
LUA_PATH="{{lua_path}}" LUA_CPATH="{{lua_cpath}}" {{luatest}} -v test/{{filter}}
# ---------------------------------------------------------------------------
# Bench
# ---------------------------------------------------------------------------
# Microbench: alloc + throughput per op across 5 payload sizes, both modes.
bench: gen
tarantool bench/bench.lua --print
# Overwrite bench/baseline.json with current alloc-per-op numbers.
bench-baseline: gen
tarantool bench/bench.lua --baseline
# Fail with exit 1 if any alloc-per-op regressed >5% vs the baseline.
bench-compare: gen
tarantool bench/bench.lua --compare
# Per-helper microbench for runtime/pb/wire.lua (every primitive).
bench-wire: gen
tarantool bench/wire_bench.lua
# Shape-variety microbench (scalar-heavy, packed, nested, maps, oneof, WKT).
bench-shapes: gen
tarantool bench/shapes_bench.lua
# Trace-stability gate: assert hot paths JIT-compile without fatal aborts.
jit-trace: gen
tarantool bench/jit_trace.lua
# Regenerate Go-side pb.go + vtproto pb.go in bench/go/pb/. Not committed
# (*.pb.go is gitignored repo-wide); run before `bench-go` on a fresh
# checkout. Requires `protoc-gen-go` and `protoc-gen-go-vtproto` on PATH:
# go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
# go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@latest
gen-go:
mkdir -p bench/go/pb/hellopb bench/go/pb/proto2pb
cd bench/go && PATH="$(go env GOPATH)/bin:$PATH" protoc \
--go_out=. --go_opt=module=github.com/tarantool-protobuf/bench/go \
--go-vtproto_out=. --go-vtproto_opt=module=github.com/tarantool-protobuf/bench/go \
--go-vtproto_opt=features=marshal+unmarshal+size \
-I proto proto/hello.proto proto/proto2_basic.proto
# Go-side comparison bench: same fixtures + sizes as bench.lua, run against
# google.golang.org/protobuf (apiv2) and planetscale/vtprotobuf. Serial by
# default — Go's testing.B doesn't parallelize unless RunParallel is called.
bench-go: gen-go
cd bench/go && go test -bench=. -benchmem -run=^$ -benchtime=1s ./...
# ---------------------------------------------------------------------------
# Conformance (Google's protobuf conformance suite, in Docker)
# ---------------------------------------------------------------------------
# Build the conformance Docker image (idempotent).
conformance-build:
docker build -t {{image}} -f docker/conformance.Dockerfile docker/
# Run the conformance suite with --enforce_recommended (strictest mode).
conformance: conformance-build gen
docker run --rm -v "$(pwd):/work" -w /work {{image}}
# Quick pass without --enforce_recommended.
conformance-quick: conformance-build gen
docker run --rm -v "$(pwd):/work" -w /work --entrypoint conformance_test_runner {{image}} \
--failure_list test/conformance/known_failures.txt \
--text_format_failure_list test/conformance/known_failures_text.txt \
/usr/bin/tarantool cmd/conformance-runner.lua
# Dump failing_tests.txt under test/conformance for triage.
conformance-refresh-failures: conformance-build gen
docker run --rm -v "$(pwd):/work" -w /work --entrypoint conformance_test_runner {{image}} \
--enforce_recommended \
--output_dir /work/test/conformance \
/usr/bin/tarantool cmd/conformance-runner.lua || true
@echo "Inspect test/conformance/*failing_tests.txt and update known_failures.txt as needed."
# Open an interactive shell in the conformance image.
conformance-shell: conformance-build
docker run --rm -it -v "$(pwd):/work" -w /work --entrypoint bash {{image}}
# ---------------------------------------------------------------------------
# Examples — see examples/Justfile for per-example runners
# ---------------------------------------------------------------------------
# Run an example. `just examples` lists per-example recipes.
examples *ARGS:
just -f examples/Justfile {{ARGS}}
# ---------------------------------------------------------------------------
# Clean
# ---------------------------------------------------------------------------
# Remove built plugin binaries and regenerated outputs.
clean: clean-c
rm -f {{plugin}} {{doc_plugin}}
rm -rf {{gen_dir}}
# Remove Tarantool instance state that leaked from running examples.
clean-state:
rm -f *.snap *.xlog *.vylog *.run *.pid 512.lock
rm -rf /tmp/tarantool-protobuf-*