diff --git a/book/src/build/cmake.md b/book/src/build/cmake.md new file mode 100644 index 0000000..1167ad1 --- /dev/null +++ b/book/src/build/cmake.md @@ -0,0 +1,171 @@ +# Build with CMake + +`a2a-cpp` is a C++20 SDK built and packaged with CMake. The project can be used directly from source with `FetchContent`, installed into a CMake package prefix, or built with dependencies supplied by vcpkg. + +## Requirements + +- CMake 3.25 or newer. +- A C++20 compiler. +- Protobuf and gRPC development packages. +- Optional: libcurl for the default buffered outbound HTTP implementation. +- Optional: PostgreSQL client libraries when `A2A_ENABLE_POSTGRES_STORE=ON`. + +On Ubuntu-like systems, the repository helper installs the dependencies used by CI: + +```bash +./scripts/install_build_deps.sh +``` + +On macOS, install equivalent packages with Homebrew: + +```bash +brew install cmake ninja protobuf grpc re2 abseil curl +``` + +## Configure from source + +The default source build enables tests, keeps the curated example apps out of the top-level build, and enables libcurl-backed HTTP support when CMake can find `CURL::libcurl`. + +```bash +cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=Debug \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DA2A_ENABLE_TESTING=ON +``` + +When dependencies are installed outside standard search paths, pass a CMake prefix path: + +```bash +cmake -S . -B build \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DCMAKE_PREFIX_PATH="/opt/homebrew;/opt/homebrew/opt/curl" +``` + +## Build and test + +```bash +cmake --build build --parallel +ctest --test-dir build --output-on-failure +``` + +For the repository's full local code validation flow, run: + +```bash +./scripts/verify_changes.sh +``` + +That script runs the same main gates expected before a code PR: formatting, configure/build, tests, and clang-tidy. + +## CMake options + +| Option | Default | Description | +| --- | --- | --- | +| `A2A_ENABLE_TESTING` | `ON` | Builds unit and integration tests and enables CTest. | +| `A2A_BUILD_EXAMPLES` | `ON` | Compatibility/message-only option for the root build today; curated examples are built as standalone consumers from `examples/fetch_content_consumer` or `examples/installed_package_consumer`. | +| `A2A_BUILD_BENCHMARKS` | `OFF` | Builds benchmark targets under `benchmarks/`. | +| `A2A_ENABLE_LIBCURL` | `ON` | Enables the default libcurl-backed outbound HTTP implementation when libcurl is found. Disable it to require injected requesters/fetchers. | +| `A2A_ENABLE_POSTGRES_STORE` | `OFF` | Builds PostgreSQL-backed store targets when PostgreSQL dependencies are available. | + +## Generated protobuf headers + +The SDK generates A2A protocol C++ sources during the build. Primary generated A2A headers are written under `build/generated/a2a/v1/`, and generated Google API annotation headers are written under `build/generated/google/api/`. + +Those generated headers are installed with the SDK, so downstream projects should include headers from the installed package rather than copying build-tree generated files. + +## Install as a CMake package + +Install the SDK to a prefix: + +```bash +cmake --install build --prefix /tmp/a2a-cpp-install +``` + +The install tree includes public headers, generated protobuf headers, libraries, and package configuration files under `lib/cmake/a2a_cpp`. + +A downstream project can then consume the installed package: + +```cmake +cmake_minimum_required(VERSION 3.25) +project(my_a2a_app LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +find_package(a2a_cpp CONFIG REQUIRED) + +add_executable(my_a2a_app main.cpp) +target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core) +``` + +Configure that downstream project with `CMAKE_PREFIX_PATH` pointing at the install prefix: + +```bash +cmake -S path/to/app -B build-app \ + -DCMAKE_PREFIX_PATH=/tmp/a2a-cpp-install +cmake --build build-app --parallel +``` + +## FetchContent consumer + +For application projects that prefer source integration, use CMake `FetchContent` and pin `GIT_TAG` to a release tag or reviewed commit: + +```cmake +include(FetchContent) + +set(A2A_ENABLE_TESTING OFF CACHE BOOL "" FORCE) +set(A2A_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(A2A_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE) +set(A2A_ENABLE_POSTGRES_STORE OFF CACHE BOOL "" FORCE) + +FetchContent_Declare( + a2a_cpp + GIT_REPOSITORY https://github.com/MisterVVP/a2a-cpp.git + GIT_TAG v0.2.0 +) +FetchContent_MakeAvailable(a2a_cpp) + +target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core) +``` + +See `examples/fetch_content_consumer/` for a minimal runnable consumer. + +## Exported targets + +Common exported targets include: + +- `a2a::core` for shared core types and utilities. +- `a2a::client` for client APIs. +- `a2a::server` for server APIs. +- `a2a::http` for HTTP support internals used by higher-level targets. +- `a2a::proto_generated` for generated protobuf bindings. +- `a2a::store_postgres` when PostgreSQL store support is enabled. + +Most applications should link the smallest set they use. The examples link `a2a::client`, `a2a::server`, and `a2a::core` for a combined client/server sample. + +## Build the curated examples + +Use the FetchContent example when testing source consumption: + +```bash +cmake -S examples/fetch_content_consumer -B build-example \ + -DA2A_EXAMPLE_APP=hello_agent +cmake --build build-example --parallel +./build-example/a2a_example +``` + +Use the installed-package example when testing package consumption: + +```bash +cmake -S examples/installed_package_consumer -B build-installed-example \ + -DCMAKE_PREFIX_PATH=/tmp/a2a-cpp-install \ + -DA2A_EXAMPLE_APP=hello_agent +cmake --build build-installed-example --parallel +./build-installed-example/a2a_example +``` + +## Platform notes + +- Linux CI configures with CMake and validates build, tests, examples, clang-format, clang-tidy, coverage, and selected sanitizer/interop flows. +- macOS CI builds with Homebrew-provided dependencies and Ninja. +- Windows CI uses vcpkg manifest dependencies and the Visual Studio 2022 generator. See [vcpkg](vcpkg.md) for manifest, triplet, and overlay details. diff --git a/book/src/build/vcpkg.md b/book/src/build/vcpkg.md new file mode 100644 index 0000000..f7c35d2 --- /dev/null +++ b/book/src/build/vcpkg.md @@ -0,0 +1,184 @@ +# Build with vcpkg + +`a2a-cpp` provides vcpkg metadata for two related workflows: + +1. **Manifest dependency mode** for building this repository with vcpkg-supplied third-party dependencies. +2. **Overlay port mode** for consuming `a2a-cpp` itself as a vcpkg package before it is available from a public registry. + +The repository root `vcpkg.json` pins the dependency baseline and declares the SDK's third-party dependencies: protobuf, gRPC, and curl. + +## Prerequisites + +Install or clone vcpkg and bootstrap it: + +```bash +git clone https://github.com/microsoft/vcpkg.git "$HOME/vcpkg" +"$HOME/vcpkg/bootstrap-vcpkg.sh" +``` + +On Windows PowerShell: + +```powershell +git clone https://github.com/microsoft/vcpkg.git C:\vcpkg +C:\vcpkg\bootstrap-vcpkg.bat +``` + +Set `VCPKG_ROOT` for convenience: + +```bash +export VCPKG_ROOT="$HOME/vcpkg" +``` + +```powershell +$env:VCPKG_ROOT = 'C:\vcpkg' +``` + +## Build this repository with manifest dependencies + +From the repository root, let vcpkg install the manifest dependencies and then configure CMake with the vcpkg toolchain file: + +```bash +"$VCPKG_ROOT/vcpkg" install +cmake -S . -B build-vcpkg \ + -DVCPKG_MANIFEST_MODE=ON \ + -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DA2A_ENABLE_TESTING=ON +cmake --build build-vcpkg --parallel +ctest --test-dir build-vcpkg --output-on-failure +``` + +On multi-config generators such as Visual Studio, pass the configuration during build and test: + +```powershell +& "$env:VCPKG_ROOT\vcpkg.exe" install +cmake -S . -B build-vcpkg -G "Visual Studio 17 2022" -A x64 ` + -DVCPKG_MANIFEST_MODE=ON ` + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" +cmake --build build-vcpkg --config RelWithDebInfo --parallel +ctest --test-dir build-vcpkg -C RelWithDebInfo --output-on-failure +``` + +## Use a specific triplet + +Pass the same target triplet to vcpkg and CMake. For native builds, use the same value for the host triplet so host tools such as `protoc` and `grpc_cpp_plugin` are resolved consistently: + +```bash +"$VCPKG_ROOT/vcpkg" install --triplet x64-linux --host-triplet x64-linux +cmake -S . -B build-vcpkg \ + -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \ + -DVCPKG_TARGET_TRIPLET=x64-linux \ + -DVCPKG_HOST_TRIPLET=x64-linux +``` + +Windows CI uses the repository triplet `triplets/ci-x64-windows-release.cmake` to build release-only dependencies and reduce dependency build time: + +```powershell +$env:VCPKG_OVERLAY_TRIPLETS = "$PWD\triplets" +& "$env:VCPKG_ROOT\vcpkg.exe" install --triplet ci-x64-windows-release --host-triplet ci-x64-windows-release +cmake -S . -B build -G "Visual Studio 17 2022" -A x64 ` + -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" ` + -DVCPKG_TARGET_TRIPLET=ci-x64-windows-release ` + -DVCPKG_HOST_TRIPLET=ci-x64-windows-release +``` + +## Consume `a2a-cpp` through the repository overlay port + +The repository includes an overlay port at `vcpkg-overlay-ports/a2a-cpp`. A downstream manifest can depend on `a2a-cpp` and point vcpkg at that overlay. + +`vcpkg.json`: + +```json +{ + "name": "my-a2a-app", + "version-string": "0.2.0", + "dependencies": [ + "a2a-cpp" + ] +} +``` + +`vcpkg-configuration.json`: + +```json +{ + "default-registry": { + "kind": "builtin", + "baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc" + }, + "overlay-ports": [ + "path/to/a2a-cpp/vcpkg-overlay-ports" + ] +} +``` + +Then configure the application with the vcpkg toolchain file on the first CMake configure and use the installed CMake package: + +```cmake +find_package(a2a_cpp CONFIG REQUIRED) +target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core) +``` + +A complete example is available in `examples/installed_package_consumer/`. + +## Enable PostgreSQL store support + +The overlay port exposes a `postgres-store` feature. Enable it in manifest mode when your application needs PostgreSQL-backed stores: + +```json +{ + "name": "my-a2a-app", + "version-string": "0.2.0", + "dependencies": [ + { + "name": "a2a-cpp", + "features": ["postgres-store"] + } + ] +} +``` + +When the feature is enabled, link the additional target where needed: + +```cmake +target_link_libraries(my_a2a_app PRIVATE a2a::store_postgres) +``` + +## Classic mode smoke install + +For a direct overlay smoke test, run classic mode from a directory that does not contain a `vcpkg.json` manifest: + +```bash +mkdir -p /tmp/a2a-vcpkg-smoke +cd /tmp/a2a-vcpkg-smoke +"$VCPKG_ROOT/vcpkg" install a2a-cpp --overlay-ports=/path/to/a2a-cpp/vcpkg-overlay-ports +``` + +Add a triplet if needed: + +```bash +"$VCPKG_ROOT/vcpkg" install a2a-cpp:x64-linux --overlay-ports=/path/to/a2a-cpp/vcpkg-overlay-ports +``` + +## Binary caching + +Large dependencies such as gRPC and protobuf can take time to build. Enable binary caching for local and CI runs: + +```bash +export VCPKG_BINARY_SOURCES="clear;files,$HOME/.cache/vcpkg-binary-cache,readwrite" +mkdir -p "$HOME/.cache/vcpkg-binary-cache" +``` + +On Windows PowerShell: + +```powershell +$env:VCPKG_BINARY_SOURCES = 'clear;files,C:\vcpkg-binary-cache,readwrite' +New-Item -ItemType Directory -Force C:\vcpkg-binary-cache | Out-Null +``` + +## Troubleshooting + +- **CMake cannot find gRPC or Protobuf**: confirm `CMAKE_TOOLCHAIN_FILE` points to `scripts/buildsystems/vcpkg.cmake` before the first configure. If you configured without it, delete the build directory and configure again. +- **Unexpected manifest behavior in classic mode**: classic `vcpkg install a2a-cpp` should be run outside directories containing `vcpkg.json`, otherwise vcpkg switches to manifest mode. +- **Different host and target triplets**: pass both `VCPKG_TARGET_TRIPLET` and `VCPKG_HOST_TRIPLET` when cross-compiling or when CI uses a custom host triplet. +- **Slow clean builds**: enable binary caching and prefer release-only dependency triplets for CI jobs that only link release configurations.