Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4e8493c
Add BUILD_CURL_HTTP_CLIENT option to build Linux without curl/TLS
bmehta001 Jun 25, 2026
167fc2b
Add MATSDK_MINIMAL_SQLITE: private feature-stripped SQLite to cut foo…
bmehta001 Jun 25, 2026
0977e64
Address Copilot review: scope bundled-SQLite export to static mat
bmehta001 Jun 25, 2026
534be72
Clarify sqlite3_bundled PRIVATE-link comment (Copilot review)
bmehta001 Jun 25, 2026
2c88c16
vcpkg port: selectable TLS backend (curl-openssl/curl-mbedtls) + no-d…
bmehta001 Jun 25, 2026
c00ce55
Harden HTTP-client features: CURL CONFIG mode + mutual-exclusivity gu…
bmehta001 Jun 25, 2026
7b3e35a
Remove the no-curl (no-default-http-client) option
bmehta001 Jun 25, 2026
c83b7c6
vcpkg: use Apple's system libsqlite3/libz on macOS/iOS instead of vcp…
bmehta001 Jun 25, 2026
3621a32
Clarify mbedTLS guidance: [core,...] drops system-sqlite too
bmehta001 Jun 26, 2026
884cbb0
Fix misleading curl 'optional' label and mbedTLS feature description
bmehta001 Jun 26, 2026
f6ae4c4
Harden [core,...] guidance and fix exported CURL find_dependency mode
bmehta001 Jun 26, 2026
14aa079
Scope curl TLS-backend guards to Linux/Android only
bmehta001 Jun 26, 2026
509ed08
vcpkg port tests: build the working tree, not a pinned release
bmehta001 Jun 30, 2026
00c5621
Fix Windows vcpkg test to actually build the working tree
bmehta001 Jun 30, 2026
2994141
Gate test suites on top-level project (default OFF for consumers)
bmehta001 Jul 7, 2026
2995f9e
Address Copilot review: validate source dir, append VCPKG_KEEP_ENV_VARS
bmehta001 Jul 7, 2026
5d127d7
Support consuming SDK as a CMake subproject in legacy mode
bmehta001 Jul 7, 2026
e8a25ad
Explicitly disable warning-as-error for the vendored SQLite TU on MSVC
bmehta001 Jul 7, 2026
5a238e8
Clarify MATSDK_MINIMAL_SQLITE-on-Apple comment for the iOS legacy path
bmehta001 Jul 7, 2026
c114475
Link system sqlite3 + zlib on Apple legacy builds (match repo convent…
bmehta001 Jul 8, 2026
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
88 changes: 79 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ else()
endif()
message(STATUS "MATSDK_USE_VCPKG_DEPS: ${MATSDK_USE_VCPKG_DEPS}")

# Build a private, feature-stripped copy of the vendored SQLite amalgamation
# instead of linking an external SQLite. The SDK uses SQLite only for its offline
# event-storage cache, so the minimal build (see lib/CMakeLists.txt
# MATSDK_SQLITE_MINIMAL_DEFS) omits every optional SQLite subsystem the SDK does
# not use, shrinking the SQLite code ~10% and removing the external sqlite3
# dependency. Off by default to preserve the existing external/system-SQLite
# behavior; the Android NDK path always bundles SQLite regardless.
option(MATSDK_MINIMAL_SQLITE "Build a feature-stripped vendored SQLite instead of an external one" OFF)
message(STATUS "MATSDK_MINIMAL_SQLITE: ${MATSDK_MINIMAL_SQLITE}")

# Begin Uncomment for i386 build
#set(CMAKE_SYSTEM_PROCESSOR i386)
#set(CMAKE_C_FLAGS -m32)
Expand Down Expand Up @@ -327,8 +337,20 @@ message(STATUS "SDK version: ${SDK_VERSION_PREFIX}-${MATSDK_BUILD_VERSION}")
option(BUILD_HEADERS "Build API headers" YES)
option(BUILD_LIBRARY "Build library" YES)
option(BUILD_TEST_TOOL "Build console test tool" YES)
option(BUILD_UNIT_TESTS "Build unit tests" YES)
option(BUILD_FUNC_TESTS "Build functional tests" YES)
# Default the test suites ON only when this repository is the top-level project
# (developer/CI build), and OFF when it is consumed via add_subdirectory()/
# FetchContent, so downstream projects don't build the tests or require the
# third_party/googletest submodule. PROJECT_IS_TOP_LEVEL exists on CMake >= 3.21;
# fall back to comparing the source dirs on older CMake (floor is 3.15).
if(DEFINED PROJECT_IS_TOP_LEVEL)
set(MATSDK_TESTS_DEFAULT ${PROJECT_IS_TOP_LEVEL})
elseif(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
set(MATSDK_TESTS_DEFAULT ON)
else()
set(MATSDK_TESTS_DEFAULT OFF)
endif()
option(BUILD_UNIT_TESTS "Build unit tests" ${MATSDK_TESTS_DEFAULT})
option(BUILD_FUNC_TESTS "Build functional tests" ${MATSDK_TESTS_DEFAULT})
option(BUILD_JNI_WRAPPER "Build JNI wrapper" NO)
option(BUILD_OBJC_WRAPPER "Build Obj-C wrapper" YES)
option(BUILD_SWIFT_WRAPPER "Build Swift Wrappers" YES)
Expand Down Expand Up @@ -363,10 +385,25 @@ if(PAL_IMPLEMENTATION STREQUAL "CPP11"
AND NOT BUILD_APPLE_HTTP)
set(MATSDK_NEEDS_CURL ON)
add_definitions(-DHAVE_MAT_CURL_HTTP_CLIENT)
find_package(CURL REQUIRED)
if(MATSDK_USE_VCPKG_DEPS)
# The TLS backend (OpenSSL/mbedTLS) is selected by the vcpkg port's
# curl-openssl (default) / curl-mbedtls features; the SDK just links libcurl.
# Force CONFIG mode so the vcpkg-provided CURLConfig (which defines the
# CURL::libcurl imported target) is used rather than the module FindCURL,
# which on some CMake versions does not define that target.
find_package(CURL CONFIG QUIET)
if(NOT TARGET CURL::libcurl)
message(FATAL_ERROR
"libcurl was not found. The vcpkg port provides the curl HTTP client "
"through the curl-openssl (default) or curl-mbedtls feature. Install "
"cpp-client-telemetry with its default features, or, under the [core,...] "
"form (which drops the default curl-openssl and system-sqlite features), "
"re-select a curl backend and a SQLite backend together, e.g. "
"[core,curl-openssl,system-sqlite] or [core,curl-mbedtls,minimal-sqlite].")
endif()
list(APPEND LIBS CURL::libcurl)
else()
find_package(CURL REQUIRED)
# Prefer the imported target, which carries curl's include dirs and link
# flags. Fall back to the find-module variables on CMake < 3.12, where
# find_package(CURL) does not define CURL::libcurl.
Expand All @@ -383,13 +420,46 @@ endif()
# Dependency resolution (vcpkg mode vs vendored)
################################################################################################
if(MATSDK_USE_VCPKG_DEPS)
find_package(unofficial-sqlite3 CONFIG REQUIRED)
find_package(ZLIB REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
message(STATUS "Using vcpkg-provided sqlite3, zlib, nlohmann-json")
if(APPLE)
# macOS/iOS ship libsqlite3 and libz as system libraries (the SDK's SPM
# distribution links them the same way), so the vcpkg sqlite3/zlib packages are
# not pulled there -- find the system ones via CMake's standard find modules.
find_package(SQLite3 REQUIRED)
find_package(ZLIB REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
set(MATSDK_APPLE_SYSTEM_DEPS ON)
message(STATUS "Apple: using system SQLite3 + zlib; vcpkg-provided nlohmann-json")
else()
set(MATSDK_APPLE_SYSTEM_DEPS OFF)
# SQLite is provided by the private minimal build when MATSDK_MINIMAL_SQLITE is
# ON, so only require the external vcpkg sqlite3 package otherwise.
if(NOT MATSDK_MINIMAL_SQLITE)
find_package(unofficial-sqlite3 CONFIG QUIET)
if(NOT unofficial-sqlite3_FOUND)
message(FATAL_ERROR
"SQLite was not found and the minimal SQLite is not enabled. The vcpkg "
"port provides SQLite through one of two features: 'system-sqlite' "
"(default, links the external sqlite3 package) or 'minimal-sqlite' "
"(builds a private feature-stripped SQLite). Install "
"cpp-client-telemetry with its default features, or with "
"[core,system-sqlite] or [core,minimal-sqlite]. For a direct CMake build, pass "
"-DMATSDK_MINIMAL_SQLITE=ON or ensure unofficial-sqlite3 is discoverable.")
endif()
endif()
find_package(ZLIB REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
if(MATSDK_MINIMAL_SQLITE)
message(STATUS "Using vcpkg-provided zlib, nlohmann-json; private minimal SQLite")
else()
message(STATUS "Using vcpkg-provided sqlite3, zlib, nlohmann-json")
endif()
endif()
else()
# Include repo root to allow includes of vendored sqlite, zlib, and nlohmann
include_directories(${CMAKE_SOURCE_DIR})
# Include repo root to allow includes of vendored sqlite, zlib, and nlohmann.
# Use CMAKE_CURRENT_SOURCE_DIR (this repo's root) rather than CMAKE_SOURCE_DIR
# so the vendored headers still resolve when the SDK is consumed as a subproject
# (add_subdirectory/FetchContent), where CMAKE_SOURCE_DIR is the consumer's root.
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
message(STATUS "Using vendored sqlite3, zlib, nlohmann-json")
endif()

Expand Down
16 changes: 13 additions & 3 deletions cmake/MSTelemetryConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

include(CMakeFindDependencyMacro)

# Re-find dependencies that consumers need
find_dependency(unofficial-sqlite3 CONFIG)
# Re-find dependencies that consumers need.
# On Apple the SDK links the system libsqlite3 (SQLite::SQLite3); elsewhere it uses
# the vcpkg sqlite3 package unless a private minimal SQLite is bundled.
if(@MATSDK_APPLE_SYSTEM_DEPS@)
find_dependency(SQLite3)
elseif(NOT @MATSDK_BUNDLE_SQLITE@)
find_dependency(unofficial-sqlite3 CONFIG)
endif()
Comment thread
bmehta001 marked this conversation as resolved.
find_dependency(ZLIB)
find_dependency(nlohmann_json CONFIG)

Expand All @@ -14,7 +20,11 @@ find_dependency(nlohmann_json CONFIG)
# because the macOS BUILD_APPLE_HTTP choice can't be inferred from
# CMAKE_SYSTEM_NAME alone.
if(@MATSDK_NEEDS_CURL@)
find_dependency(CURL)
# Force CONFIG mode so the vcpkg-provided CURLConfig (which defines the
# CURL::libcurl imported target referenced by MSTelemetryTargets.cmake) is
# used, rather than module-mode FindCURL, which on some CMake versions does
# not define that target.
find_dependency(CURL CONFIG)
endif()

# Pthreads are needed on Linux and Android (POSIX threading)
Expand Down
127 changes: 124 additions & 3 deletions docs/building-with-vcpkg.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,24 @@ The vcpkg port automatically resolves the following dependencies:

| Dependency | vcpkg Package | CMake Target | Platforms |
| -------------- | --------------- | --------------------------------- | ------------------ |
| SQLite3 | `sqlite3` | `unofficial::sqlite3::sqlite3` | All |
| zlib | `zlib` | `ZLIB::ZLIB` | All |
| SQLite3 | `sqlite3` | `unofficial::sqlite3::sqlite3` | Non-Apple (default; see `minimal-sqlite`). **macOS/iOS link the system `libsqlite3`** (`SQLite::SQLite3`) |
| zlib | `zlib` | `ZLIB::ZLIB` | Non-Apple. **macOS/iOS link the system `libz`** |
| nlohmann JSON | `nlohmann-json` | `nlohmann_json::nlohmann_json` | All |
| libcurl | `curl[openssl]` | `CURL::libcurl` | Non-Windows, non-Apple |
| libcurl | `curl[openssl]` or `curl[mbedtls]` | `CURL::libcurl` | Non-Windows, non-Apple (required; TLS backend selectable: OpenSSL default or mbedTLS) |

On **macOS/iOS** the SDK links the OS-provided `libsqlite3` and `libz` (the same
system libraries the SDK's Swift Package links), so the vcpkg `sqlite3` and `zlib`
packages are not pulled there — those binaries carry no bundled SQLite/zlib.
(`minimal-sqlite` therefore has no effect on Apple.)

The external `sqlite3` package is provided by the default `system-sqlite`
feature. The `minimal-sqlite` feature replaces it with a private, feature-stripped
SQLite built from the SDK's vendored amalgamation — see
[Build a private minimal SQLite](#build-a-private-minimal-sqlite-minimal-sqlite-feature).

libcurl is provided by the default `curl-openssl` feature; `curl-mbedtls` swaps in
the mbedTLS backend — see
[Choose the HTTP client / TLS backend](#choose-the-http-client--tls-backend-largest-lever-on-linux).

Windows and macOS/iOS use platform-native HTTP clients (WinInet and
NSURLSession respectively). Android vcpkg consumers use native libcurl because
Expand Down Expand Up @@ -230,6 +244,54 @@ the stripping happens at your link. Keep the SDK a static dependency linked
*into* your binary: if you re-export its API across your own DLL boundary, the
export table pins its symbols and defeats `/OPT:REF`.

### Choose the HTTP client / TLS backend (largest lever on Linux)

On Linux/Android the built-in HTTP client is libcurl, and curl's TLS backend
dominates the SDK's footprint. (Windows uses WinInet and Apple uses NSURLSession,
so this section does not apply there.) The port exposes the TLS backend as two
mutually-exclusive features; pick the one that matches what your application
already has:

| Feature | Transport | Approx. stripped size¹ | Use when |
| ------- | --------- | ---------------------- | -------- |
| `curl-openssl` (default) | libcurl + OpenSSL | ~10.6 MB | your app already links OpenSSL (share it) |
| `curl-mbedtls` | libcurl + mbedTLS | ~4.4 MB | your app has no HTTP/TLS stack of its own |

¹ Rough sizes of a minimal Linux consumer **without** consumer-side dead-stripping
(worst case); enabling `-Wl,--gc-sections` at your link reduces them. Your numbers
depend on triplet, dead-stripping, and what else shares those libraries.

To select **mbedTLS**, two things are required in *your top-level* manifest:

```json
{
"dependencies": [
{
"name": "cpp-client-telemetry",
"default-features": false,
"features": [ "minimal-sqlite", "curl-mbedtls" ]
},
{ "name": "curl", "default-features": false, "features": [ "mbedtls" ] }
]
}
```

1. `"default-features": false` (the `[core,...]` form) drops **all** of the SDK's
default features -- both `curl-openssl` *and* `system-sqlite` -- so the SDK no
longer *requests* OpenSSL. Because it also drops `system-sqlite`, you must
re-select a SQLite backend (`minimal-sqlite` above, or `system-sqlite`);
otherwise the SDK configure step fails with no SQLite feature selected.
2. The explicit top-level `curl` entry is also needed because vcpkg honors curl's
own `"default-features": false` **only for top-level dependencies** — curl's
default `ssl` feature (which pulls OpenSSL on Linux) and `non-http` are
installed transitively otherwise. With both, curl resolves to `curl[core,mbedtls]`
and OpenSSL is not built; with only the feature, you get
`curl[mbedtls,ssl,openssl,non-http]` (mbedTLS *and* OpenSSL). This recipe is
verified with `vcpkg install --dry-run`.

The default install (no features specified) keeps `curl-openssl` and works out of
the box.

### Drop unused SQLite features (json1)

The SDK uses SQLite only for offline event storage — plain tables and indexes,
Expand All @@ -256,6 +318,65 @@ If any package in your build (or your own code) needs SQLite's JSON functions,
request `sqlite3[json1]` instead and the extension is restored for the whole
graph.

### Build a private minimal SQLite (`minimal-sqlite` feature)

For a larger, self-contained reduction, the port can compile a private,
feature-stripped SQLite directly from the SDK's vendored amalgamation instead of
linking the external `sqlite3` package at all. The SDK uses SQLite only for its
offline event-storage cache (plain tables and indexes, transactions, WAL,
autovacuum/`VACUUM`, a few PRAGMAs, and one custom UTF-8 SQL function), so this
build omits the unused SQLite subsystems — `SQLITE_OMIT_JSON` plus load-extension,
shared-cache, deprecated APIs, authorization, EXPLAIN, introspection pragmas,
deserialize, and more. The result is **~10% smaller SQLite code** (`.text`) and
**~13% smaller** as a stripped object, and it drops the external `sqlite3`
dependency from your graph entirely.

Enable it through the vcpkg feature:

```json
{
"dependencies": [
{
"name": "cpp-client-telemetry",
"default-features": false,
"features": [ "minimal-sqlite", "curl-openssl" ]
}
]
}
```

Use the `[core,minimal-sqlite]` form (here, `"default-features": false` is the
`[core]` part) so the default `system-sqlite` feature — and its `sqlite3`
dependency — is dropped. Because `[core]` drops **all** defaults, the example
also re-selects `curl-openssl`: on Linux/Android the built-in curl client
requires a TLS backend, so omitting it would fail to configure (swap in
`curl-mbedtls` for the smaller mbedTLS backend). Requesting `minimal-sqlite`
*without* `[core]` still pulls in the default `system-sqlite`; that is harmless
(the external `sqlite3` is installed but unused) but does not save the dependency.

For a plain (non-vcpkg) CMake build, pass the option directly:

```bash
cmake -DMATSDK_MINIMAL_SQLITE=ON ..
```

The strip is **amalgamation-safe**: it changes no SQLite grammar/parser, so no
code generation is required. All offline storage features the SDK relies on (WAL,
autovacuum, `VACUUM`, PRAGMAs, the custom UTF-8 function, blobs, 64-bit integers,
transactions) are retained, and the SDK's offline-storage unit tests pass
unchanged against the minimal build.

> **Caveat — symbol visibility when linking statically.** The private SQLite keeps
> SQLite's default `sqlite3_*` symbol names. For a **shared** `mat`
> (`mat.dll` / `libmat.so` / `libmat.dylib`), those symbols are hidden by the
> SDK's `-fvisibility=hidden`, so there is no conflict. For a **static** `mat`,
> the minimal SQLite is installed and exported as a separate
> `MSTelemetry::sqlite3_bundled` archive that links into your binary; if **any**
> part of the final static link — your own code *or another dependency* — also
> pulls in SQLite, the duplicate `sqlite3_*` symbols will collide at link time. In
> that case, prefer the default `system-sqlite` feature so the whole graph shares a
> single SQLite.

## How It Works: MATSDK_USE_VCPKG_DEPS

When the SDK detects it is being built via vcpkg (by checking for
Expand Down
Loading
Loading