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
9e8b49a
Add vcpkg-release-bump workflow to automate port version bumps
bmehta001 Jun 11, 2026
1662a46
Bump in-repo overlay port to v3.10.161.1 tag
bmehta001 Jun 11, 2026
136e010
docs(vcpkg): add manifest-mode overlay fallback for pre-registry inst…
bmehta001 Jun 11, 2026
5c345c8
vcpkg-bump: address Copilot force-with-lease comment + drop docs note
bmehta001 Jun 11, 2026
f28bddd
Update vcpkg docs: port is now live in the official registry
bmehta001 Jun 13, 2026
049c6e5
Align overlay port with the merged upstream vcpkg port
bmehta001 Jun 13, 2026
efcd72b
Fix vcpkg-bump PR existence check: jq null skipped PR creation
bmehta001 Jun 13, 2026
10b620e
Harden vcpkg-bump workflow: graceful no-op on non-version tags, no to…
bmehta001 Jun 13, 2026
4323df2
vcpkg-bump workflow: pass release tag via env to prevent shell injection
bmehta001 Jun 13, 2026
74d5af8
Enable function-level linking in the CMake build so consumers can dea…
bmehta001 Jun 15, 2026
54a0b06
Reword function-level-linking comment to justify the vcpkg-mode excep…
bmehta001 Jun 15, 2026
cd64ce2
Consolidate section-splitting flags into the global block (drop REL_F…
bmehta001 Jun 15, 2026
17473f5
vcpkg: request sqlite3 without default features (drop json1) + docs
bmehta001 Jun 16, 2026
c0a148e
docs(vcpkg): add consumer linker dead-strip guidance; clarify json1 o…
bmehta001 Jun 16, 2026
9f461ae
vcpkg(overlay): drop port-version
bmehta001 Jun 16, 2026
eddcb1f
docs(vcpkg): precise /DEBUG wording for /OPT:REF,ICF
bmehta001 Jun 18, 2026
7571daf
cmake: clarify AppleClang dead-strip comment (ld64 atomizes per symbol)
bmehta001 Jun 18, 2026
fd3f958
build: hide non-public symbols on non-Windows (-fvisibility=hidden)
bmehta001 Jun 18, 2026
5b34293
address Copilot round on #1475: clang-cl /Gw gating + workflow_dispat…
bmehta001 Jun 18, 2026
8a6d770
Merge branch 'main' into bhamehta/vcpkg-release-bump-workflow
bmehta001 Jun 19, 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
193 changes: 193 additions & 0 deletions .github/workflows/vcpkg-release-bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
name: Vcpkg release bump

# Opens a version-bump pull request against microsoft/vcpkg for the
# `cpp-client-telemetry` port whenever a new SDK release is published.
#
# It runs ONLY when a new version is cut:
# * automatically on a published, non-draft, non-prerelease GitHub Release
# whose tag looks like a version (vMAJOR.MINOR.PATCH.BUILD), or
# * manually via workflow_dispatch for a specific tag (recovery / re-run).
# It never runs on ordinary pushes, and it opens no PR if the port already
# matches the release (no version change).
#
# One-time setup required in this repository:
# * Variable VCPKG_FORK_REPO -> the vcpkg fork to push branches to,
# e.g. "your-org/vcpkg".
# * Secret VCPKG_BUMP_TOKEN -> a PAT (classic: repo+workflow, or
# fine-grained: Contents+Pull requests RW on
# the fork) able to push to VCPKG_FORK_REPO and
# open pull requests on microsoft/vcpkg.

on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Release tag to bump the vcpkg port to (e.g. v3.10.161.1)"
required: true
type: string

permissions:
contents: read

concurrency:
group: vcpkg-release-bump-${{ github.event.release.tag_name || github.event.inputs.tag }}
cancel-in-progress: false

jobs:
bump:
name: Bump cpp-client-telemetry port
# Skip drafts and pre-releases; always allow manual dispatch.
if: >-
${{ github.event_name == 'workflow_dispatch' ||
(github.event.release.draft == false && github.event.release.prerelease == false) }}
runs-on: ubuntu-latest
env:
UPSTREAM_REPO: ${{ github.repository }} # microsoft/cpp_client_telemetry
VCPKG_UPSTREAM: microsoft/vcpkg
VCPKG_FORK_REPO: ${{ vars.VCPKG_FORK_REPO }}
PORT: cpp-client-telemetry
steps:
- name: Validate configuration
env:
VCPKG_BUMP_TOKEN: ${{ secrets.VCPKG_BUMP_TOKEN }}
run: |
set -euo pipefail
if [ -z "${VCPKG_FORK_REPO}" ]; then
echo "::error::Repository variable VCPKG_FORK_REPO is not set (e.g. 'your-org/vcpkg')."
exit 1
fi
if [ -z "${VCPKG_BUMP_TOKEN}" ]; then
echo "::error::Secret VCPKG_BUMP_TOKEN is not set. Provide a token that can push to ${VCPKG_FORK_REPO} and open PRs on ${VCPKG_UPSTREAM}."
exit 1
fi

- name: Resolve tag and version
id: ver
env:
# Pass untrusted tag values through the environment instead of
# interpolating ${{ ... }} directly into the script body, so a tag
# containing shell metacharacters cannot inject commands into this
# step (which shares a runner with later PAT-bearing steps).
RELEASE_TAG: ${{ github.event.release.tag_name }}
INPUT_TAG: ${{ github.event.inputs.tag }}
run: |
set -euo pipefail
TAG="${RELEASE_TAG:-$INPUT_TAG}"
if [ -z "${TAG}" ]; then echo "::error::No release tag could be resolved."; exit 1; fi
# Only act on version tags: vMAJOR.MINOR.PATCH.BUILD. A non-matching
# tag from the automatic release trigger is a clean no-op (the SDK also
# has historical 3-part tags such as v3.3.8); a non-matching tag from a
# manual workflow_dispatch is user error and fails loudly.
if ! printf '%s' "${TAG}" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "::error::Tag '${TAG}' is not a version tag (expected vX.Y.Z.W)."
exit 1
fi
echo "::notice::Tag '${TAG}' is not a version tag (expected vX.Y.Z.W); nothing to bump."
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
VERSION="${TAG#v}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "branch=port/${PORT}-${VERSION}" >> "$GITHUB_OUTPUT"
echo "Bumping ${PORT} -> tag=${TAG} version=${VERSION}"

- name: Compute source archive SHA512
id: sha
if: ${{ steps.ver.outputs.skip != 'true' }}
run: |
set -euo pipefail
URL="https://github.com/${UPSTREAM_REPO}/archive/${{ steps.ver.outputs.tag }}.tar.gz"
echo "Downloading ${URL}"
curl -fsSL --retry 3 "${URL}" -o source.tar.gz
SHA512="$(sha512sum source.tar.gz | cut -d' ' -f1)"
echo "sha512=${SHA512}" >> "$GITHUB_OUTPUT"
echo "SHA512=${SHA512}"

- name: Clone vcpkg fork and branch off upstream master
if: ${{ steps.ver.outputs.skip != 'true' }}
env:
GH_TOKEN: ${{ secrets.VCPKG_BUMP_TOKEN }}
run: |
set -euo pipefail
# Authenticate git via gh's credential helper instead of embedding the
# token in the clone URL (which would persist it in .git/config and
# risk leaking it if git echoes the remote). The helper is written to
# the global gitconfig and reused by the later push step.
gh auth setup-git
git clone --depth 1 "https://github.com/${VCPKG_FORK_REPO}.git" vcpkg
cd vcpkg
git remote add upstream "https://github.com/${VCPKG_UPSTREAM}.git"
git fetch --depth 1 upstream master
git checkout -B "${{ steps.ver.outputs.branch }}" upstream/master
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Bootstrap vcpkg
if: ${{ steps.ver.outputs.skip != 'true' }}
run: cd vcpkg && ./bootstrap-vcpkg.sh -disableMetrics

- name: Update port REF, SHA512 and version
if: ${{ steps.ver.outputs.skip != 'true' }}
run: |
set -euo pipefail
cd vcpkg
PORTFILE="ports/${PORT}/portfile.cmake"
MANIFEST="ports/${PORT}/vcpkg.json"
if [ ! -f "${PORTFILE}" ] || [ ! -f "${MANIFEST}" ]; then
echo "::error::${PORT} port not found in ${VCPKG_UPSTREAM}. The port must already be in the registry before it can be bumped."
exit 1
fi
sed -i -E "s|^([[:space:]]*REF[[:space:]]+).*$|\1${{ steps.ver.outputs.tag }}|" "${PORTFILE}"
sed -i -E "s|^([[:space:]]*SHA512[[:space:]]+).*$|\1${{ steps.sha.outputs.sha512 }}|" "${PORTFILE}"
jq --arg v "${{ steps.ver.outputs.version }}" '.version = $v | del(."port-version")' "${MANIFEST}" > "${MANIFEST}.tmp"
mv "${MANIFEST}.tmp" "${MANIFEST}"
./vcpkg format-manifest "${MANIFEST}"

- name: Detect change
id: diff
if: ${{ steps.ver.outputs.skip != 'true' }}
run: |
set -euo pipefail
cd vcpkg
if git diff --quiet -- "ports/${PORT}"; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No change: ${PORT} is already at ${{ steps.ver.outputs.version }} with this REF/SHA512. Nothing to do."
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Commit, update version DB, push and open PR
if: ${{ steps.ver.outputs.skip != 'true' && steps.diff.outputs.changed == 'true' }}
env:
GH_TOKEN: ${{ secrets.VCPKG_BUMP_TOKEN }}
run: |
set -euo pipefail
cd vcpkg
# gh auth setup-git ran in the clone step; reuse that credential helper
# so 'git push' authenticates without a token in the remote URL.
BR="${{ steps.ver.outputs.branch }}"
git add "ports/${PORT}"
git commit -m "[${PORT}] Update to ${{ steps.ver.outputs.version }}"
./vcpkg x-add-version "${PORT}" --overwrite-version
git add versions
git commit -m "[${PORT}] Update version database"
# Ensure a remote-tracking ref exists so --force-with-lease has a lease
# to compare against on reruns: the bump branch may already exist on the
# fork but be absent from this fresh clone. Ignore failure on the first
# run, when the branch does not exist remotely yet.
git fetch origin "+refs/heads/${BR}:refs/remotes/origin/${BR}" || true
git push --force-with-lease origin "${BR}"
if [ -n "$(gh pr list --repo "${VCPKG_UPSTREAM}" --head "$(printf '%s' "${VCPKG_FORK_REPO}" | cut -d/ -f1):${BR}" --state open --json number --jq '.[0].number // empty' 2>/dev/null)" ]; then
echo "An open PR already exists for ${BR}; the force-pushed branch refreshes it."
else
gh pr create \
--repo "${VCPKG_UPSTREAM}" \
--base master \
--head "$(printf '%s' "${VCPKG_FORK_REPO}" | cut -d/ -f1):${BR}" \
--title "[${PORT}] Update to ${{ steps.ver.outputs.version }}" \
--body "Automated port bump to [\`${UPSTREAM_REPO}@${{ steps.ver.outputs.tag }}\`](https://github.com/${UPSTREAM_REPO}/releases/tag/${{ steps.ver.outputs.tag }}). Generated by the \`vcpkg-release-bump\` workflow."
fi
53 changes: 48 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,17 @@ else()
endif()

if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# Using GCC with -s and -Wl linker flags
set(REL_FLAGS "-s -Wl,--gc-sections -Os ${WARN_FLAGS} -ffunction-sections -fdata-sections -fmerge-all-constants")
# Using GCC with -s and -Wl linker flags. -ffunction-sections/-fdata-sections
# are set once for all dep modes by the global block further below.
set(REL_FLAGS "-s -Wl,--gc-sections -Os ${WARN_FLAGS} -fmerge-all-constants")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(REL_FLAGS "${WARN_FLAGS}")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
# AppleClang does not support -ffunction-sections and -fdata-sections with the -fembed-bitcode and -fembed-bitcode-marker
set(REL_FLAGS "-Os ${WARN_FLAGS} -fmerge-all-constants")
else()
# Using clang - strip unsupported GCC options
set(REL_FLAGS "-Os ${WARN_FLAGS} -ffunction-sections -fmerge-all-constants")
# Using clang - strip unsupported GCC options (-ffunction-sections is set by
# the global block further below).
set(REL_FLAGS "-Os ${WARN_FLAGS} -fmerge-all-constants")
endif()

## Uncomment this to reduce the volume of note warnings on RPi4 w/gcc-8 Ref. https://gcc.gnu.org/ml/gcc/2017-05/msg00073.html
Expand Down Expand Up @@ -206,6 +207,48 @@ endif()

endif() # NOT MATSDK_USE_VCPKG_DEPS (compiler flags)

# --- Dead-strip enablement (applies in BOTH vendored and vcpkg modes) ---------
# Deliberate exception to the "let the toolchain manage compiler flags" note
# above (the NOT MATSDK_USE_VCPKG_DEPS block): these flags are NOT optimization
# or dependency choices the vcpkg toolchain owns -- they only split functions and
# data into separate COMDATs/sections so a *consumer's* linker can drop
# unreferenced SDK code (MSVC /OPT:REF + /OPT:ICF, GNU/Clang --gc-sections, Apple
# ld -dead_strip). The toolchain does not set them, and the vcpkg-packaged
# library (and every MSVC build, which never gets /Gy from the block above) would
# otherwise link whole .obj files instead of individual functions. Applying them
# here in both modes closes that gap and matches the MSBuild Release projects,
# which already enable FunctionLevelLinking + OptimizeReferences + COMDATFolding.
if(MSVC)
# /Gy (function-level linking) is supported by both cl.exe and clang-cl.
add_compile_options(/Gy)
# /Gw (whole-program global data) is cl.exe-only; the ClangCL toolset (for
# which MSVC is also true) does not support it.
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_compile_options(/Gw)
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
# On Mach-O, clang emits .subsections_via_symbols, so ld64's -dead_strip
# already removes unreferenced code at per-symbol (function) granularity
# without -ffunction-sections; we add it only for cross-toolchain
# consistency. -fdata-sections is omitted because it historically conflicted
# with bitcode on AppleClang.
add_compile_options(-ffunction-sections)
else()
# GCC / Clang (Linux, Android, MinGW)
add_compile_options(-ffunction-sections -fdata-sections)
endif()
Comment thread
bmehta001 marked this conversation as resolved.

# Hidden symbol visibility (non-Windows): export only the MATSDK_LIBABI-decorated
# public API (classes + the C API), hiding SDK internals and the bundled
# sqlite3/zlib. This shrinks the dynamic symbol table (faster dynamic
# linking/loading, smaller binaries) and enables more inlining + dead-code
# elimination -- the non-Windows analog of what /Gy plus the consumer's /OPT:REF
# achieve on MSVC. Windows already restricts exports via __declspec(dllexport)
# on MATSDK_LIBABI (lib/include/public/ctmacros.hpp).
if(NOT MSVC)
add_compile_options(-fvisibility=hidden -fvisibility-inlines-hidden)
endif()

include(tools/Utils.cmake)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
Expand Down
69 changes: 65 additions & 4 deletions docs/building-with-vcpkg.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Building 1DS C++ SDK with vcpkg

[vcpkg](https://vcpkg.io/) is a Microsoft cross-platform open source C++ package manager. Onboarding instructions for Windows, Linux and Mac OS X [available here](https://docs.microsoft.com/en-us/cpp/build/vcpkg). This document assumes that the customer build system is already configured to use vcpkg ([getting started guide](https://learn.microsoft.com/en-us/vcpkg/get_started/overview)). 1DS C++ SDK maintainers provide a build recipe, `cpp-client-telemetry` port or CONTROL file for vcpkg. The mainline vcpkg repo is refreshed to point to latest stable open source release of 1DS C++ SDK.
[vcpkg](https://vcpkg.io/) is a Microsoft cross-platform open source C++ package manager. Onboarding instructions for Windows, Linux and Mac OS X [available here](https://docs.microsoft.com/en-us/cpp/build/vcpkg). This document assumes that the customer build system is already configured to use vcpkg ([getting started guide](https://learn.microsoft.com/en-us/vcpkg/get_started/overview)). The `cpp-client-telemetry` port is published in the official vcpkg registry, so it can be consumed directly with no overlay or extra configuration. Maintainers refresh the registry to point to the latest stable open source release of the 1DS C++ SDK on each release.

The port provides the core SDK — the `MSTelemetry::mat` target and its public
C++ headers. The optional Microsoft-proprietary modules (Privacy Guard,
Expand All @@ -16,7 +16,8 @@ git clone --recurse-submodules https://github.com/microsoft/cpp_client_telemetry

### Installing from the vcpkg registry

Once a new port has been accepted into the official vcpkg registry, install with:
The `cpp-client-telemetry` port is available in the [official vcpkg registry](https://github.com/microsoft/vcpkg/tree/master/ports/cpp-client-telemetry),
so you can install it directly — no overlay or extra configuration required:

```console
vcpkg install cpp-client-telemetry
Expand All @@ -26,8 +27,9 @@ That's it! The package should be compiled for the current OS.

### Installing from the overlay port (development / pre-release)

Before the port is published, or to test local changes, use the overlay port
shipped in this repository:
The overlay port shipped in this repository is for **development only** — use it
to test local changes to the port, or a newer SDK revision, before they are
published to the registry:

```console
git clone https://github.com/microsoft/cpp_client_telemetry
Expand Down Expand Up @@ -190,6 +192,65 @@ will automatically use the optimized zlib-ng build.
> zlib. When using `ZLIB_COMPAT=ON`, ensure all dependencies resolve to
> zlib-ng rather than mixing stock zlib and zlib-ng.

## Reducing binary footprint

The SDK links statically into your binary, so most footprint control lives on
*your* side of the link.

### Enable linker dead-stripping (largest lever)

The SDK is compiled with function-level linking (`/Gy /Gw` on MSVC,
`-ffunction-sections -fdata-sections` on GCC/Clang) so that **your** linker can
discard SDK code you never reference. Make sure your final link enables it:

- **MSVC:** `/OPT:REF` (drop unreferenced functions/data) and `/OPT:ICF` (fold
identical COMDATs). These are on by default for Release, **but `/DEBUG` flips
their default to off** (`/OPT:NOREF,NOICF`, per the MSVC `/OPT` docs) — so if
you ship PDBs, re-enable them explicitly. `/OPT:REF` is also incompatible with
incremental linking, so set `/INCREMENTAL:NO`:

```cmake
target_link_options(your_target PRIVATE
$<$<CONFIG:Release,RelWithDebInfo>:/OPT:REF>
$<$<CONFIG:Release,RelWithDebInfo>:/OPT:ICF>
$<$<CONFIG:Release,RelWithDebInfo>:/INCREMENTAL:NO>)
```

- **GCC / Clang:** link with `-Wl,--gc-sections`.
- **Apple (clang):** link with `-Wl,-dead_strip`.

This is by far the largest lever — on a static `x64-windows-static` Release link
it can roughly halve the binary. The SDK's `/Gy /Gw` flags only *enable* this;
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`.

### Drop unused SQLite features (json1)

The SDK uses SQLite only for offline event storage — plain tables and indexes,
with no JSON, FTS, R*Tree, or virtual-table features. This in-repo overlay port
already requests `sqlite3` with `default-features: false` on its dependency edge
(the published registry port will follow once this change is upstreamed).

vcpkg unions feature requests across the whole dependency graph, and a
transitive opt-out alone is **not** enough: you must **also** request `sqlite3`
with `default-features: false` in your own top-level manifest to actually omit
`json1` (which compiles SQLite with `SQLITE_OMIT_JSON`, ~50 KB smaller on a
static `x64-windows-static` Release build):

```json
{
"dependencies": [
"cpp-client-telemetry",
{ "name": "sqlite3", "default-features": false }
]
}
```

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.

## How It Works: MATSDK_USE_VCPKG_DEPS

When the SDK detects it is being built via vcpkg (by checking for
Expand Down
11 changes: 9 additions & 2 deletions lib/include/public/ctmacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@
#define MATSDK_LIBABI_CDECL
#endif

#ifndef MATSDK_LIBABI
#define MATSDK_LIBABI
#ifndef MATSDK_LIBABI
// Mark the public API as default-visibility so it stays exported when the SDK is
// built with -fvisibility=hidden (see CMakeLists.txt). This is the non-Windows
// analog of the __declspec(dllexport) gating above. Harmless without the flag.
# if defined(__GNUC__) || defined(__clang__)
# define MATSDK_LIBABI __attribute__((visibility("default")))
# else
# define MATSDK_LIBABI
# endif
#endif

// TODO: [MG] - ideally we'd like to use __attribute__((unused)) with gcc/clang
Expand Down
7 changes: 2 additions & 5 deletions tools/ports/cpp-client-telemetry/portfile.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO microsoft/cpp_client_telemetry
REF 4485b82005abf1d24336ace99b11df88dd578eb0
SHA512 1f3ee1c26f1ae9e7323262c9b4c8796efba2c6addcde432d6c6c77b8c1c2f254cb8ff334b1dd0a72dc8ecfbfbae04ab374ec5ac7e5d286d6042953d53e50fd5b
REF v3.10.161.1
SHA512 4664b34ddce601d6a95669df4a59d11a6cc67de1f23de132192f791a275edc6a10b8498d340e6cf7d120d9e7a22c494d7517b24fc0954bf9e236e84a8800589a
HEAD_REF main
)

Expand Down Expand Up @@ -46,8 +46,5 @@ vcpkg_cmake_config_fixup(PACKAGE_NAME MSTelemetry CONFIG_PATH lib/cmake/MSTeleme
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")
file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share")

# Install usage instructions
file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}")

# Install license
vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
Loading
Loading