This document describes how to build, download, and update the bundled C++ agent binaries in Criterium.
Criterium bundles pre-compiled native agent binaries in the JAR to enable zero-configuration usage. The agent provides allocation tracking capabilities through a JNI interface.
IMPORTANT: Agent binaries are NOT committed to version control. They are in .gitignore and must be downloaded from CI artifacts before building release JARs. This keeps the repository clean while still allowing binaries to be bundled in distributed artifacts.
Supported Platforms:
linux-x64 - 64-bit Linux (x86_64)macos-x64 - 64-bit macOS (Intel)macos-arm64 - macOS on Apple Silicon (M1/M2/M3)Future Platforms (Out of Scope):
linux-aarch64 - Deferred until CI infrastructure readyThe GitHub Actions workflow .github/workflows/agent-cpp.yml automatically builds agent binaries for all supported platforms whenever code is pushed to the repository.
Trigger Options:
workflow_dispatch with optional DEBUG build flagBuild Matrix:
ubuntu-latest → agent-cpp-linux-x64macos-latest → agent-cpp-macos-x64 and agent-cpp-macos-arm64The macOS job cross-compiles for both x86_64 and ARM64 architectures.
Each build produces an artifact containing the platform-specific shared library and its SHA256 hash:
libcriterium.so and libcriterium.so.sha256libcriterium.dylib and libcriterium.dylib.sha256 (for each architecture)The SHA256 hash files are used by the runtime extraction mechanism to generate unique filenames and verify binary integrity.
To download agent binaries from a CI run:
Navigate to the Actions tab in GitHub or use the CLI:
# List recent workflow runs
gh run list --workflow="agent-cpp.yml" --limit 5
# View details of a specific run
gh run view <run-id>
# Download Linux artifact
gh run download <run-id> -n agent-cpp-linux-x64
# Download macOS artifacts (both architectures)
gh run download <run-id> -n agent-cpp-macos-x64
gh run download <run-id> -n agent-cpp-macos-arm64
This creates directories named agent-cpp-linux-x64/, agent-cpp-macos-x64/, and agent-cpp-macos-arm64/ containing the respective binaries.
Move the downloaded binaries and hash files to the appropriate resource paths:
# Create resource directories if they don't exist
mkdir -p bases/agent/resources/native/linux-x64
mkdir -p bases/agent/resources/native/macos-x64
mkdir -p bases/agent/resources/native/macos-arm64
# Copy binaries and hash files to resource paths
cp agent-cpp-linux-x64/libcriterium.* bases/agent/resources/native/linux-x64/
cp agent-cpp-macos-x64/libcriterium.* bases/agent/resources/native/macos-x64/
cp agent-cpp-macos-arm64/libcriterium.* bases/agent/resources/native/macos-arm64/
Resource Path Convention:
bases/agent/resources/native/{platform}/libcriterium.{ext}
bases/agent/resources/native/{platform}/libcriterium.{ext}.sha256
Where:
{platform} is linux-x64, macos-x64, or macos-arm64{ext} is so (Linux) or dylib (macOS)After placing the binaries, test them locally:
# Run tests with the bundled agent
clojure -M:kaocha:dev:test --reporter dots
# Test specific agent functionality
clojure -M:dev
(require 'criterium.agent)
(criterium.agent/loaded?) ; Should return true
Use this checklist when updating agent binaries for a release:
[ ] Trigger CI Build:
[ ] Verify Build Success:
[ ] Download Artifacts:
agent-cpp-linux-x64, agent-cpp-macos-x64, and agent-cpp-macos-arm64 artifacts[ ] Place in Resources (Not Committed to Git):
bases/agent/resources/native/{platform}/.gitignore and should NOT be committed to version control[ ] Test Locally:
git status shows no binary files[ ] Build Release JAR:
clojure -M:build jar to build JAR with bundled binariesjar tf command[ ] Tag Release:
[ ] Document Changes:
For development with local agent modifications, build manually instead of using bundled binaries:
# Build agent locally (from agent-cpp/ directory)
cd agent-cpp
cmake -B build
cmake --build build
# Build with debug symbols
cmake -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build
# Use :with-agent-* aliases to load local build
clojure -M:dev:with-agent-mac # macOS
clojure -M:dev:with-agent-linux # Linux
The :with-agent-* aliases configure JVM to load the agent from the local agent-cpp/ build directory rather than using bundled binaries.
The current process is manual to reduce initial complexity. Future improvements may include:
Cross-Compilation:
The macOS build uses cross-compilation to produce both x86_64 and ARM64 binaries from a single runner. CMake uses the CMAKE_OSX_ARCHITECTURES variable to specify the target architecture:
# Build for specific architecture
cmake -B build -DCMAKE_OSX_ARCHITECTURES=x86_64 # Intel Macs
cmake --build build
cmake -B build -DCMAKE_OSX_ARCHITECTURES=arm64 # Apple Silicon
cmake --build build
Binary Size: Typical agent binary is ~200KB per platform. Total JAR size increase is acceptable for zero-configuration convenience.
Version-Specific Paths: Runtime extraction uses version-specific temporary paths to prevent collisions when multiple JAR versions are on the classpath.
Artifact not found:
Binary won't load:
Test failures after update:
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |