Modernize CMake embedding and self-contained dependencies - #1511
Modernize CMake embedding and self-contained dependencies#1511bmehta001 wants to merge 10 commits into
Conversation
Expose the same MSTelemetry::mat target name for build-tree add_subdirectory/FetchContent consumers so downstream projects can link one target regardless of vcpkg/install vs source embedding. Files changed: - lib/CMakeLists.txt: add MSTelemetry::mat build-tree alias. - CMakeLists.txt, lib/CMakeLists.txt: add optional MATSDK_CURL_TARGET, MATSDK_SQLITE_TARGET, and MATSDK_ZLIB_TARGET overrides for non-vcpkg superbuilds, with a WIN32 zlib guard for the existing act_z_* header path. - docs/embedding-with-cmake.md: document source embedding and dependency target overrides. - tests/embedding/CMakeLists.txt: add add_subdirectory smoke project linking MSTelemetry::mat. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
Allow source-embedding consumers to set MATSDK_CURL_PROVIDER=FETCH so 1DS downloads and builds a pinned static curl dependency on Linux, matching the ORT GenAI model. Details: - Add MATSDK_CURL_PROVIDER and MATSDK_CURL_TLS_BACKEND options, defaulting to package discovery and mbedTLS for fetched curl. - Add pinned curl and mbedTLS URL/SHA cache variables. - Add cmake/MatsdkFetchCurl.cmake to build HTTP(S)-only static curl with mbedTLS or OpenSSL. - Document fetched curl and dependency-target override usage for non-vcpkg embedding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
This PR improves the CMake “source embedding” experience (via add_subdirectory() / FetchContent) so consumers can link the SDK through the same MSTelemetry::mat target name used by vcpkg/installed workflows, and optionally obtain a self-contained non-vcpkg libcurl on Linux.
Changes:
- Add a build-tree
MSTelemetry::matalias for the in-treemattarget. - Add non-vcpkg dependency override cache variables (
MATSDK_CURL_TARGET,MATSDK_SQLITE_TARGET,MATSDK_ZLIB_TARGET) and a Linux-onlyMATSDK_CURL_PROVIDER=FETCHpath with selectable TLS backend. - Add embedding documentation and a CMake smoke project that links
MSTelemetry::matviaadd_subdirectory().
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
CMakeLists.txt |
Adds cache variables and validation for non-vcpkg dependency overrides and fetched-curl selection. |
lib/CMakeLists.txt |
Adds build-tree MSTelemetry::mat alias and wires SQLite/zlib override targets into platform link logic. |
cmake/MatsdkFetchCurl.cmake |
Implements Linux-only FetchContent build of pinned static curl (+ optional mbedTLS/OpenSSL). |
docs/embedding-with-cmake.md |
Documents embedding with MSTelemetry::mat and the non-vcpkg override/fetch options. |
tests/embedding/CMakeLists.txt |
Adds an embedding smoke CMake project that links MSTelemetry::mat. |
Comments suppressed due to low confidence (1)
cmake/MatsdkFetchCurl.cmake:116
- FetchContent URL_HASH uses SHA1 for the pinned curl download. SHA1 is cryptographically weak for verifying downloaded archives; prefer SHA256 (or stronger) to reduce the risk of a collision-based substitution.
FetchContent_Declare(
matsdk_curl
URL ${MATSDK_CURL_URL}
URL_HASH SHA1=${MATSDK_CURL_SHA1})
FetchContent_MakeAvailable(matsdk_curl)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
CMakeLists.txt:379
- The fetched dependency integrity pins use SHA1 (MATSDK_MBEDTLS_SHA1). SHA1 is collision-prone; prefer SHA256 (or stronger) for FetchContent URL_HASH to reduce supply-chain risk. This change will require updating both the cache variable(s) and the URL_HASH algorithm in MatsdkFetchCurl.cmake.
set(MATSDK_MBEDTLS_URL "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-3.6.7/mbedtls-3.6.7.tar.bz2" CACHE STRING
"URL for the mbedTLS dependency used by MATSDK_CURL_PROVIDER=FETCH and MATSDK_CURL_TLS_BACKEND=MBEDTLS")
set(MATSDK_MBEDTLS_SHA1 "e892e98cff90cf7e0736c525bf357626a2513c4c" CACHE STRING
"SHA1 for MATSDK_MBEDTLS_URL")
Use SHA256 URL_HASH pins for fetched curl and mbedTLS instead of SHA1, matching FetchContent's stronger integrity checks. Do not override CURL_CA_BUNDLE/CURL_CA_PATH to none; allow fetched curl to use normal CA discovery so default TLS verification can succeed without every consumer supplying CAINFO. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
cmake/MatsdkFetchCurl.cmake:73
- Same as above for the ON toggles: these should be set as CACHE entries so the fetched curl/mbedTLS builds deterministically pick them up (especially options like BUILD_STATIC_LIBS / HTTP_ONLY).
foreach(option IN ITEMS
BUILD_STATIC_LIBS
DISABLE_PACKAGE_CONFIG_AND_INSTALL
CURL_DISABLE_INSTALL
HTTP_ONLY
CURL_DISABLE_ALTSVC
CURL_DISABLE_HSTS
CURL_DISABLE_COOKIES
CURL_DISABLE_NETRC
CURL_DISABLE_MIME
CURL_DISABLE_DOH
CURL_DISABLE_AWS
CURL_DISABLE_BEARER_AUTH
CURL_DISABLE_DIGEST_AUTH
CURL_DISABLE_KERBEROS_AUTH
CURL_DISABLE_NEGOTIATE_AUTH)
set(${option} ON)
endforeach()
cmake/MatsdkFetchCurl.cmake:54
- The feature/option toggles are set as normal variables (e.g.,
set(${option} OFF)), which may not reliably control the fetched subprojects'option()/CACHE settings across all CMake versions and scopes. To ensure curl/mbedTLS actually build with the intended minimal feature set, set these as CACHE entries (with FORCE) beforeFetchContent_MakeAvailable().
This issue also appears on line 56 of the same file.
foreach(option IN ITEMS
BUILD_SHARED_LIBS
BUILD_TESTING
ENABLE_PROGRAMS
ENABLE_TESTING
GEN_FILES
UNSAFE_BUILD
INSTALL_MBEDTLS_HEADERS
MBEDTLS_FATAL_WARNINGS
USE_SHARED_MBEDTLS_LIBRARY
LINK_WITH_PTHREAD
BUILD_CURL_EXE
BUILD_EXAMPLES
BUILD_LIBCURL_DOCS
BUILD_MISC_DOCS
ENABLE_CURL_MANUAL
CURL_ENABLE_EXPORT_TARGET
CURL_USE_OPENSSL
CURL_USE_PKGCONFIG
CURL_USE_CMAKECONFIG
CURL_ZLIB
CURL_BROTLI
CURL_ZSTD
USE_LIBIDN2
CURL_USE_LIBPSL
CURL_USE_LIBSSH2
CURL_USE_LIBSSH
CURL_USE_GSSAPI
CURL_USE_GSASL
USE_NGHTTP2
USE_NGTCP2
USE_QUICHE
ENABLE_ARES
ENABLE_UNIX_SOCKETS)
set(${option} OFF)
endforeach()
CMakeLists.txt:391
MATSDK_CURL_TLS_BACKENDis validated even whenMATSDK_CURL_PROVIDERis PACKAGE (or curl isn't used on the current platform). This makes otherwise-valid configurations fail due to an unused setting. Gate the validation onMATSDK_CURL_PROVIDER=FETCH.
string(TOUPPER "${MATSDK_CURL_TLS_BACKEND}" MATSDK_CURL_TLS_BACKEND_UPPER)
if(NOT MATSDK_CURL_TLS_BACKEND_UPPER STREQUAL "MBEDTLS" AND NOT MATSDK_CURL_TLS_BACKEND_UPPER STREQUAL "OPENSSL")
message(FATAL_ERROR "MATSDK_CURL_TLS_BACKEND must be MBEDTLS or OPENSSL; got '${MATSDK_CURL_TLS_BACKEND}'.")
endif()
CMakeLists.txt:393
- The
MATSDK_*_TARGEToverrides are described as applying to non-vcpkg builds, but they are validated unconditionally. This can make vcpkg configurations fail due to unused override variables. Consider gating this validation onNOT MATSDK_USE_VCPKG_DEPS.
if(${_matsdk_dependency_target_var} AND NOT TARGET "${${_matsdk_dependency_target_var}}")
docs/embedding-with-cmake.md:26
- The docs mention
MATSDK_CURL_PROVIDER=FETCHbut don’t note that it will fail if the consuming build already definesCURL::libcurl(e.g., viafind_package(CURL)), because the embedded curl build needs to create that target name. Calling this out will save consumers time when integrating into larger superbuilds.
When the CPP11 PAL uses the curl HTTP transport outside vcpkg, the SDK normally
calls `find_package(CURL)` and links `CURL::libcurl` when that imported target is
available. On Linux, set `MATSDK_CURL_PROVIDER=FETCH` to let the SDK download and
build a pinned static curl dependency instead:
Select HTTP/2 only when the linked curl runtime advertises support and otherwise request HTTP/1.1, so minimal fetched curl builds do not force an unavailable protocol. Check curl option/getinfo failures, preserve constructor configuration errors, and use the correct response-code/socket types before sending. Also fix the conventional calloc argument ordering in EventProperties while bundling small correctness work with the larger embedding PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
Bundle the remaining embedding work into PR microsoft#1511 so downstream projects can consume one stable target without source rewrites or platform-specific dependency glue. Key changes: - use standard CMAKE_OSX_* architecture/sysroot/deployment settings with legacy input compatibility; - add canonical MATSDK_* build options and explicit STATIC/SHARED library selection; - make warnings, Werror, ARC, visibility, and dead-strip policy target-local; - add explicit SYSTEM/MINIMAL/VENDORED SQLite and zlib providers with self-contained static installs; - preserve static/dynamic and pinned-source vcpkg compatibility; - add FetchContent consumer CI for Linux, Windows, macOS universal/arm64, iOS device/simulator, and Android under warnings-as-errors; - update build scripts/docs and route legacy installation through cmake --install. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
lib/http/HttpClient_Curl.hpp:317
CURLOPT_WRITEFUNCTIONexpects a function pointer; passing it as avoid*(via(void *)&WriteVectorCallback) is undefined behavior on platforms where data pointers and function pointers differ. Prefer passing a function-pointer type (e.g.,curl_write_callback) and pass data pointers asvoid*explicitly.
else if (!SetOption(CURLOPT_WRITEFUNCTION, (void *)&WriteVectorCallback)
|| !SetOption(CURLOPT_HEADERDATA, (void *)&respHeaders)
|| !SetOption(CURLOPT_WRITEDATA, (void *)&respBody))
{
cmake/MatsdkFetchCurl.cmake:54
- The curl/mbedTLS option toggles are set with plain
set(...)inside a CMakefunction(). FetchContent builds the dependency viaadd_subdirectory(), which typically does not inherit function-scope variables, so these toggles may be ignored and the fetched curl build could end up using its defaults (shared libs, extra protocols/features, installs, etc.). Consider switching to a mechanism guaranteed to affect the dependency configure (e.g., cache variables scoped/restored around the FetchContent call, or a wrapper toolchain/options file).
foreach(option IN ITEMS
BUILD_SHARED_LIBS
BUILD_TESTING
ENABLE_PROGRAMS
ENABLE_TESTING
GEN_FILES
UNSAFE_BUILD
INSTALL_MBEDTLS_HEADERS
MBEDTLS_FATAL_WARNINGS
USE_SHARED_MBEDTLS_LIBRARY
LINK_WITH_PTHREAD
BUILD_CURL_EXE
BUILD_EXAMPLES
BUILD_LIBCURL_DOCS
BUILD_MISC_DOCS
ENABLE_CURL_MANUAL
CURL_ENABLE_EXPORT_TARGET
CURL_USE_OPENSSL
CURL_USE_PKGCONFIG
CURL_USE_CMAKECONFIG
CURL_ZLIB
CURL_BROTLI
CURL_ZSTD
USE_LIBIDN2
CURL_USE_LIBPSL
CURL_USE_LIBSSH2
CURL_USE_LIBSSH
CURL_USE_GSSAPI
CURL_USE_GSASL
USE_NGHTTP2
USE_NGTCP2
USE_QUICHE
ENABLE_ARES
ENABLE_UNIX_SOCKETS)
set(${option} OFF)
endforeach()
lib/http/HttpClient_Curl.hpp:240
- This guard can leak a previous successful HTTP status code into the
!curl || !m_isConfiguredfailure path (because it only overwritesreswhen it is exactlyCURLE_OK). That can makeSend()report success even though it immediately fails initialization. Consider overridingreswhen it isCURLE_OKor when it looks like an HTTP status code (>=100), while still preserving a prior CURL error from construction/configuration.
if(!curl || !m_isConfigured)
{
if (res == CURLE_OK)
{
res = CURLE_FAILED_INIT;
}
DispatchEvent(OnSendFailed);
Pass curl_write_callback function pointers instead of converting function pointers to void*, and use void* only for callback userdata. This preserves portability on architectures where function and data pointers differ. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
lib/http/HttpClient_Curl.hpp:318
Send()attempts to collect response headers intorespHeadersviaCURLOPT_HEADERDATA, but noCURLOPT_HEADERFUNCTIONis set. In that case, libcurl will not userespHeaders(andGetResponseHeaders()will always return empty). Set an explicit header callback (the existingWriteVectorCallbackworks) so therespHeadersbuffer is actually populated.
else if (!SetOption(CURLOPT_WRITEFUNCTION,
static_cast<curl_write_callback>(&WriteVectorCallback))
|| !SetOption(CURLOPT_HEADERDATA, static_cast<void*>(&respHeaders))
|| !SetOption(CURLOPT_WRITEDATA, static_cast<void*>(&respBody)))
Substitute a build-platform boolean that is always TRUE or FALSE so generated package configs never depend on an undefined APPLE variable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
lib/http/HttpClient_Curl.hpp:322
respHeadersis never populated: the code setsCURLOPT_HEADERDATAbut never setsCURLOPT_HEADERFUNCTION, so libcurl has no callback to write headers intorespHeaders. As a result,HttpClient_Curl.cppalways sees an empty header map fromGetResponseHeaders(). SetCURLOPT_HEADERFUNCTION(and keepCURLOPT_HEADERDATA) so headers are captured separately from the body.
else if (!SetOption(CURLOPT_WRITEFUNCTION,
static_cast<curl_write_callback>(&WriteVectorCallback))
|| !SetOption(CURLOPT_HEADERDATA, static_cast<void*>(&respHeaders))
|| !SetOption(CURLOPT_WRITEDATA, static_cast<void*>(&respBody)))
{
lib/http/HttpClient_Curl.hpp:283
- On the pre-7.45.0 libcurl path (
CURLINFO_LASTSOCKET),lastSocketcan be-1even whencurl_easy_getinforeturnsCURLE_OK. That leavessockextrasCURL_SOCKET_BAD, but the code proceeds toWaitOnSocket()and treatspoll()errors as success. TreatCURL_SOCKET_BADas a connect failure before using the socket.
{
CURLcode infoResult;
#if LIBCURL_VERSION_NUM >= 0x072D00 // Version 7.45.00
infoResult = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockextr);
#else
long lastSocket = -1;
infoResult = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &lastSocket);
if (infoResult == CURLE_OK)
{
sockextr = static_cast<curl_socket_t>(lastSocket);
}
#endif
if(CURLE_OK != infoResult)
{
res = static_cast<long>(infoResult);
DispatchEvent(OnConnectFailed); // couldn't connect - stage 2
TRACE("Error #2: %s\n", curl_easy_strerror(infoResult));
goto cleanup;
}
.github/workflows/test-embedding.yml:137
- The Android embedding workflow uses
ANDROID_NDK_LATEST_HOME, but the repo’s existing Android tooling usesANDROID_NDK_HOME(e.g.,tests/vcpkg/test-vcpkg-android.sh). Using a different env var here risks expanding to an empty toolchain path and breaking CI on runners whereANDROID_NDK_LATEST_HOMEisn’t set. Prefer the sameANDROID_NDK_HOMEvariable for consistency.
run: >
cmake -G Ninja -S tests/embedding -B build-embedding
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK_LATEST_HOME}/build/cmake/android.toolchain.cmake
-DANDROID_ABI=arm64-v8a
Capture response headers with an explicit typed callback, reject invalid or failed socket waits, and build CMake invocations as argv arrays so custom flags and universal architecture lists retain correct quoting. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
lib/http/HttpClient_Curl.hpp:290
- The per-operation
httpConnTimeoutparameter is never used;Send()still waits using the compile-timeHTTP_CONN_TIMEOUTconstant. This makeshttpConnTimeoutineffective for callers and can lead to unexpected timeout behavior when a non-default value is provided.
/* wait for the socket to become ready for sending */
sockfd = sockextr;
socketWaitResult = WaitOnSocket(sockfd, 0, HTTP_CONN_TIMEOUT * 1000L);
if(socketWaitResult <= 0 || isAborted)
{
lib/http/HttpClient_Curl.hpp:393
resis along, but the trace uses%d(int). If tracing is ever enabled, this is undefined behavior on LP64 platforms. Use%ld(or cast) to match the argument type.
// We got some response from server. Dump the contents.
TRACE("HTTP response code %d\n", res);
DispatchEvent(OnResponse);
Remove recent redundant SQLite/vendor compatibility switches in favor of the explicit provider options, while retaining established legacy build inputs. Also reuse parent-provided CURL::libcurl automatically and make bundled Apple-mobile SQLite explicitly disable gethostuuid, matching the remaining useful ONNX Runtime patch behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b12c5862-01e3-45e4-bf91-6389c20cae41
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 26 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
cmake/MatsdkFetchCurl.cmake:72
- Same scoping issue as above: setting these dependency options to ON as non-cache variables may not affect the FetchContent-added subproject. Use CACHE BOOL (FORCE) so curl/mbedTLS configuration is deterministic.
set(${option} ON)
cmake/MatsdkFetchCurl.cmake:53
- The curl/mbedTLS option toggles are set as normal variables inside a function. Because FetchContent adds the dependency via add_subdirectory(), these values may not propagate into the fetched project's directory scope, so curl could ignore them and build unwanted components (tests, tools, shared libs, etc.). Set them as CACHE variables (FORCE) so the fetched subproject reliably honors them.
This issue also appears on line 72 of the same file.
set(${option} OFF)
Problem
Source embedding via
add_subdirectory()/FetchContentshould let ORT / ORT GenAI-style consumers link one stable target without patching 1DS sources, manually wiring curl/SQLite/zlib, inheriting SDK warning flags, or passing nonstandard Apple architecture variables.Changes
Uniform embedding surface
MSTelemetry::mat.MATSDK_LIBRARY_TYPE=STATIC|SHAREDwithout mutating parentBUILD_SHARED_LIBS.MATSDK_BUILD_*options; legacyBUILD_*inputs remain compatibility inputs.Dependency providers
MATSDK_SQLITE_PROVIDER=AUTO|SYSTEM|MINIMAL|VENDORED.MATSDK_ZLIB_PROVIDER=AUTO|SYSTEM|VENDORED.MATSDK_CURL_TARGET,MATSDK_SQLITE_TARGET, andMATSDK_ZLIB_TARGEThooks.MATSDK_CURL_PROVIDER=PACKAGE|FETCHandMATSDK_CURL_TLS_BACKEND=MBEDTLS|OPENSSL.libmat.Build correctness and isolation
CMAKE_OSX_ARCHITECTURES,CMAKE_OSX_SYSROOT, andCMAKE_OSX_DEPLOYMENT_TARGET; retain legacy Apple input translation.find_package()paths./usr/local/includefrom all cross-compiles.callocargument order.cmake --install.Consumer CI
Add a source-embedding matrix covering:
All consumer targets build with warnings-as-errors. Existing vcpkg CI continues to cover installed
find_package(MSTelemetry)consumers.Local validation
/usr/local/include.nm -D).BUILD_*,BUILD_SHARED_LIBS, andMAC_ARCH=universalcompatibility verified.