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
65 changes: 60 additions & 5 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 @@ -363,10 +373,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,10 +408,40 @@ 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})
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 on lines +8 to +12
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