Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
153bda4
bridge-cpp: commit C ABI header and baml-cpp tarball packaging
codeshaunted Jul 13, 2026
cb1a691
bridge-cpp: pin smoke test to C++11, the minimum supported standard
codeshaunted Jul 13, 2026
b44a790
bridge-cpp: revise minimum supported standard to C++17
codeshaunted Jul 13, 2026
7f2bdcf
bridge-cpp: build the cdylib with panic=unwind (release-bridge-cffi p…
codeshaunted Jul 13, 2026
8b2826b
bridge-cpp: wire baml-cpp tarballs into the nightly release graph
codeshaunted Jul 13, 2026
0b3154c
bridge-cpp: align release wiring with the bridge release contract
codeshaunted Jul 13, 2026
bd30566
bridge-cpp: header-only bridge core (buffer, errors, Arg, call regist…
codeshaunted Jul 13, 2026
31517c1
bridge-cpp: unify null with the std vocabulary
codeshaunted Jul 13, 2026
ec25dd6
bridge-cpp: accept baml::Null{} as explicit null in Arg<T>
codeshaunted Jul 13, 2026
342dc91
bridge-cpp: rework Arg<T> to two-state over the argument's normalized…
codeshaunted Jul 13, 2026
e809e9a
bridge-cpp: sdk_test_cpp harness scaffolding (instructions step 1 gro…
codeshaunted Jul 14, 2026
50af31f
bridge-cpp: wire codec + call driver; first end-to-end BAML calls fro…
codeshaunted Jul 14, 2026
6994257
bridge-cpp: sdkgen_cpp slice 1 - free functions with basic types, end…
codeshaunted Jul 14, 2026
430278a
bridge-cpp: sdkgen_cpp slice 2 - classes and enums with generated codecs
codeshaunted Jul 14, 2026
876bbf9
bridge-cpp: multi-member union codec + five more roundtrip test ports
codeshaunted Jul 14, 2026
8150695
bridge-cpp: sdkgen_cpp slice 3 - methods and optional arguments (opts…
codeshaunted Jul 14, 2026
942327b
bridge-cpp: typed error accessors + error/raises test ports
codeshaunted Jul 14, 2026
8882318
bridge-cpp: transparent type aliases + void/routing test ports
codeshaunted Jul 14, 2026
5d2a1a5
bridge-cpp: doc rollups + unions/cancellation/docstrings/main test ports
codeshaunted Jul 14, 2026
3432482
bridge-cpp: recursion via baml::Box + cycle-breaking emitter pass
codeshaunted Jul 14, 2026
5bded10
bridge-cpp: generics emitter - class/function templates, ty<T>, type_…
codeshaunted Jul 14, 2026
0b08ab7
bridge-cpp: generics + complex-model parity ports (58 new cases)
codeshaunted Jul 14, 2026
b5786ec
bridge-cpp: typed naming layer (Go reference architecture)
codeshaunted Jul 14, 2026
16f4026
bridge-cpp: bytecode-init C ABI export, CI sdk-test matrix, harness r…
codeshaunted Jul 14, 2026
1dbcbab
bridge-cpp: generated SDKs boot from embedded bytecode
codeshaunted Jul 14, 2026
7b8ad2c
bridge-cpp: emit stdlib (baml.*) types + entry points
codeshaunted Jul 14, 2026
7253aab
bridge-cpp: host callables (std::function across the boundary)
codeshaunted Jul 14, 2026
ef7ab9f
bridge-cpp: emit $stream companion classes under stream_types::
codeshaunted Jul 14, 2026
8592a64
bridge-cpp: handles + bigint (unlocks fs/http/time stdlib surface)
codeshaunted Jul 14, 2026
2a12edd
bridge-cpp: media types via the stdlib media classes
codeshaunted Jul 14, 2026
3827c04
bridge-cpp: streaming + function companions (llm_functions e2e)
codeshaunted Jul 14, 2026
87b1454
bridge-cpp: recursive type aliases + full Python test parity
codeshaunted Jul 14, 2026
01ede20
bridge-cpp: adopt Google C++ style (.h/.cc, PascalCase API)
codeshaunted Jul 14, 2026
06f0343
bridge-cpp: restore .markdown-whitelist section structure
codeshaunted Jul 14, 2026
49608b6
bridge-cpp: enforce clang-format through prek
codeshaunted Jul 14, 2026
3085ecb
bridge-cpp: drop the baml::Null alias
codeshaunted Jul 15, 2026
e28a260
bridge-cpp: hash-valued enumerators (reorder-stable ordinals)
codeshaunted Jul 15, 2026
6f92f66
bridge-cpp: canonical union alternative order + order-independent decode
codeshaunted Jul 15, 2026
8fb136a
bridge-cpp: opts structs keep the function's verbatim spelling
codeshaunted Jul 15, 2026
1ccd216
Merge origin/canary into avery/bridge-cpp (BamlApiV1 table + CFFI dyl…
codeshaunted Jul 15, 2026
0549d31
bridge-cpp: switch to dlopen + BamlApiV1 table (contract compliance)
codeshaunted Jul 15, 2026
0115985
bridge-cpp: kill the tarball -- generate is self-contained, CI verify…
codeshaunted Jul 15, 2026
12a4c40
bridge-cpp: teardown-safe singletons + no unwind across the C ABI
codeshaunted Jul 15, 2026
1d12578
bridge-cpp: embed bytecode as chunked string literals (protobuf-style)
codeshaunted Jul 15, 2026
e477516
bridge-cpp: round-trip test for the OptionalBox<RecList> pin
codeshaunted Jul 15, 2026
a4dada4
bridge-cpp: disable multi-member unions pending redesign
codeshaunted Jul 15, 2026
9c181b9
bridge-cpp: slim to the step-8 feature set (packaging slice)
codeshaunted Jul 16, 2026
f4cec6a
bridge-cpp: BAML maps land as std::unordered_map
codeshaunted Jul 16, 2026
121f707
bridge-cpp: emit using declarations for non-recursive aliases
codeshaunted Jul 16, 2026
800923a
Merge origin/canary: generated V1 C ABI + canonical codegen types
codeshaunted Jul 16, 2026
35058f7
bridge-cpp: simplification pass (dev source-init, companions, naming)
codeshaunted Jul 16, 2026
4484f84
bridge-cpp: apply vestigial-code findings from the cleanup sweep
codeshaunted Jul 16, 2026
29c06a9
Merge remote-tracking branch 'origin/canary' into avery/bridge-cpp
codeshaunted Jul 16, 2026
8abc320
bridge-cpp: emit a CMakeLists.txt into generated baml_sdk trees
codeshaunted Jul 16, 2026
f5b7c08
bridge-cpp: wire cpp into baml-cli generate
codeshaunted Jul 16, 2026
7e9cdec
bridge-cpp: add -pthread/-ldl to the README raw-compile example
codeshaunted Jul 16, 2026
1b916aa
bridge-cpp: name the wire field numbers
codeshaunted Jul 16, 2026
10f12ad
bridge-cpp: replace the hand-rolled wire layer with pinned protobuf-lite
codeshaunted Jul 16, 2026
c81164d
Merge remote-tracking branch 'origin/canary' into avery/bridge-cpp
codeshaunted Jul 17, 2026
f698ae9
Merge remote-tracking branch 'origin/canary' into avery/bridge-cpp
codeshaunted Jul 17, 2026
403b793
bridge-cpp: fix CI fallout from the protobuf migration
codeshaunted Jul 17, 2026
0e0b276
bridge-cpp: fix pb_generation test on Windows
codeshaunted Jul 17, 2026
60379eb
bridge-cpp: close the parity-audit assertion gaps vs the python tests
codeshaunted Jul 17, 2026
ba25a7d
bridge-cpp: address review findings on the protobuf migration
codeshaunted Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/cargo-tests.reusable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,21 @@ jobs:
"rust-cache-key": "linux-cargo",
"timeout": 30,
},
{
// The C++ sdk-test crate needs the host C++ toolchain and
// CMake (preinstalled on the runners) plus nextest; its
// setup.sh builds the bridge_cffi cdylib with cargo and
// pre-clones the pinned protobuf sources. Windows joins
// once the MSVC test driver lands (test.sh is bash).
"sdk-label": "cpp",
"package-name": "sdk_test_cpp",
"sdk-path": "cpp",
"install-args": "sccache direnv cargo:cargo-nextest",
"os-label": "linux",
"runs-on": "blacksmith-16vcpu-ubuntu-2404",
"rust-cache-key": "linux-cargo",
"timeout": 30,
},
{
"sdk-label": "rust",
"package-name": "sdk_test_rust",
Expand All @@ -432,6 +447,16 @@ jobs:
"rust-cache-key": "macos-cargo",
"timeout": 40,
},
{
"sdk-label": "cpp",
"package-name": "sdk_test_cpp",
"sdk-path": "cpp",
"install-args": "sccache direnv cargo:cargo-nextest",
"os-label": "macos",
"runs-on": "blacksmith-6vcpu-macos-latest",
"rust-cache-key": "macos-cargo",
"timeout": 40,
},
{
"sdk-label": "typescript",
"package-name": "sdk_test_typescript",
Expand Down
13 changes: 13 additions & 0 deletions .github/workflows/release-baml-language.yml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,18 @@ jobs:
release_plan_json: ${{ needs.plan.outputs.release_plan_json }}
source_sha: ${{ needs.plan.outputs.source_sha }}

# Verify-only: the C++ SDK ships no artifact (headers are vendored at
# generate time); it consumes the shared bridge_cffi artifacts.
verify-cpp-sdk:
name: Verify C++ SDK
needs: [plan, build-bridge-cffi]
uses: ./.github/workflows/verify-cpp-sdk.reusable.yaml
permissions:
contents: read
with:
release_plan_json: ${{ needs.plan.outputs.release_plan_json }}
source_sha: ${{ needs.plan.outputs.source_sha }}

build-rust-sdk:
name: Build Rust SDK
needs: [plan]
Expand Down Expand Up @@ -430,6 +442,7 @@ jobs:
# The engine cdylib is required — it is the shared artifact every
# dylib-loader SDK depends on.
- build-bridge-cffi
- verify-cpp-sdk
# The Rust SDK is production-ready (crates.io publisher live), so its
# build + consumer verification gate the release: a failure here blocks
# publishing rather than shipping a release the Rust SDK isn't part of.
Expand Down
164 changes: 164 additions & 0 deletions .github/workflows/verify-cpp-sdk.reusable.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
name: BAML SDK Release - Verify C++

# The C++ SDK ships no artifact of its own: `baml-cli generate` vendors the
# bridge headers into the generated source tree, and the runtime library is
# the shared language-neutral `bridge_cffi` cdylib built once by
# build2-bridge-cffi.reusable.yaml (invariant: language jobs consume shared
# artifacts, never rebuild private runtimes).
#
# This workflow is therefore verify-only: for every supported target it
# downloads the final `bridge-cffi-<target>` artifact, renames it to the
# canonical loader filename, compiles the in-repo bridge consumer smoke
# (runtime_smoke.cc via CMake: load via BAML_RUNTIME_PATH, ABI-table
# validation, register_bridge, bytecode-init error surface, decode over the
# pinned protobuf-lite runtime), runs it against the
# artifact, and asserts the canonical version. musl runs inside a real
# Alpine userspace; Windows compiles with MSVC.

on:
workflow_call:
inputs:
release_plan_json:
description: "Frozen BAML language release-plan.json content"
type: string
required: true
source_sha:
description: "Exact repository commit to build"
type: string
required: true

concurrency:
# suffix is important to prevent a concurrency deadlock with the calling workflow
group: ${{ github.workflow }}-${{ github.ref }}-verify-cpp-sdk
cancel-in-progress: true

defaults:
run:
shell: bash

jobs:
# Matrices are derived from the repository-owned platform contract so the
# target list is not another copied YAML matrix (bridge-release-contract.md).
platform-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.derive.outputs.matrix }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.source_sha }}
persist-credentials: false
sparse-checkout: release
- id: derive
run: |
set -euo pipefail
# Every target with a cffi artifact gets consumer-verified. The
# verify runner must be NATIVE for the triple (the cffi build may
# cross-compile; a consumer smoke cannot), so it is derived from
# os/arch rather than reusing the build runner.
matrix="$(jq -c '{include: [.targets[]
| select(.artifacts.cffi != null)
| {target: .triple,
libc: .libc,
runner: (if .os == "macos" then (if .arch == "aarch64" then "macos-14" else "macos-15-intel" end)
elif .os == "linux" then (if .arch == "aarch64" then "ubuntu-24.04-arm" else "ubuntu-latest" end)
else (if .arch == "aarch64" then "windows-11-arm" else "windows-2022" end) end),
smoke_container: (if .libc == "musl" then "alpine:3.21" else null end),
msvc_arch: (if .arch == "aarch64" then "arm64" else "amd64" end)}]}' release/platforms.json)"
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"

