Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@
- `./scripts/format.sh` / `clang-format -i` — format (`.clang-format`, 110 cols, Google base)
- Auth/tokens-only build (no LiveKit): `cmake -B build -S . -DDECART_BUILD_REALTIME=OFF`
(compiles out `Client::realtime()` via the `DECART_NO_REALTIME` interface define)
- Release: `scripts/release.sh X.Y.Z` (from `main`) bumps the version, tags, and
pushes; the Release workflow publishes the GitHub release on the tag.

## Versioning

The version lives in exactly one place — `project(decart VERSION ...)` in the
top-level CMakeLists.txt. `<decart/version.h>` is generated from `version.h.in`
via `configure_file`, so it can't drift from the release tag. Never hand-edit a
version number anywhere else.

## Architecture

Expand Down
14 changes: 13 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,17 @@ endif()
add_library(decart ${DECART_SOURCES})
add_library(decart::decart ALIAS decart)

# Single source of truth for the version: the project() VERSION above. Generate
# <decart/version.h> from it so headers can never drift from the release tag.
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/include/decart/version.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/generated/decart/version.h"
@ONLY)

target_include_directories(decart
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/generated>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src)
Expand Down Expand Up @@ -207,7 +215,11 @@ install(TARGETS decart
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# Public headers, excluding the .in template (the generated header is installed below).
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
PATTERN "*.in" EXCLUDE)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/generated/decart/version.h"
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/decart)

install(EXPORT decartTargets
FILE decartTargets.cmake
Expand Down
11 changes: 7 additions & 4 deletions include/decart/version.h → include/decart/version.h.in
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
// Copyright 2026 Decart. SPDX-License-Identifier: MIT
//
// Generated from version.h.in by CMake — do not edit. The version is the single
// source of truth in the top-level CMakeLists.txt `project(... VERSION ...)`.
#pragma once

#include <string>

/// Major version of the Decart C++ SDK.
#define DECART_SDK_VERSION_MAJOR 0
#define DECART_SDK_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
/// Minor version of the Decart C++ SDK.
#define DECART_SDK_VERSION_MINOR 1
#define DECART_SDK_VERSION_MINOR @PROJECT_VERSION_MINOR@
/// Patch version of the Decart C++ SDK.
#define DECART_SDK_VERSION_PATCH 0
#define DECART_SDK_VERSION_PATCH @PROJECT_VERSION_PATCH@
/// Full version string of the Decart C++ SDK.
#define DECART_SDK_VERSION "0.1.0"
#define DECART_SDK_VERSION "@PROJECT_VERSION@"

namespace decart {

Expand Down
66 changes: 66 additions & 0 deletions scripts/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
#
# Cut a release: bump the version (single source of truth in CMakeLists.txt),
# commit, tag, and push. The Release workflow then verifies the tag matches the
# project version and publishes the GitHub release.
#
# scripts/release.sh 0.2.0
#
set -euo pipefail
cd "$(dirname "$0")/.."

if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version> (e.g. $0 0.2.0)" >&2
exit 1
fi
new="$1"

if [[ ! "$new" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "error: version must be semver X.Y.Z (got '$new')" >&2
exit 1
fi

branch="$(git rev-parse --abbrev-ref HEAD)"
if [[ "$branch" != "main" ]]; then
echo "error: releases are cut from 'main' (on '$branch')" >&2
exit 1
fi
if [[ -n "$(git status --porcelain)" ]]; then
echo "error: working tree is not clean; commit or stash first" >&2
exit 1
fi

git pull --ff-only origin main

current="$(sed -n -E 's/^[[:space:]]*VERSION[[:space:]]+([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CMakeLists.txt | head -1)"
if [[ -z "$current" ]]; then
echo "error: could not find the project VERSION line in CMakeLists.txt" >&2
exit 1
fi
if [[ "$new" == "$current" ]]; then
echo "error: version is already $current" >&2
exit 1
fi

if git rev-parse -q --verify "refs/tags/v$new" >/dev/null; then
echo "error: tag v$new already exists" >&2
exit 1
fi

echo "Releasing v$new (was v$current)"

# Bump the version. CMakeLists.txt is the single source of truth (version.h is
# generated from it at build time); keep vcpkg.json's manifest version in lockstep
# so it can't drift from the release tag.
sed -i.bak -E "s/^([[:space:]]*VERSION[[:space:]]+)[0-9]+\.[0-9]+\.[0-9]+/\1$new/" CMakeLists.txt
sed -i.bak -E "s/(\"version\"[[:space:]]*:[[:space:]]*\")[0-9]+\.[0-9]+\.[0-9]+(\")/\1$new\2/" vcpkg.json
rm -f CMakeLists.txt.bak vcpkg.json.bak

git add CMakeLists.txt vcpkg.json
git commit -m "chore: release v$new"
git tag -a "v$new" -m "decart-cpp v$new"

git push origin main
git push origin "v$new"

echo "Pushed v$new — the Release workflow will publish the GitHub release."
Loading