- Session move-only RAII; destructor best-effort close
- Client::create_session / list_sessions / get_session
- TurnResult.text() helper
- All post-parse json::get<T>() wrapped via with_protocol_guard (no nlohmann leak)
- tests/test_session.cpp: ~12 tests covering RAII/idempotency/move/list/state/404/protocol-error/regression
- ASan + UBSan clean
- README "Multi-turn / Sessions (v0.2)" section
v0.1 surface unchanged. C++17 preserved. cpp-httplib 0.20.1 preserved.
Spec: memory/spec-clawdforge-v0.2.md
Server core: 940861f
217 lines
7 KiB
CMake
217 lines
7 KiB
CMake
# SPDX-License-Identifier: MIT
|
|
cmake_minimum_required(VERSION 3.20)
|
|
|
|
project(clawdforge
|
|
VERSION 0.1.0
|
|
DESCRIPTION "C++ SDK for the clawdforge HTTP API"
|
|
LANGUAGES CXX
|
|
)
|
|
|
|
# ---- options ----------------------------------------------------------------
|
|
|
|
option(CLAWDFORGE_BUILD_TESTS "Build unit tests" ON)
|
|
option(CLAWDFORGE_BUILD_EXAMPLES "Build examples" ON)
|
|
option(CLAWDFORGE_WARNINGS_AS_ERRORS "Treat warnings as errors" ON)
|
|
|
|
# When consumed via add_subdirectory, default the extras off unless the user
|
|
# explicitly opts in. Top-level builds (the SDK's own CI / dev loop) keep them
|
|
# on so we exercise them.
|
|
if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
|
set(CLAWDFORGE_BUILD_TESTS OFF)
|
|
set(CLAWDFORGE_BUILD_EXAMPLES OFF)
|
|
endif()
|
|
|
|
# ---- standard / flags -------------------------------------------------------
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
|
|
endif()
|
|
|
|
include(CMakePackageConfigHelpers)
|
|
include(GNUInstallDirs)
|
|
include(FetchContent)
|
|
|
|
# ---- dependencies -----------------------------------------------------------
|
|
|
|
# nlohmann/json — try find_package first, fall back to FetchContent.
|
|
find_package(nlohmann_json 3.10 QUIET)
|
|
if(NOT nlohmann_json_FOUND)
|
|
message(STATUS "clawdforge: nlohmann_json not installed, fetching v3.11.3")
|
|
FetchContent_Declare(nlohmann_json
|
|
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
|
GIT_TAG v3.11.3
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
|
set(JSON_Install ON CACHE INTERNAL "")
|
|
FetchContent_MakeAvailable(nlohmann_json)
|
|
endif()
|
|
|
|
# libcurl — system-installed.
|
|
find_package(CURL REQUIRED)
|
|
|
|
# ---- library target ---------------------------------------------------------
|
|
|
|
add_library(clawdforge)
|
|
add_library(clawdforge::clawdforge ALIAS clawdforge)
|
|
|
|
target_sources(clawdforge
|
|
PRIVATE
|
|
src/client.cpp
|
|
src/http.cpp
|
|
)
|
|
|
|
target_include_directories(clawdforge
|
|
PUBLIC
|
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
|
PRIVATE
|
|
${CMAKE_CURRENT_SOURCE_DIR}/src
|
|
)
|
|
|
|
target_link_libraries(clawdforge
|
|
PUBLIC
|
|
nlohmann_json::nlohmann_json
|
|
PRIVATE
|
|
CURL::libcurl
|
|
)
|
|
|
|
target_compile_features(clawdforge PUBLIC cxx_std_17)
|
|
|
|
set_target_properties(clawdforge PROPERTIES
|
|
CXX_VISIBILITY_PRESET hidden
|
|
VISIBILITY_INLINES_HIDDEN ON
|
|
POSITION_INDEPENDENT_CODE ON
|
|
VERSION ${PROJECT_VERSION}
|
|
SOVERSION ${PROJECT_VERSION_MAJOR}
|
|
EXPORT_NAME clawdforge
|
|
)
|
|
|
|
# Warnings -- private so consumers don't inherit our flags.
|
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
|
target_compile_options(clawdforge PRIVATE
|
|
-Wall -Wextra -Wpedantic
|
|
-Wshadow -Wconversion -Wsign-conversion
|
|
-Wnon-virtual-dtor -Wold-style-cast
|
|
)
|
|
if(CLAWDFORGE_WARNINGS_AS_ERRORS)
|
|
target_compile_options(clawdforge PRIVATE -Werror)
|
|
endif()
|
|
elseif(MSVC)
|
|
target_compile_options(clawdforge PRIVATE /W4 /permissive-)
|
|
if(CLAWDFORGE_WARNINGS_AS_ERRORS)
|
|
target_compile_options(clawdforge PRIVATE /WX)
|
|
endif()
|
|
endif()
|
|
|
|
# ---- install ----------------------------------------------------------------
|
|
|
|
install(DIRECTORY include/clawdforge
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
|
FILES_MATCHING PATTERN "*.hpp"
|
|
)
|
|
|
|
install(TARGETS clawdforge
|
|
EXPORT clawdforge-targets
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
)
|
|
|
|
install(EXPORT clawdforge-targets
|
|
FILE clawdforge-targets.cmake
|
|
NAMESPACE clawdforge::
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
|
|
)
|
|
|
|
configure_package_config_file(
|
|
cmake/clawdforge-config.cmake.in
|
|
"${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config.cmake"
|
|
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
|
|
)
|
|
|
|
write_basic_package_version_file(
|
|
"${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config-version.cmake"
|
|
VERSION ${PROJECT_VERSION}
|
|
COMPATIBILITY SameMajorVersion
|
|
)
|
|
|
|
install(FILES
|
|
"${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config.cmake"
|
|
"${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config-version.cmake"
|
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
|
|
)
|
|
|
|
# ---- examples ---------------------------------------------------------------
|
|
|
|
if(CLAWDFORGE_BUILD_EXAMPLES)
|
|
add_executable(clawdforge_basic_example examples/basic.cpp)
|
|
target_link_libraries(clawdforge_basic_example PRIVATE clawdforge::clawdforge)
|
|
endif()
|
|
|
|
# ---- tests ------------------------------------------------------------------
|
|
|
|
if(CLAWDFORGE_BUILD_TESTS)
|
|
enable_testing()
|
|
|
|
# cpp-httplib for an in-process mock server. Prefer system / installed copy.
|
|
# Test-only — never linked into the shipped library. Bumped from 0.15.3 to
|
|
# 0.20.1 for clean dep graphs (0.15.x has several published advisories;
|
|
# the SDK never exposes the mock to a network).
|
|
find_package(httplib QUIET CONFIG)
|
|
if(NOT httplib_FOUND)
|
|
message(STATUS "clawdforge: cpp-httplib not installed, fetching v0.20.1")
|
|
# The mock server doesn't need TLS / compression — disable optional
|
|
# backends so we don't drag in zstd / brotli / openssl find_package
|
|
# requirements for a test-only dep.
|
|
set(HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF CACHE INTERNAL "")
|
|
set(HTTPLIB_USE_ZLIB_IF_AVAILABLE OFF CACHE INTERNAL "")
|
|
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF CACHE INTERNAL "")
|
|
set(HTTPLIB_USE_ZSTD_IF_AVAILABLE OFF CACHE INTERNAL "")
|
|
FetchContent_Declare(cpp_httplib
|
|
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
|
|
GIT_TAG v0.20.1
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_MakeAvailable(cpp_httplib)
|
|
endif()
|
|
|
|
# doctest — single-header, fastest to compile of the popular options.
|
|
find_package(doctest QUIET CONFIG)
|
|
if(NOT doctest_FOUND)
|
|
message(STATUS "clawdforge: doctest not installed, fetching v2.4.11")
|
|
FetchContent_Declare(doctest
|
|
GIT_REPOSITORY https://github.com/doctest/doctest.git
|
|
GIT_TAG v2.4.11
|
|
GIT_SHALLOW TRUE
|
|
)
|
|
FetchContent_MakeAvailable(doctest)
|
|
endif()
|
|
|
|
add_executable(clawdforge_tests
|
|
tests/test_client.cpp
|
|
tests/test_session.cpp
|
|
)
|
|
target_link_libraries(clawdforge_tests
|
|
PRIVATE
|
|
clawdforge::clawdforge
|
|
httplib::httplib
|
|
doctest::doctest
|
|
)
|
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
|
target_compile_options(clawdforge_tests PRIVATE
|
|
-Wall -Wextra
|
|
# Designated initializers in C++20 don't need to set every member.
|
|
-Wno-missing-field-initializers
|
|
# CHECK_THROWS_AS expands to a discarded-value expression; the
|
|
# `[[nodiscard]]` on Client methods makes that legitimately noisy.
|
|
-Wno-unused-result
|
|
)
|
|
endif()
|
|
|
|
add_test(NAME clawdforge_tests COMMAND clawdforge_tests)
|
|
endif()
|