verify:
needs: platform-matrix
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.platform-matrix.outputs.matrix) }}
name: verify ${{ matrix.target }}
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.source_sha }}
persist-credentials: false

- uses: actions/download-artifact@v4
with:
name: bridge-cffi-${{ matrix.target }}
path: runtime-dist

- name: Resolve expected version
env:
RELEASE_PLAN_JSON: ${{ inputs.release_plan_json }}
run: |
set -euo pipefail
printf '%s\n' "$RELEASE_PLAN_JSON" > release-plan.json
expected="$(jq -r .canonical_version release-plan.json)"
echo "BAML_EXPECTED_VERSION=$expected" >> "$GITHUB_ENV"

- name: Verify checksum and stage canonical filename
run: |
set -euo pipefail
cd runtime-dist
if command -v sha256sum > /dev/null; then
sha256sum -c ./*.sha256
else
shasum -a 256 -c ./*.sha256
fi
# The release asset carries the loader's triple-suffixed name;
# stage it under the canonical filename the C++ contract uses.
case '${{ matrix.target }}' in
*apple*) canonical="libbridge_cffi.dylib" ;;
*windows*) canonical="bridge_cffi.dll" ;;
*) canonical="libbridge_cffi.so" ;;
esac
shopt -s nullglob
for lib in libbaml_cffi-*.so libbaml_cffi-*.dylib baml_cffi-*.dll; do
cp "$lib" "$canonical"
done
test -f "$canonical"
echo "BAML_RUNTIME_PATH=$PWD/$canonical" >> "$GITHUB_ENV"

- name: Consumer smoke (unix)
if: matrix.libc != 'musl' && !contains(matrix.target, 'windows')
run: |
set -euo pipefail
cmake -S baml_language/sdks/cpp/bridge_cpp/tests -B smoke-build
cmake --build smoke-build -j
out="$(./smoke-build/runtime_smoke)"
echo "$out"
echo "$out" | grep -qx "version: $BAML_EXPECTED_VERSION"

- name: Consumer smoke (musl container)
if: matrix.libc == 'musl'
run: |
set -euo pipefail
docker run --rm -v "$PWD:/work" -w /work \
-e BAML_RUNTIME_PATH=/work/runtime-dist/libbridge_cffi.so \
-e BAML_EXPECTED_VERSION \
${{ matrix.smoke_container }} \
sh -c 'apk add --no-cache bash g++ cmake make git linux-headers && \
cmake -S baml_language/sdks/cpp/bridge_cpp/tests -B smoke-build && \
cmake --build smoke-build -j && \
out="$(./smoke-build/runtime_smoke)" && echo "$out" && \
echo "$out" | grep -qx "version: $BAML_EXPECTED_VERSION"'

- name: Consumer smoke (windows)
if: contains(matrix.target, 'windows')
shell: pwsh
run: |
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vsPath = & $vswhere -latest -products * -property installationPath
if (-not $vsPath) { throw "no Visual Studio installation found via vswhere" }
Import-Module (Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll")
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation `
-DevCmdArguments "-arch=${{ matrix.msvc_arch }} -host_arch=${{ matrix.msvc_arch }}"
cmake -S baml_language\sdks\cpp\bridge_cpp\tests -B smoke-build
if ($LASTEXITCODE -ne 0) { throw "cmake configure failed" }
# Debug config: the smoke asserts must stay compiled in (NDEBUG off).
cmake --build smoke-build -j --config Debug
if ($LASTEXITCODE -ne 0) { throw "cmake build failed" }
$out = & .\smoke-build\Debug\runtime_smoke.exe
if ($LASTEXITCODE -ne 0) { throw "runtime_smoke exited with $LASTEXITCODE" }
Write-Output $out
if (-not ($out -contains "version: $env:BAML_EXPECTED_VERSION")) {
throw "expected version $env:BAML_EXPECTED_VERSION not reported"
}
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ repos:
files: ^baml_language/
priority: 2

- id: clang-format-cpp
name: clang-format (C++ SDK)
entry: bash -c 'cd baml_language && mise run fmt-cpp'
language: system
pass_filenames: false
files: ^baml_language/(sdks/cpp/|sdk_tests/crates/cpp/).*\.(h|cc)$
priority: 2

- id: cargo-stow
name: cargo stow
entry: bash -c 'cd baml_language && mise run stow'
Expand Down
19 changes: 19 additions & 0 deletions baml_language/.config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,22 @@ setup = 'python_pydantic2_uv_unix'
filter = 'package(=sdk_test_python_pydantic2)'
platform = { host = 'cfg(windows)' }
setup = 'python_pydantic2_uv_win'

# cpp tests link the dev-profile bridge_cffi cdylib; build it once. fire only
# when a cpp sdk-test is selected. setup.sh / setup.ps1 are byte-for-byte
# equivalent — same cargo build in the host shell of each platform.
[scripts.setup.cpp_cdylib_unix]
command = './sdk_tests/crates/cpp/setup.sh'

[scripts.setup.cpp_cdylib_win]
command = ['powershell', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', './sdk_tests/crates/cpp/setup.ps1']

[[profile.default.scripts]]
filter = 'package(=sdk_test_cpp)'
platform = { host = 'cfg(unix)' }
setup = 'cpp_cdylib_unix'

[[profile.default.scripts]]
filter = 'package(=sdk_test_cpp)'
platform = { host = 'cfg(windows)' }
setup = 'cpp_cdylib_win'
3 changes: 3 additions & 0 deletions baml_language/.markdown-whitelist
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ TASK/REVIEW.md
TASK/REVIEW-RESPONSE.md
TASK/POST-IMPLEMENTATION-NOTES.md
TASK/RECONCILIATION.md

# C++ SDK style guide
sdks/cpp/STYLE.md
22 changes: 22 additions & 0 deletions baml_language/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions baml_language/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
members = [
"crates/*",
"forks/*",
"sdks/cpp/sdkgen_cpp",
"sdks/go/sdkgen_go",
"sdks/typescript/bridge_typescript",
"sdks/typescript/bridge_typescript_web",
Expand All @@ -11,6 +12,7 @@ members = [
"sdk_tests/harness_setup",
"sdk_tests/harness_runner",
"sdk_tests/harness/llm_recordings",
"sdk_tests/crates/cpp",
"sdk_tests/crates/python_pydantic2",
# `sdk_tests/crates/typescript`'s build.rs runs codegen +
# `pnpm install` but soft-fails into `$OUT_DIR/build_diagnostics.txt`
Expand Down Expand Up @@ -63,6 +65,7 @@ baml_type_runtime = { path = "crates/baml_type_runtime" }
baml_type_macros = { path = "crates/baml_type_macros" }
baml_builtins2 = { path = "crates/baml_builtins2" }
baml_builtins2_codegen = { path = "crates/baml_builtins2_codegen" }
sdkgen_cpp = { path = "sdks/cpp/sdkgen_cpp" }
sdkgen_typescript_shared = { path = "sdks/typescript/sdkgen_typescript_shared" }
sdkgen_python_pydantic2 = { path = "sdks/python/rust/sdkgen_python_pydantic2" }
sdkgen_rust = { path = "sdks/rust/sdkgen_rust" }
Expand Down
1 change: 1 addition & 0 deletions baml_language/crates/baml_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ baml_workspace = { workspace = true }
bex_cache = { workspace = true }
bex_engine = { workspace = true }
bex_vm_types = { workspace = true }
sdkgen_cpp = { workspace = true }
sdkgen_python_pydantic2 = { workspace = true }
sdkgen_rust = { workspace = true }
sdkgen_typescript_shared = { workspace = true }
Expand Down
17 changes: 16 additions & 1 deletion baml_language/crates/baml_cli/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ impl GenerateArgs {
.map(|(path, content)| (path, content.into_bytes()))
.collect()
}
OutputType::Cpp => {
// The C++ emitter embeds source paths (reference
// comments only); the runtime payload is the bytecode.
let source_paths: Vec<PathBuf> = source_files
.iter()
.map(|sf| {
let path = sf.path(&db);
path.strip_prefix(&from).unwrap_or(&path).to_path_buf()
})
.collect();
sdkgen_cpp::to_source_code_with_bytecode(&pool, &source_paths, &baml_bytecode)
.into_iter()
.map(|(path, content)| (path, content.into_bytes()))
.collect()
}
};

std::fs::create_dir_all(&output_dir).with_context(|| {
Expand Down Expand Up @@ -301,7 +316,7 @@ fn discover_generators(root: &Path) -> (Vec<GeneratorDef>, Vec<Diagnostic>) {
name,
"output_type",
generator.output_type.as_ref(),
r#"one of: "python/pydantic", "python/pydantic/v1", "typescript/node", "typescript/web", "rust""#,
r#"one of: "python/pydantic", "python/pydantic/v1", "typescript/node", "typescript/web", "rust", "cpp""#,
table_range,
&mut diags,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub enum OutputType {
/// TypeScript + Web/WASM SDK (`@boundaryml/baml-bridge-web` runtime).
#[strum(serialize = "typescript/web")]
TypescriptWeb,
/// C++17 SDK (self-contained source tree; dlopens the shared runtime).
#[strum(serialize = "cpp")]
Cpp,
}

/// Identifier-casing policy a code generator must respect. Surfaces as
Expand Down
Loading
Loading