-
Notifications
You must be signed in to change notification settings - Fork 273
Add C++ SDK Support #544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add C++ SDK Support #544
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 |
| 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) | ||
|
|
||
| # ----------------------------- | ||
| # 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 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
| 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", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| 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 |
There was a problem hiding this comment.
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.