Skip to content
Open
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
47 changes: 47 additions & 0 deletions sdk/cpp/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
Language: Cpp
BasedOnStyle: Microsoft

# Match the existing project style
Standard: c++17
ColumnLimit: 120

# Indentation
IndentWidth: 4
TabWidth: 4
UseTab: Never
AccessModifierOffset: -4
IndentCaseLabels: false
NamespaceIndentation: All

# Braces
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterStruct: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false

# Alignment
AlignAfterOpenBracket: Align
AlignOperands: Align
AlignTrailingComments: true

# Includes
SortIncludes: false
IncludeBlocks: Preserve

# Misc
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortBlocksOnASingleLine: Empty
PointerAlignment: Left
SpaceAfterCStyleCast: false
SpaceBeforeParens: ControlStatements
155 changes: 155 additions & 0 deletions sdk/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
cmake_minimum_required(VERSION 3.20)

# VS hot reload policy (safe-guarded)
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
if (MSVC)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
"$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>")
endif()
endif()

project(CppSdk LANGUAGES CXX)

# -----------------------------
# Windows-only + compiler guard
# -----------------------------
if (NOT WIN32)
message(FATAL_ERROR "CppSdk is Windows-only for now (uses Win32/WIL headers).")
endif()

# Accept MSVC OR clang-cl (Clang in MSVC compatibility mode).
# VS CMake Open-Folder often uses clang-cl by default.
if (NOT (MSVC OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")))
message(STATUS "CMAKE_CXX_COMPILER_ID = ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "CMAKE_CXX_COMPILER = ${CMAKE_CXX_COMPILER}")
message(STATUS "CMAKE_CXX_SIMULATE_ID = ${CMAKE_CXX_SIMULATE_ID}")
message(FATAL_ERROR "Need MSVC or clang-cl (MSVC-compatible toolchain).")
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Optional: target Windows 10+ APIs (adjust if you need older)
add_compile_definitions(_WIN32_WINNT=0x0A00 WINVER=0x0A00)

include(FetchContent)

# -----------------------------
# nlohmann_json (clean CMake target)
# -----------------------------
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.12.0
)
FetchContent_MakeAvailable(nlohmann_json)
Comment on lines +42 to +47
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is using FetchContent allowed by security rules or do we need to use vcpkg? I have a working vcpkg based setup in my WIP branch if you need to copy from somewhere.


# -----------------------------
# WIL (download headers only; DO NOT run WIL's CMake)
# This avoids NuGet/test requirements and missing wil::wil targets.
# -----------------------------
FetchContent_Declare(
wil_src
GIT_REPOSITORY https://github.com/microsoft/wil.git
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the SDK Windows only or it builds/runs on other platforms?

GIT_TAG v1.0.250325.1
)
FetchContent_Populate(wil_src)

# -----------------------------
# Microsoft GSL (Guidelines Support Library)
# Provides gsl::span for C++17 (std::span is C++20)
# -----------------------------
FetchContent_Declare(
gsl
GIT_REPOSITORY https://github.com/microsoft/GSL.git
GIT_TAG v4.0.0
)
FetchContent_MakeAvailable(gsl)

# -----------------------------
# Google Test (for unit tests)
# -----------------------------
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
# Prevent GoogleTest from overriding our compiler/linker options on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

# -----------------------------
# SDK library (STATIC)
# List ONLY .cpp files here.
# -----------------------------
add_library(CppSdk STATIC
src/foundry_local.cpp
# Add more .cpp files as you migrate:
# src/parser.cpp
# src/dllmain.cpp
# src/pch.cpp
)
Comment on lines +87 to +93
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we build a shared library as well or there's no requirement for that currently?


target_include_directories(CppSdk
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${wil_src_SOURCE_DIR}/include
)

target_link_libraries(CppSdk
PUBLIC
nlohmann_json::nlohmann_json
Microsoft.GSL::GSL
)

# -----------------------------
# Sample executable
# -----------------------------
add_executable(CppSdkSample
sample/main.cpp
)

target_link_libraries(CppSdkSample PRIVATE CppSdk)

# -----------------------------
# Unit tests
# -----------------------------
enable_testing()

add_executable(CppSdkTests
test/parser_and_types_test.cpp
test/model_variant_test.cpp
test/catalog_test.cpp
test/client_test.cpp
)

target_include_directories(CppSdkTests
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test
)

target_compile_definitions(CppSdkTests PRIVATE FL_TESTS)

target_link_libraries(CppSdkTests
PRIVATE
CppSdk
GTest::gtest_main
)

# Copy testdata files next to the test executable so file-based tests can find them.
add_custom_command(TARGET CppSdkTests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/test/testdata
$<TARGET_FILE_DIR:CppSdkTests>/testdata
)

include(GoogleTest)
gtest_discover_tests(CppSdkTests
WORKING_DIRECTORY $<TARGET_FILE_DIR:CppSdkTests>
)

# Make Visual Studio start/debug this target by default
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTY VS_STARTUP_PROJECT CppSdkSample)
99 changes: 99 additions & 0 deletions sdk/cpp/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"version": 6,
"configurePresets": [
{
"name": "windows-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "x64-debug",
"displayName": "MSVC x64 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x64-release",
"displayName": "MSVC x64 Release",
"inherits": "windows-base",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "x86-debug",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about x86? We don't have FL Core builds of that do we?

"displayName": "MSVC x86 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x86-release",
"displayName": "MSVC x86 Release",
"inherits": "windows-base",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{
"name": "x64-debug",
"configurePreset": "x64-debug",
"displayName": "MSVC x64 Debug Build"
},
{
"name": "x64-release",
"configurePreset": "x64-release",
"displayName": "MSVC x64 Release Build"
}
],
"testPresets": [
{
"name": "x64-debug",
"configurePreset": "x64-debug",
"displayName": "MSVC x64 Debug Tests",
"output": {
"outputOnFailure": true
}
},
{
"name": "x64-release",
"configurePreset": "x64-release",
"displayName": "MSVC x64 Release Tests",
"output": {
"outputOnFailure": true
}
}
]
}
65 changes: 65 additions & 0 deletions sdk/cpp/include/configuration.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once
#include <string>
#include <optional>
#include <unordered_map>
#include <stdexcept>
#include <filesystem>
#include "log_level.h"

namespace FoundryLocal {

/// Optional configuration for the built-in web service.
struct WebServiceConfig {
// URL/s to bind the web service to.
// Default: 127.0.0.1:0 (random ephemeral port).
// Multiple URLs can be specified as a semicolon-separated list.
std::optional<std::string> urls;

// If the web service is running in a separate process, provide its URL here.
std::optional<std::string> external_url;
};

struct Configuration {
// Construct a Configuration with just an application name.
// All other fields use their defaults.
Configuration(std::string name) : app_name(std::move(name)) {}

// Your application name. MUST be set to a valid name.
std::string app_name;

// Application data directory.
// Default: {home}/.{appname}, where {home} is the user's home directory and {appname} is the app_name value.
std::optional<std::filesystem::path> app_data_dir;

// Model cache directory.
// Default: {appdata}/cache/models, where {appdata} is the app_data_dir value.
std::optional<std::filesystem::path> model_cache_dir;

// Log directory.
// Default: {appdata}/logs
std::optional<std::filesystem::path> logs_dir;

// Logging level.
// Valid values are: Verbose, Debug, Information, Warning, Error, Fatal.
// Default: LogLevel.Warning
LogLevel log_level = LogLevel::Warning;

// Optional web service configuration.
std::optional<WebServiceConfig> web;

// Additional settings that Foundry Local Core can consume.
std::optional<std::unordered_map<std::string, std::string>> additional_settings;

void Validate() const {
if (app_name.empty()) {
throw std::invalid_argument("Configuration app_name must be set to a valid application name.");
}

constexpr std::string_view invalidChars = R"(\/:?\"<>|)";
if (app_name.find_first_of(invalidChars) != std::string::npos) {
throw std::invalid_argument("Configuration app_name value contains invalid characters.");
}
}
};

} // namespace FoundryLocal
Loading
Loading