# 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. # # `.dylib` is searched before `.so` because `package.searchpath` returns # the first existing file (not the first loadable one). If both exist # (e.g., a Linux `.so` left in the working tree by `just conformance-c`, # which builds inside the bind-mounted container), macOS dlopen would # fail on the foreign ELF without ever trying the local `.dylib`. Linux # never produces a `.dylib` so the order is harmless there. lua_cpath := "./runtime/?.dylib;./runtime/?.so;./runtime/?/init.dylib;./runtime/?/init.so;;" # --------------------------------------------------------------------------- # 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}} # Same as `conformance`, but exercises the C-acceleration path # (require('pb.c_runtime')). Builds runtime/pb/c_runtime.so inside the # container (host .dylib won't load there), then re-runs the suite with # PB_ENABLE_C=1 so pb/init.lua dispatches to the C codec. conformance-c: conformance-build gen docker run --rm -v "$(pwd):/work" -w /work -e PB_ENABLE_C=1 \ --entrypoint bash {{image}} -c '\ set -e; \ make -C runtime/pb/c clean >/dev/null; \ make -C runtime/pb/c >/dev/null; \ conformance_test_runner --enforce_recommended \ --failure_list test/conformance/known_failures.txt \ --text_format_failure_list test/conformance/known_failures_text.txt \ /usr/bin/tarantool cmd/conformance-runner.lua; \ rc=$?; \ make -C runtime/pb/c clean >/dev/null; \ exit $rc' # 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-*