Skip to content

Buildspy in CI — exit codes & gating

When a C/C++ project has no compile_commands.json, Buildspy captures the exact include paths and macros by watching your build — ideal for headless/CI setups. This page covers running it in a pipeline and, importantly, how to gate correctly on exit codes. For the GUI alternative and the full Buildspy usage, see Capture your build — Build Watcher vs Buildspy.

Using CMake? Skip Buildspy

Prefer compile_commands.json — it captures the same information cleanly and stays in sync. Reach for Buildspy only when you can't produce one.

Capture in the pipeline

Buildspy either runs your build for you (-cmd) or is fed by the gccwrapper/g++wrapper compiler wrappers. In CI, -cmd is usually simplest:

buildspy -db project.und -cmd "make <target>"
  • Start from a clean build (make clean) so every translation unit is seen.
  • Buildspy forwards the build's stdout/stderr, so build output still appears in the CI log.
  • After capture, the project's files, includes, and macros are set — you still need to analyze: und -db project.und analyze.

Exit codes — read this before you gate

Buildspy's exit code does NOT mean 'the build passed' or 'analysis is clean'

Buildspy returns a non-zero (1) exit code only for its own setup failures — a missing/invalid -db or -cmd, a database it can't open, or a build command that fails to start. On a build it successfully watched, Buildspy exits 0 regardless of whether the compilation itself succeeded or failed. It does not propagate your build tool's exit status.

Because of that, structure the gate in stages and let each stage own its own failure:

Gate on Do this Notes
The build compiling Run the build (or buildspy -cmd …) and check the build tool's exit code Buildspy won't fail for you if make fails. Run make directly to gate, or verify make's status separately.
A usable project und -db project.und analyze and inspect the log for parse errors Analyze surfaces errors; decide your own threshold.
Coding-standard violations und -db project.und codecheck -exitstatus … Exit code = violation count → non-zero fails the step. See Run from the command line.
#!/bin/bash -x
set -o pipefail

# Gate the compile on the BUILD TOOL, not on buildspy:
make clean
buildspy -db project.und -cmd "make app" || { echo "buildspy setup failed"; exit 1; }
# buildspy exited 0 even if 'make app' failed — verify the build separately if you need that gate.

und -db project.und analyze
und -db project.und codecheck -exitstatus -sarif out/results.sarif "MyConfig" out   # non-zero == violations

Wire this capture step into the larger end-to-end pipeline.

Compiler selection

gccwrapper calls gcc and g++wrapper calls g++ by default. For a different compiler, pass -cc/-cxx (or set UND_PBCCCOMPILER / UND_PBCXXCOMPILER). The wrappers work with any compiler that takes gcc-like arguments.