From cf3cdbc596c5f73c031d10536638bab3655dffb0 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 12 Oct 2026 16:38:05 +0200 Subject: [PATCH 1/5] Bump libdatadog to v45.0.0 Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 1 + LIBDATADOG_VERSION | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 191e079..e769ff3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -144,6 +144,7 @@ Output lands in `output/libdatadog-/`. For aarch64 Linux targets you n ## Recent Changes (Reverse Chronological) +- **2026-10**: Bumped to libdatadog v45 (from v38). Rust toolchain pin still `1.87.0` (v45's MSRV). The profiling, crashtracker and library-config headers are source compatible with v38 (only additions), so dd-trace-dotnet's native profiler builds unchanged; the musl builds import a few more libc symbols. - **2026-07**: Bumped to libdatadog v38 (from v36). Rust toolchain pin already at `1.87.0`, which matches v38's MSRV, so no toolchain change was needed. - **2026-06**: Bumped to libdatadog v36 (from v32). Rust toolchain pin already at `1.87.0`, which matches v36's MSRV, so no toolchain change was needed. - **2026-05**: aarch64-gnu switched from cross-rs cross-compile to QEMU + native manylinux2014_aarch64. Necessary because libdd-libunwind-sys (v30) can't be cross-compiled. diff --git a/LIBDATADOG_VERSION b/LIBDATADOG_VERSION index 531d2a4..74578d1 100644 --- a/LIBDATADOG_VERSION +++ b/LIBDATADOG_VERSION @@ -1 +1 @@ -38.0.0 +45.0.0 From b8d207fc3dbe38bbb76953e1a47a4dde885f9b4f Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Mon, 12 Oct 2026 17:38:58 +0200 Subject: [PATCH 2/5] Add datadog-dotnet-ffi with a remote configuration client FFI The shipped library is now built from datadog-dotnet-ffi: libdatadog's profiling FFI (same features as the builder) plus a remote configuration client for dd-trace-dotnet (ddog_rc_*), keeping the library names. --- .gitignore | 3 + AGENTS.md | 18 +- Cargo.toml | 15 + README.md | 11 +- build.ps1 | 93 ++- build.sh | 43 +- datadog-dotnet-ffi/Cargo.toml | 47 ++ datadog-dotnet-ffi/src/lib.rs | 12 + datadog-dotnet-ffi/src/remote_config.rs | 782 ++++++++++++++++++++++++ rustfmt.toml | 11 + tools/build-ffi.sh | 62 ++ 11 files changed, 1073 insertions(+), 24 deletions(-) create mode 100644 Cargo.toml create mode 100644 datadog-dotnet-ffi/Cargo.toml create mode 100644 datadog-dotnet-ffi/src/lib.rs create mode 100644 datadog-dotnet-ffi/src/remote_config.rs create mode 100644 rustfmt.toml create mode 100755 tools/build-ffi.sh diff --git a/.gitignore b/.gitignore index 2399aae..4223179 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ desktop.ini .claude/settings.local.json /output-test libdatadog/.claude/settings.local.json + +# libdatadog sources (checked out by the build scripts, or a symlink to a local checkout) +/libdatadog diff --git a/AGENTS.md b/AGENTS.md index e769ff3..6ce63ef 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,20 +8,25 @@ A thin packaging wrapper around the official [libdatadog](https://github.com/Dat ## Build Approach -We **don't** orchestrate cargo + cbindgen ourselves. We install libdatadog's own `release` binary (from its `builder` crate) and let it produce the package: +We **don't** orchestrate cbindgen ourselves. We check out libdatadog at the pinned tag into `libdatadog/` (gitignored), install its own `release` binary (from its `builder` crate) and let it produce the package, then replace the package's shared library with the `datadog-dotnet-ffi` build: ``` +git clone --depth 1 --branch "v${LIBDATADOG_VERSION}" https://github.com/DataDog/libdatadog libdatadog cargo install \ - --git https://github.com/DataDog/libdatadog \ - --tag "v${LIBDATADOG_VERSION}" \ + --path libdatadog/builder \ --bin release \ --no-default-features \ --features "profiling,crashtracker,symbolizer,library-config" \ builder release --out --target +tools/build-ffi.sh ``` -The builder handles the FFI cargo build, header generation (cbindgen + dedup), library stripping, and packaging. We just orchestrate per-platform Docker containers and (on Windows) reshape the resulting zip to match what dd-trace-dotnet expects. +The builder handles the FFI cargo build, header generation (cbindgen + dedup), library stripping, and packaging. We orchestrate per-platform Docker containers and (on Windows) reshape the resulting zip to match what dd-trace-dotnet expects. + +`datadog-dotnet-ffi` (the only Rust code here) is a cdylib that depends on libdatadog's crates by git revision (the `LIBDATADOG_VERSION` tag's commit, or a commit on top of it with unreleased changes — the headers come from the builder at the tag) and re-exports `libdd-profiling-ffi` (with the feature list the builder computes for our builder features — keep `datadog-dotnet-ffi/Cargo.toml` in sync with `builder/src/features.rs`), plus the .NET specific FFI (`src/remote_config.rs`: the remote configuration client used by dd-trace-dotnet). Its library is named `datadog_dotnet_ffi` (the dependency's own cdylib would collide otherwise), and `tools/build-ffi.sh` / `build.ps1` copy it over the builder's library under the original names (setting the soname / install name, and on Windows generating an import library for `datadog_profiling_ffi.dll`). It is built with libdatadog's `Cargo.lock`. + +Use `--libdatadog-path ../libdatadog` (`-LibdatadogPath`) to run the builder from a local libdatadog checkout; `libdatadog/` then is a symlink (junction on Windows), which is mounted at the same path into the build containers. To build `datadog-dotnet-ffi` against a local checkout, add a `[patch."https://github.com/DataDog/libdatadog"]` section with path dependencies. ## Version Pinning @@ -98,8 +103,11 @@ So `build.ps1`: ``` libdatadog-dotnet/ ├── LIBDATADOG_VERSION # Pinned upstream libdatadog tag (no "v") +├── Cargo.toml # Workspace (release profile = libdatadog's) +├── datadog-dotnet-ffi/ # The shipped library: profiling FFI + .NET specific FFI ├── build.sh # Linux/macOS — docker orchestration + macOS native ├── build.ps1 # Windows — runs builder twice, re-assembles legacy zip +├── tools/build-ffi.sh # Builds datadog-dotnet-ffi into a builder package ├── tools/docker/ │ ├── Dockerfile.centos # x86_64-gnu: cross-rs centos7 + devtoolset-10 │ ├── Dockerfile.centos-aarch64 # aarch64-gnu: manylinux2014_aarch64 + rustup @@ -144,6 +152,8 @@ Output lands in `output/libdatadog-/`. For aarch64 Linux targets you n ## Recent Changes (Reverse Chronological) +- **2026-10**: Added `datadog-dotnet-ffi`, which replaces the builder's shared library, with the remote configuration client FFI (`ddog_rc_*`) for dd-trace-dotnet. The builder is now installed from a `libdatadog/` checkout of the tag (or `--libdatadog-path`) instead of `cargo install --git`. `datadog-dotnet-ffi` uses libdatadog v45 plus the unreleased remote config changes (DataDog/libdatadog#2662) by git revision. + - **2026-10**: Bumped to libdatadog v45 (from v38). Rust toolchain pin still `1.87.0` (v45's MSRV). The profiling, crashtracker and library-config headers are source compatible with v38 (only additions), so dd-trace-dotnet's native profiler builds unchanged; the musl builds import a few more libc symbols. - **2026-07**: Bumped to libdatadog v38 (from v36). Rust toolchain pin already at `1.87.0`, which matches v38's MSRV, so no toolchain change was needed. - **2026-06**: Bumped to libdatadog v36 (from v32). Rust toolchain pin already at `1.87.0`, which matches v36's MSRV, so no toolchain change was needed. diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b7be311 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# ./libdatadog is the libdatadog checkout build.sh / build.ps1 install the builder from. + +[workspace] +members = ["datadog-dotnet-ffi"] +exclude = ["libdatadog"] +resolver = "2" + +# Same as libdatadog's release profile, which the builder uses for the profiling library. +[profile.release] +codegen-units = 1 +debug = "line-tables-only" +lto = true +opt-level = "s" diff --git a/README.md b/README.md index 09ab704..585c444 100644 --- a/README.md +++ b/README.md @@ -43,21 +43,26 @@ These are the builder-crate feature flags upstream libdatadog exposes — names ## How It Works -We install libdatadog's own `release` binary (from its `builder` crate) at the pinned tag, then let it produce the package: +We check out libdatadog at the pinned tag (into `libdatadog/`), install its own `release` binary (from its `builder` crate), let it produce the package, and then replace the package's shared library with our own build: ``` +git clone --depth 1 --branch "v${LIBDATADOG_VERSION}" https://github.com/DataDog/libdatadog libdatadog cargo install \ - --git https://github.com/DataDog/libdatadog \ - --tag "v${LIBDATADOG_VERSION}" \ + --path libdatadog/builder \ --bin release \ --no-default-features \ --features "" \ builder release --out --target +tools/build-ffi.sh ``` The builder handles the FFI cargo build, header generation (cbindgen + dedup), library stripping, and packaging. +The shared library itself (`libdatadog_profiling.{so,dylib}`, `datadog_profiling_ffi.dll`) comes from `datadog-dotnet-ffi`, this repository's crate: it re-exports libdatadog's profiling FFI (with the same features) and adds .NET specific FFI, like the remote configuration client (`ddog_rc_*`). It keeps the library name, so it's a drop-in replacement for the C++ profiler and the tracer. Only the .NET tracer uses the additional exports, so there are no headers for them. + +`datadog-dotnet-ffi` depends on libdatadog's crates by git revision (see `datadog-dotnet-ffi/Cargo.toml`), so it builds on its own; this can be a commit on top of the tag with unreleased changes. To run the builder from a local libdatadog checkout instead of the tag, pass `--libdatadog-path ../libdatadog` (`-LibdatadogPath` on Windows); to build `datadog-dotnet-ffi` against it, add a `[patch."https://github.com/DataDog/libdatadog"]` section with path dependencies. + **Windows quirk**: the builder produces a flat `lib/datadog_profiling.{dll,lib,pdb}` layout, but dd-trace-dotnet's vcpkg portfile expects the legacy `release/{dynamic,static}` + `debug/{dynamic,static}` tree with `_ffi`-suffixed filenames. `build.ps1` runs the builder twice (release + debug) and reassembles that layout from cargo's raw `target/` output. ## GLIBC Compatibility diff --git a/build.ps1 b/build.ps1 index 9101adb..5b8d9e9 100644 --- a/build.ps1 +++ b/build.ps1 @@ -12,7 +12,7 @@ # Produces a Windows zip with the legacy layout the .NET tracer's vcpkg # portfile and runtime DLL loader still expect: # -# release/dynamic/datadog_profiling_ffi.{dll,lib,pdb} (DLL + import lib) +# release/dynamic/datadog_profiling_ffi.{dll,lib,pdb} (DLL + import lib, from datadog-dotnet-ffi) # release/static/datadog_profiling_ffi.lib (static archive) # debug/dynamic/datadog_profiling_ffi.{dll,lib,pdb} # debug/static/datadog_profiling_ffi.lib @@ -24,12 +24,18 @@ # by name, the MSI installer references it, etc.). We therefore run the # builder once per profile (release + debug) and re-assemble the layout # from cargo's raw target/ outputs, which keep the _ffi names. +# +# The DLL itself is the datadog-dotnet-ffi library (see Cargo.toml): libdatadog's +# profiling FFI plus the .NET specific FFI. It is renamed to datadog_profiling_ffi.dll, +# with an import library generated for that name. param( [string]$Platform = "x64-windows", [string]$OutputDir = "output", [string]$Features = "profiling,crashtracker,symbolizer,library-config", - [switch]$Clean + [switch]$Clean, + # Build from a local libdatadog checkout instead of the tag in LIBDATADOG_VERSION + [string]$LibdatadogPath = "" ) $ErrorActionPreference = "Stop" @@ -71,6 +77,29 @@ New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null $OutputDir = (Resolve-Path $OutputDir).Path $PackageDir = Join-Path $OutputDir "libdatadog-$Platform" +# The libdatadog sources the builder is installed from: either a checkout of the release +# tag, or a junction to a local checkout. +$LibdatadogDir = Join-Path $PWD "libdatadog" +$LibdatadogItem = Get-Item $LibdatadogDir -ErrorAction SilentlyContinue +$IsLink = $LibdatadogItem -and $LibdatadogItem.LinkType +if ($LibdatadogPath) { + if ($LibdatadogItem -and -not $IsLink) { + Write-Host "Error: $LibdatadogDir exists and is not a link, remove it to use -LibdatadogPath" -ForegroundColor Red + exit 1 + } + if ($IsLink) { $LibdatadogItem.Delete() } + New-Item -ItemType Junction -Path $LibdatadogDir -Target (Resolve-Path $LibdatadogPath).Path | Out-Null +} elseif ($IsLink) { + Write-Host "Error: $LibdatadogDir links to a local checkout, pass -LibdatadogPath or remove it" -ForegroundColor Red + exit 1 +} elseif (-not $LibdatadogItem) { + git clone --quiet --depth 1 --branch "v${Version}" https://github.com/DataDog/libdatadog $LibdatadogDir + if ($LASTEXITCODE -ne 0) { Write-Host "Error: git clone failed" -ForegroundColor Red; exit 1 } +} elseif ((git -C $LibdatadogDir describe --tags --exact-match 2>$null) -ne "v${Version}") { + Write-Host "Error: $LibdatadogDir is not a checkout of v${Version}, remove it to check out the right version" -ForegroundColor Red + exit 1 +} + # Install the builder binary once. Each subsequent profile run reuses it. # Clear CARGO_BUILD_TARGET so `cargo install` compiles the builder for the # host (x86_64). The workflow sets CARGO_BUILD_TARGET=i686-pc-windows-msvc @@ -81,8 +110,7 @@ $PackageDir = Join-Path $OutputDir "libdatadog-$Platform" $savedTarget = $env:CARGO_BUILD_TARGET $env:CARGO_BUILD_TARGET = $null cargo install ` - --git https://github.com/DataDog/libdatadog ` - --tag "v${Version}" ` + --path libdatadog/builder ` --bin release ` --root .builder ` --no-default-features ` @@ -143,6 +171,49 @@ function Invoke-Builder { $ReleaseOut = Invoke-Builder -BuildProfile "release" $DebugOut = Invoke-Builder -BuildProfile "debug" +# Build datadog-dotnet-ffi, which replaces the profiling DLL. The PDB path embedded in the +# DLL already gets the final name. Uses the dependency versions libdatadog is tested with. +Copy-Item -Path (Join-Path $LibdatadogDir "Cargo.lock") -Destination (Join-Path $PWD "Cargo.lock") -Force +$env:CARGO_TARGET_DIR = $CargoTargetDir +$env:RUSTFLAGS = "-C relocation-model=pic -C target-feature=+crt-static -C link-arg=/PDBALTPATH:datadog_profiling_ffi.pdb" +foreach ($p in @("release", "debug")) { + $cargoProfile = if ($p -eq "debug") { "dev" } else { $p } + cargo build -p datadog-dotnet-ffi --target $Target --profile $cargoProfile + if ($LASTEXITCODE -ne 0) { + Write-Host "Error: building datadog-dotnet-ffi ($p) failed" -ForegroundColor Red + exit 1 + } +} +$env:RUSTFLAGS = $null + +# Creates an import library for $Dll under the name $DllName. +function New-ImportLibrary { + param([string]$Dll, [string]$DllName, [string]$OutLib) + + $vswhere = Join-Path ${env:ProgramFiles(x86)} "Microsoft Visual Studio\Installer\vswhere.exe" + $toolsBin = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ` + -find "VC\Tools\MSVC\**\bin\Hostx64\x64" | Select-Object -First 1 + if (-not $toolsBin) { + Write-Host "Error: MSVC tools not found" -ForegroundColor Red + exit 1 + } + $machine = if ($Target -like "i686-*") { "X86" } else { "X64" } + + # Lines like " 1 0 000A1B20 ddog_Error_drop" + $exports = & (Join-Path $toolsBin "dumpbin.exe") /nologo /exports $Dll | ForEach-Object { + if ($_ -match '^\s+\d+\s+[0-9A-F]+\s+[0-9A-F]{8}\s+(\S+)') { $Matches[1] } + } + $def = [IO.Path]::ChangeExtension($OutLib, ".def") + @("LIBRARY $DllName", "EXPORTS") + ($exports | ForEach-Object { " $_" }) | Set-Content -Encoding ascii $def + & (Join-Path $toolsBin "lib.exe") /nologo "/def:$def" "/machine:$machine" "/out:$OutLib" + if ($LASTEXITCODE -ne 0) { + Write-Host "Error: creating the import library failed" -ForegroundColor Red + exit 1 + } + Remove-Item $def + Remove-Item ([IO.Path]::ChangeExtension($OutLib, ".exp")) -ErrorAction SilentlyContinue +} + # --- Assemble the dd-trace-dotnet-compatible package --- Write-Host "Assembling legacy Windows package layout..." -ForegroundColor Yellow @@ -170,19 +241,19 @@ foreach ($f in @("LICENSE", "NOTICE", "LICENSE-3rdparty.csv")) { # - datadog_profiling_ffi.dll.lib (import library for the cdylib) # - datadog_profiling_ffi.lib (staticlib) # - datadog_profiling_ffi.pdb -# The builder copies the .dll and the staticlib .lib but does not copy the -# import library, so we pick all four directly from the cargo target dir. -# The import library is renamed .dll.lib -> .lib in the dynamic slot to match -# what the tracer's vcpkg portfile expects. +# The static slot gets that staticlib. The dynamic slot gets the datadog-dotnet-ffi +# DLL and PDB instead, renamed, with a generated datadog_profiling_ffi.lib import library +# (the import library cargo produces refers to datadog_dotnet_ffi.dll). foreach ($p in @("release", "debug")) { $cargoOut = Join-Path $CargoTargetDir "$Target/$p" $dynDir = Join-Path $PackageDir "$p/dynamic" $staticDir = Join-Path $PackageDir "$p/static" New-Item -ItemType Directory -Force -Path $dynDir, $staticDir | Out-Null - Copy-Item -Path (Join-Path $cargoOut "datadog_profiling_ffi.dll") -Destination (Join-Path $dynDir "datadog_profiling_ffi.dll") - Copy-Item -Path (Join-Path $cargoOut "datadog_profiling_ffi.dll.lib") -Destination (Join-Path $dynDir "datadog_profiling_ffi.lib") - Copy-Item -Path (Join-Path $cargoOut "datadog_profiling_ffi.pdb") -Destination (Join-Path $dynDir "datadog_profiling_ffi.pdb") + Copy-Item -Path (Join-Path $cargoOut "datadog_dotnet_ffi.dll") -Destination (Join-Path $dynDir "datadog_profiling_ffi.dll") + Copy-Item -Path (Join-Path $cargoOut "datadog_dotnet_ffi.pdb") -Destination (Join-Path $dynDir "datadog_profiling_ffi.pdb") + New-ImportLibrary -Dll (Join-Path $dynDir "datadog_profiling_ffi.dll") -DllName "datadog_profiling_ffi.dll" ` + -OutLib (Join-Path $dynDir "datadog_profiling_ffi.lib") Copy-Item -Path (Join-Path $cargoOut "datadog_profiling_ffi.lib") -Destination (Join-Path $staticDir "datadog_profiling_ffi.lib") } diff --git a/build.sh b/build.sh index e5d526c..518bc64 100755 --- a/build.sh +++ b/build.sh @@ -18,6 +18,7 @@ OUTPUT_DIR="output" PROFILE="release" FEATURES="" CLEAN=false +LIBDATADOG_PATH="" while [[ $# -gt 0 ]]; do case $1 in @@ -26,6 +27,7 @@ while [[ $# -gt 0 ]]; do --profile) PROFILE="$2"; shift 2 ;; --features) FEATURES="$2"; shift 2 ;; --clean) CLEAN=true; shift ;; + --libdatadog-path) LIBDATADOG_PATH="$2"; shift 2 ;; -h|--help) echo "Usage: $0 --platform PLATFORM [OPTIONS]" echo "" @@ -37,6 +39,8 @@ while [[ $# -gt 0 ]]; do echo " (default: profiling,crashtracker," echo " symbolizer,library-config)" echo " --clean Remove output directory before building" + echo " --libdatadog-path P Build from a local libdatadog checkout instead of" + echo " the tag in LIBDATADOG_VERSION" echo " -h, --help Show this help" echo "" echo "Environment variables:" @@ -78,6 +82,29 @@ mkdir -p "$OUTPUT_DIR" OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)" PACKAGE_DIR="$OUTPUT_DIR/libdatadog-${PLATFORM:-$TARGET}" +# The libdatadog sources the builder is installed from: either a checkout of the release +# tag, or a symlink to a local checkout. +LIBDATADOG_DIR="$SCRIPT_DIR/libdatadog" +DOCKER_LIBDATADOG_MOUNT=() +if [[ -n "$LIBDATADOG_PATH" ]]; then + LIBDATADOG_PATH="$(cd "$LIBDATADOG_PATH" && pwd)" + if [[ -e "$LIBDATADOG_DIR" && ! -L "$LIBDATADOG_DIR" ]]; then + echo "Error: $LIBDATADOG_DIR exists and is not a symlink, remove it to use --libdatadog-path" >&2 + exit 1 + fi + ln -sfn "$LIBDATADOG_PATH" "$LIBDATADOG_DIR" + # Mounted at the same path, so that the symlink also resolves inside the containers + DOCKER_LIBDATADOG_MOUNT=(-v "$LIBDATADOG_PATH:$LIBDATADOG_PATH") +elif [[ -L "$LIBDATADOG_DIR" ]]; then + echo "Error: $LIBDATADOG_DIR is a symlink to a local checkout, pass --libdatadog-path or remove it" >&2 + exit 1 +elif [[ ! -e "$LIBDATADOG_DIR" ]]; then + git clone --quiet --depth 1 --branch "v${VERSION}" https://github.com/DataDog/libdatadog "$LIBDATADOG_DIR" +elif [[ "$(git -C "$LIBDATADOG_DIR" describe --tags --exact-match 2>/dev/null)" != "v${VERSION}" ]]; then + echo "Error: $LIBDATADOG_DIR is not a checkout of v${VERSION}, remove it to check out the right version" >&2 + exit 1 +fi + # docker_run_gnu IMAGE TARGET PLATFORM # Runs the builder inside an x86_64 GNU/glibc container (CentOS 7 sysroot). # The host Rust toolchain is mounted read-write so that: @@ -98,6 +125,7 @@ docker_run_gnu() { -v "${cargo_home}:/usr/local/cargo" \ -v "${rustup_home}:/usr/local/rustup" \ -v "$SCRIPT_DIR:/workspace" \ + "${DOCKER_LIBDATADOG_MOUNT[@]}" \ -w /workspace \ -e CARGO_HOME=/usr/local/cargo \ -e RUSTUP_HOME=/usr/local/rustup \ @@ -115,8 +143,7 @@ docker_run_gnu() { # binary without interference from any RUSTFLAGS overrides. unset CARGO_ENCODED_RUSTFLAGS cargo install \ - --git https://github.com/DataDog/libdatadog \ - --tag "v${BUILDER_VERSION}" \ + --path /workspace/libdatadog/builder \ --bin release \ --root /tmp/builder \ --no-default-features \ @@ -149,6 +176,8 @@ docker_run_gnu() { /tmp/builder/bin/release \ --out "/workspace/output/libdatadog-${BUILDER_PLATFORM}" \ --target "${BUILDER_TARGET}" + sh tools/build-ffi.sh "${BUILDER_TARGET}" "${BUILDER_PROFILE}" \ + "/workspace/output/libdatadog-${BUILDER_PLATFORM}" ' } @@ -167,6 +196,7 @@ docker_run_musl() { -v "$HOME/.cargo/registry:/root/.cargo/registry" \ -v "$HOME/.cargo/git:/root/.cargo/git" \ -v "$SCRIPT_DIR:/workspace" \ + "${DOCKER_LIBDATADOG_MOUNT[@]}" \ -w /workspace \ -e CARGO_HOME=/root/.cargo \ -e BUILDER_VERSION="$VERSION" \ @@ -182,8 +212,7 @@ docker_run_musl() { # binary without interference from any RUSTFLAGS overrides. unset CARGO_ENCODED_RUSTFLAGS cargo install \ - --git https://github.com/DataDog/libdatadog \ - --tag "v${BUILDER_VERSION}" \ + --path /workspace/libdatadog/builder \ --bin release \ --root /tmp/builder \ --no-default-features \ @@ -227,6 +256,8 @@ docker_run_musl() { /tmp/builder/bin/release \ --out "/workspace/output/libdatadog-${BUILDER_PLATFORM}" \ --target "${BUILDER_TARGET}" + sh tools/build-ffi.sh "${BUILDER_TARGET}" "${BUILDER_PROFILE}" \ + "/workspace/output/libdatadog-${BUILDER_PLATFORM}" ' } @@ -266,8 +297,7 @@ case "$TARGET" in # handles cross-compilation internally (e.g. x86_64 on an arm64 runner). unset CARGO_BUILD_TARGET cargo install \ - --git https://github.com/DataDog/libdatadog \ - --tag "v${VERSION}" \ + --path libdatadog/builder \ --bin release \ --root .builder \ --no-default-features \ @@ -298,6 +328,7 @@ case "$TARGET" in .builder/bin/release \ --out "$PACKAGE_DIR" \ --target "$TARGET" + sh tools/build-ffi.sh "$TARGET" "$PROFILE" "$PACKAGE_DIR" ;; *) echo "Error: unsupported target '$TARGET'" >&2 diff --git a/datadog-dotnet-ffi/Cargo.toml b/datadog-dotnet-ffi/Cargo.toml new file mode 100644 index 0000000..945e3e7 --- /dev/null +++ b/datadog-dotnet-ffi/Cargo.toml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "datadog-dotnet-ffi" +version = "0.1.0" +edition = "2024" +rust-version = "1.87.0" +license = "Apache-2.0" +publish = false +description = "The libdatadog library shipped with the .NET tracer: libdatadog's profiling FFI plus .NET specific FFI" + +[lib] +# Shipped as libdatadog_profiling.{so,dylib} / datadog_profiling_ffi.dll, see build.sh / build.ps1. +# The name must differ from libdd-profiling-ffi's own library to avoid colliding outputs. +name = "datadog_dotnet_ffi" +crate-type = ["cdylib"] +bench = false + +[dependencies] +anyhow = { version = "1.0", default-features = false, features = ["std"] } +function_name = { version = "0.3.0", default-features = false } +strum = { version = "0.26", default-features = false } +tokio = { version = "1.49", default-features = false, features = ["macros", "net", "rt", "time"] } +tokio-util = { version = "0.7.11", default-features = false } + +# libdatadog v45 (LIBDATADOG_VERSION, which the builder is built from) plus the unreleased +# remote config changes of DataDog/libdatadog#2662. +libdd-capabilities-impl = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false } +libdd-common = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false } +libdd-common-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["std"] } +libdd-remote-config = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["client"] } +# Must be the feature list the libdatadog builder computes for the libdatadog-dotnet builder +# features (profiling,crashtracker,symbolizer,library-config), see builder/src/features.rs. +libdd-profiling-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = [ + "ddcommon-ffi", + "catch_panic", + "crashtracker-ffi", + "crashtracker-collector", + "crashtracker-receiver", + "demangler", + "symbolizer", + "datadog-library-config-ffi", +] } + +[dev-dependencies] +libdd-remote-config = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["client", "test"] } +tokio = { version = "1.49", default-features = false, features = ["rt-multi-thread"] } diff --git a/datadog-dotnet-ffi/src/lib.rs b/datadog-dotnet-ffi/src/lib.rs new file mode 100644 index 0000000..8160fda --- /dev/null +++ b/datadog-dotnet-ffi/src/lib.rs @@ -0,0 +1,12 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +#![cfg_attr(not(test), deny(clippy::panic))] +#![cfg_attr(not(test), deny(clippy::unwrap_used))] +#![cfg_attr(not(test), deny(clippy::expect_used))] + +// Re-export the whole profiling library (profiling, crashtracker, symbolizer, library-config), +// so that this library is a drop-in replacement for it. +pub use datadog_profiling_ffi::*; + +pub mod remote_config; diff --git a/datadog-dotnet-ffi/src/remote_config.rs b/datadog-dotnet-ffi/src/remote_config.rs new file mode 100644 index 0000000..4f6f6e5 --- /dev/null +++ b/datadog-dotnet-ffi/src/remote_config.rs @@ -0,0 +1,782 @@ +// Copyright 2026-Present Datadog, Inc. https://www.datadoghq.com/ +// SPDX-License-Identifier: Apache-2.0 + +//! Remote configuration client for the .NET tracer. +//! +//! The tracer drives the polling: each [`ddog_rc_client_fetch`] call performs one request to the +//! agent, blocking the calling thread, and returns the configurations which changed since the +//! previous call. The contents of added or updated configurations are shared with the caller +//! without being copied: they stay valid until the caller passes their owner to +//! [`ddog_rc_content_drop`]. + +use function_name::named; +use libdd_capabilities_impl::{HttpClientCapability, NativeCapabilities}; +use libdd_common::Endpoint; +use libdd_common_ffi::slice::{AsBytes, CharSlice, Slice}; +use libdd_common_ffi::{VoidResult, wrap_with_void_ffi_result}; +use libdd_remote_config::fetch::{ + ConfigApplyState, ConfigInvariants, ConfigOptions, SingleFetcher, +}; +use libdd_remote_config::file_change_tracker::{Change, ChangeTracker, FilePath, UpdatedFiles}; +use libdd_remote_config::file_storage::{ParseFile, RawFile, RawFileStorage}; +use libdd_remote_config::{ + RemoteConfigCapabilities, RemoteConfigPath, RemoteConfigProduct, Target, +}; +use std::ffi::c_void; +use std::str::FromStr; +use std::sync::{Arc, Mutex}; +use std::time::Duration; +use strum::IntoEnumIterator; +use tokio_util::sync::CancellationToken; + +/// Stores the contents in an `Arc`, which is shared with the tracer when handing them out. +#[derive(Clone, Default)] +struct SharedBytesParser; + +impl ParseFile for SharedBytesParser { + type Parsed = Arc>; + + fn parse(&self, _path: &RemoteConfigPath, contents: Vec) -> Arc> { + Arc::new(contents) + } +} + +type File = RawFile>>; +type Fetcher = SingleFetcher, NativeCapabilities>; + +struct RcClientInner { + runtime: tokio::runtime::Runtime, + /// Only None while being replaced by a new instance, see [`RcClient::rebind`]. + fetcher: Option, + /// Tracks what was delivered to the tracer, so it outlives the fetcher instances. + tracker: ChangeTracker, +} + +fn fetcher_lost() -> anyhow::Error { + anyhow::anyhow!("The remote config client is unusable after a failed rebind") +} + +impl RcClientInner { + fn fetcher(&mut self) -> anyhow::Result<&mut Fetcher> { + self.fetcher.as_mut().ok_or_else(fetcher_lost) + } +} + +pub struct RcClient { + inner: Mutex, + cancel: CancellationToken, +} + +#[repr(C)] +pub struct RcTarget<'a> { + pub service: CharSlice<'a>, + pub env: CharSlice<'a>, + pub app_version: CharSlice<'a>, + /// `key:value` formatted tags. + pub tags: Slice<'a, CharSlice<'a>>, + /// `key:value` formatted process tags. + pub process_tags: Slice<'a, CharSlice<'a>>, +} + +/// The products and capabilities are set with [`ddog_rc_client_set_products`]. +#[repr(C)] +pub struct RcClientConfig<'a> { + pub language: CharSlice<'a>, + pub tracer_version: CharSlice<'a>, + pub runtime_id: CharSlice<'a>, + pub client_id: CharSlice<'a>, + pub target: RcTarget<'a>, +} + +pub const DDOG_RC_CHANGE_UPSERT: u32 = 0; +pub const DDOG_RC_CHANGE_REMOVE: u32 = 1; + +#[repr(C)] +pub struct RcChange { + /// The version of the config; 0 for removals. + pub version: u64, + /// The config path, e.g. `datadog/2/ASM_DD/blocking/config`. Valid until the changes are + /// dropped. + pub path_ptr: *const u8, + pub path_len: usize, + /// The contents of an added or updated config. Valid until passing `contents_owner` to + /// [`ddog_rc_content_drop`], independently of the changes. + pub contents_ptr: *const u8, + pub contents_len: usize, + /// Null for removals. + pub contents_owner: *mut c_void, + /// [`DDOG_RC_CHANGE_UPSERT`] or [`DDOG_RC_CHANGE_REMOVE`]. + pub kind: u32, +} + +/// The removals come first, then the added or updated configs. +#[repr(C)] +pub struct RcChanges { + pub ptr: *const RcChange, + pub len: usize, + /// Owns the changes and their paths, released by [`ddog_rc_changes_drop`]. + owner: *mut c_void, +} + +struct ChangesBatch { + changes: Vec, + /// Keeps the paths alive. + files: Vec>, +} + +impl ChangesBatch { + fn push(&mut self, file: Arc, upserted: bool) { + let (kind, version, contents_ptr, contents_len, contents_owner) = if upserted { + let contents = file.contents().clone(); + let (ptr, len) = (contents.as_ptr(), contents.len()); + let owner = Arc::into_raw(contents) as *mut c_void; + (DDOG_RC_CHANGE_UPSERT, file.version(), ptr, len, owner) + } else { + ( + DDOG_RC_CHANGE_REMOVE, + 0, + std::ptr::null(), + 0, + std::ptr::null_mut(), + ) + }; + let path = file.path().as_str(); + self.changes.push(RcChange { + version, + path_ptr: path.as_ptr(), + path_len: path.len(), + contents_ptr, + contents_len, + contents_owner, + kind, + }); + self.files.push(file); + } + + fn into_ffi(self) -> RcChanges { + let batch = Box::new(self); + RcChanges { + ptr: batch.changes.as_ptr(), + len: batch.changes.len(), + owner: Box::into_raw(batch) as *mut c_void, + } + } +} + +fn to_string(slice: CharSlice) -> anyhow::Result { + Ok(slice.try_to_utf8()?.to_string()) +} + +fn to_strings(slices: Slice) -> anyhow::Result> { + slices.iter().map(|s| to_string(*s)).collect() +} + +fn to_target(target: &RcTarget) -> anyhow::Result { + Ok(Target::new( + to_string(target.service)?, + to_string(target.env)?, + to_string(target.app_version)?, + to_strings(target.tags)?, + to_strings(target.process_tags)?, + )) +} + +/// Unknown products are skipped, and reported as error once the known ones are applied. +fn to_products( + products: Slice, +) -> anyhow::Result<(Vec, Vec)> { + let mut known = vec![]; + let mut unknown = vec![]; + for product in products.iter() { + let product = product.try_to_utf8()?; + match RemoteConfigProduct::from_str(product) { + Ok(product) => known.push(product), + Err(_) => unknown.push(product.to_string()), + } + } + Ok((known, unknown)) +} + +fn to_capabilities(capabilities: u64) -> Vec { + RemoteConfigCapabilities::iter() + .filter(|c| (*c as u32) < 64 && capabilities & (1 << (*c as u32)) != 0) + .collect() +} + +fn report_unknown_products(unknown: Vec) -> anyhow::Result<()> { + if unknown.is_empty() { + Ok(()) + } else { + anyhow::bail!("Unsupported remote config products: {}", unknown.join(", ")) + } +} + +impl RcClient { + fn new(config: &RcClientConfig, endpoint: &Endpoint) -> anyhow::Result { + let runtime = tokio::runtime::Builder::new_current_thread() + .enable_all() + // Only needed for DNS resolution. + .max_blocking_threads(1) + .thread_keep_alive(Duration::from_secs(1)) + .build()?; + let fetcher = SingleFetcher::new_no_agentless( + RawFileStorage::default(), + to_target(&config.target)?, + to_string(config.runtime_id)?, + ConfigOptions { + invariants: ConfigInvariants { + language: to_string(config.language)?, + tracer_version: to_string(config.tracer_version)?, + endpoint: endpoint.clone(), + agentless: None, + }, + products: vec![], + capabilities: vec![], + }, + NativeCapabilities::new_periodic(), + ) + .with_client_id(to_string(config.client_id)?); + Ok(RcClient { + inner: Mutex::new(RcClientInner { + runtime, + fetcher: Some(fetcher), + tracker: ChangeTracker::default(), + }), + cancel: CancellationToken::new(), + }) + } + + fn lock(&self) -> anyhow::Result> { + self.inner + .lock() + .map_err(|_| anyhow::anyhow!("The remote config client is unusable after a panic")) + } + + /// Replaces the fetcher with a new instance for `target` and `endpoint` (if any, otherwise the + /// current one), which takes over the known files of the previous one. + fn rebind(&self, target: Target, endpoint: Option) -> anyhow::Result<()> { + let mut guard = self.lock()?; + let inner = &mut *guard; + let previous = inner.fetcher.take().ok_or_else(fetcher_lost)?; + inner.fetcher = Some(inner.runtime.block_on(previous.rebind(target, endpoint))?); + Ok(()) + } + + fn fetch(&self) -> anyhow::Result { + let mut guard = self.lock()?; + let RcClientInner { + runtime, + fetcher, + tracker, + } = &mut *guard; + let fetcher = fetcher.as_mut().ok_or_else(fetcher_lost)?; + let cancel = &self.cancel; + let files = runtime.block_on(async { + tokio::select! { + biased; + _ = cancel.cancelled() => anyhow::bail!("The remote config client was cancelled"), + files = fetcher.fetch_once() => files, + } + })?; + + let mut batch = ChangesBatch { + changes: vec![], + files: vec![], + }; + let Some(files) = files else { + return Ok(batch); + }; + let updated = fetcher.file_storage().updated(); + for change in tracker.get_changes(files, updated) { + match change { + Change::Remove(file) => batch.push(file, false), + Change::Add(file) | Change::Update(file, _) => { + fetcher.set_config_state(file.path(), ConfigApplyState::Unacknowledged); + batch.push(file, true); + } + } + } + Ok(batch) + } +} + +/// Creates a remote config client for the agent at `endpoint` (see `ddog_endpoint_from_url`), +/// which is copied. The client does nothing until [`ddog_rc_client_fetch`] is called. +/// +/// # Safety +/// All slices in `config` must be valid. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub unsafe extern "C" fn ddog_rc_client_new( + config: &RcClientConfig, + endpoint: &Endpoint, + out_client: &mut *mut RcClient, +) -> VoidResult { + wrap_with_void_ffi_result!({ + *out_client = Box::into_raw(Box::new(RcClient::new(config, endpoint)?)); + }) +} + +/// # Safety +/// `client` must be null or come from [`ddog_rc_client_new`], and not be in use by any other +/// thread. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn ddog_rc_client_drop(client: *mut RcClient) { + if !client.is_null() { + drop(unsafe { Box::from_raw(client) }); + } +} + +/// Aborts an ongoing fetch and makes all further fetches fail immediately. May be called from +/// any thread, e.g. while shutting down. +#[unsafe(no_mangle)] +pub extern "C" fn ddog_rc_client_cancel(client: &RcClient) { + client.cancel.cancel(); +} + +/// Switches to another target (service, env, version, tags) and, if `endpoint` is not null, +/// another agent endpoint (which is copied), with a new fetcher instance (and client session) +/// taking over the known files. Unchanged files are neither downloaded again nor reported as +/// changed. +/// +/// # Safety +/// All slices must be valid. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub unsafe extern "C" fn ddog_rc_client_rebind( + client: &RcClient, + target: &RcTarget, + endpoint: Option<&Endpoint>, +) -> VoidResult { + wrap_with_void_ffi_result!({ + client.rebind(to_target(target)?, endpoint.cloned())?; + }) +} + +/// Replaces the subscribed products (names like `ASM_DD`) and the capabilities (bit n set for the +/// capability with index n). Unsupported products are reported as error, after applying the +/// supported ones. +/// +/// # Safety +/// All slices must be valid. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub unsafe extern "C" fn ddog_rc_client_set_products( + client: &RcClient, + products: Slice, + capabilities: u64, +) -> VoidResult { + wrap_with_void_ffi_result!({ + let (products, unknown) = to_products(products)?; + client + .lock()? + .fetcher()? + .set_product_capabilities(products, to_capabilities(capabilities)); + report_unknown_products(unknown)?; + }) +} + +/// Replaces the services discovered at runtime, which are sent to the agent with each request. +/// +/// # Safety +/// All slices must be valid. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub unsafe extern "C" fn ddog_rc_client_set_extra_services( + client: &RcClient, + services: Slice, +) -> VoidResult { + wrap_with_void_ffi_result!({ + let services = to_strings(services)?; + client.lock()?.fetcher()?.set_extra_services(services); + }) +} + +/// Polls the agent once, blocking until the response is processed or the request timed out. +/// On success, `out_changes` must be released with [`ddog_rc_changes_drop`]. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub extern "C" fn ddog_rc_client_fetch( + client: &RcClient, + out_changes: &mut RcChanges, +) -> VoidResult { + wrap_with_void_ffi_result!({ + *out_changes = client.fetch()?.into_ffi(); + }) +} + +/// Sets the apply state reported for a config: 1 = unacknowledged, 2 = acknowledged, 3 = error +/// (with `error` as message). +/// +/// # Safety +/// All slices must be valid. +#[unsafe(no_mangle)] +#[must_use] +#[named] +pub unsafe extern "C" fn ddog_rc_client_set_apply_state( + client: &RcClient, + path: CharSlice, + state: u32, + error: CharSlice, +) -> VoidResult { + wrap_with_void_ffi_result!({ + let path = RemoteConfigPath::parse(path.try_to_utf8()?)?; + let state = match state { + 1 => ConfigApplyState::Unacknowledged, + 2 => ConfigApplyState::Acknowledged, + 3 => ConfigApplyState::Error(to_string(error)?), + _ => anyhow::bail!("Invalid apply state {state}"), + }; + client.lock()?.fetcher()?.set_config_state(&path, state); + }) +} + +/// Releases the changes, but not the contents of the configs, see [`ddog_rc_content_drop`]. +/// +/// # Safety +/// `changes` must come from [`ddog_rc_client_fetch`] and must not be used afterwards. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn ddog_rc_changes_drop(changes: RcChanges) { + if !changes.owner.is_null() { + drop(unsafe { Box::from_raw(changes.owner as *mut ChangesBatch) }); + } +} + +/// Releases the contents of a config. +/// +/// # Safety +/// `owner` must be null or the `contents_owner` of a change, and must not be used afterwards. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn ddog_rc_content_drop(owner: *mut c_void) { + if !owner.is_null() { + drop(unsafe { Arc::from_raw(owner as *const Vec) }); + } +} + +impl Default for RcChanges { + fn default() -> Self { + RcChanges { + ptr: std::ptr::null(), + len: 0, + owner: std::ptr::null_mut(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libdd_common_ffi::endpoint::ddog_endpoint_from_url; + use libdd_remote_config::fetch::test_server::RemoteConfigServer; + + fn slices(strings: &[&'static str]) -> Vec> { + strings.iter().map(|s| CharSlice::from(*s)).collect() + } + + struct Fixture { + server: Arc, + _server_runtime: tokio::runtime::Runtime, + client: *mut RcClient, + tags: Vec>, + } + + impl Fixture { + fn new() -> Fixture { + let server_runtime = tokio::runtime::Runtime::new().unwrap(); + let server = server_runtime.block_on(async { RemoteConfigServer::spawn() }); + Fixture { + server, + _server_runtime: server_runtime, + client: std::ptr::null_mut(), + tags: slices(&["key:value"]), + } + } + + fn target(&self, service: &'static str) -> RcTarget<'_> { + RcTarget { + service: service.into(), + env: "env".into(), + app_version: "1.2.3".into(), + tags: Slice::new(&self.tags), + process_tags: Slice::empty(), + } + } + + fn create(&mut self, url: &str) -> VoidResult { + let mut client = std::ptr::null_mut(); + let endpoint = ddog_endpoint_from_url(CharSlice::from(url)).unwrap(); + let config = RcClientConfig { + language: "dotnet".into(), + tracer_version: "3.0.0".into(), + runtime_id: "runtime-id".into(), + client_id: "client-id".into(), + target: self.target("first"), + }; + let result = unsafe { ddog_rc_client_new(&config, &endpoint, &mut client) }; + self.client = client; + result + } + + fn set_products(&self, products: &[&'static str]) -> VoidResult { + let products = slices(products); + unsafe { + ddog_rc_client_set_products( + self.client(), + Slice::new(&products), + 1 << RemoteConfigCapabilities::ApmTracingCustomTags as u32, + ) + } + } + + /// Creates the client, subscribed to APM_TRACING. + fn start(&mut self) { + let url = self.server.endpoint.url.to_string(); + self.create(&url).unwrap(); + self.set_products(&["APM_TRACING"]).unwrap(); + } + + fn client(&self) -> &RcClient { + unsafe { &*self.client } + } + + fn add_file(&self, id: &str, services: &[&str], contents: &str) { + let targets = services + .iter() + .map(|s| { + Arc::new(Target::new( + s.to_string(), + "env".to_string(), + "1.2.3".to_string(), + vec![], + vec![], + )) + }) + .collect(); + self.server.files.lock().unwrap().insert( + RemoteConfigPath::parse(&format!("datadog/2/APM_TRACING/{id}/config")).unwrap(), + (targets, 1, contents.to_string()), + ); + } + + /// Returns (kind, path, contents) and releases everything. + fn fetch(&self) -> Vec<(u32, String, Option)> { + let mut changes = RcChanges::default(); + ddog_rc_client_fetch(self.client(), &mut changes).unwrap(); + let result = unsafe { std::slice::from_raw_parts(changes.ptr, changes.len) } + .iter() + .map(|c| unsafe { + let path = + std::str::from_utf8(std::slice::from_raw_parts(c.path_ptr, c.path_len)) + .unwrap() + .to_string(); + let contents = (!c.contents_owner.is_null()).then(|| { + String::from_utf8( + std::slice::from_raw_parts(c.contents_ptr, c.contents_len).to_vec(), + ) + .unwrap() + }); + (c.kind, path, contents, c.contents_owner) + }) + .collect::>(); + unsafe { ddog_rc_changes_drop(changes) }; + result + .into_iter() + .map(|(kind, path, contents, owner)| { + unsafe { ddog_rc_content_drop(owner) }; + (kind, path, contents) + }) + .collect() + } + + fn last_request_state(&self) -> RequestState { + let request = self.server.last_request.lock().unwrap(); + let client = request.as_ref().unwrap().client.as_ref().unwrap(); + let state = client.state.as_ref().unwrap(); + RequestState { + service: client.client_tracer.as_ref().unwrap().service.clone(), + targets_version: state.targets_version, + config_states: state + .config_states + .iter() + .map(|s| (s.id.clone(), s.apply_state, s.apply_error.clone())) + .collect(), + cached_files: request.as_ref().unwrap().cached_target_files.len(), + } + } + } + + struct RequestState { + service: String, + targets_version: u64, + config_states: Vec<(String, u64, String)>, + cached_files: usize, + } + + impl Drop for Fixture { + fn drop(&mut self) { + unsafe { ddog_rc_client_drop(self.client) }; + } + } + + const UPSERT: u32 = DDOG_RC_CHANGE_UPSERT; + const REMOVE: u32 = DDOG_RC_CHANGE_REMOVE; + + fn path(id: &str) -> String { + format!("datadog/2/APM_TRACING/{id}/config") + } + + #[test] + #[cfg_attr(miri, ignore)] + fn subscribes_to_known_products_and_reports_unknown_ones() { + let mut fixture = Fixture::new(); + fixture.start(); + assert!(matches!( + fixture.set_products(&["NOT_A_PRODUCT", "ASM_DD"]), + VoidResult::Err(_) + )); + fixture.fetch(); + let request = fixture.server.last_request.lock().unwrap(); + let client = request.as_ref().unwrap().client.as_ref().unwrap(); + assert_eq!(client.products, ["ASM_DD"]); + // Capability 15, big endian + assert_eq!(client.capabilities, [0x80, 0x00]); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn delivers_changes_and_apply_states() { + let mut fixture = Fixture::new(); + fixture.start(); + + fixture.add_file("a", &["first"], "{\"a\":1}"); + fixture.add_file("b", &["first"], "{\"b\":1}"); + let mut changes = fixture.fetch(); + changes.sort(); + assert_eq!( + changes, + [ + (UPSERT, path("a"), Some("{\"a\":1}".to_string())), + (UPSERT, path("b"), Some("{\"b\":1}".to_string())), + ] + ); + + unsafe { + ddog_rc_client_set_apply_state( + fixture.client(), + path("a").as_str().into(), + 2, + CharSlice::empty(), + ) + .unwrap(); + ddog_rc_client_set_apply_state( + fixture.client(), + path("b").as_str().into(), + 3, + "broken".into(), + ) + .unwrap(); + } + + fixture + .server + .files + .lock() + .unwrap() + .remove(&RemoteConfigPath::parse(&path("a")).unwrap()); + fixture.add_file("b", &["first"], "{\"b\":2}"); + assert_eq!( + fixture.fetch(), + [ + (REMOVE, path("a"), None), + (UPSERT, path("b"), Some("{\"b\":2}".to_string())), + ] + ); + let mut states = fixture.last_request_state().config_states; + states.sort(); + assert_eq!( + states, + [ + ("a".to_string(), 2, String::new()), + ("b".to_string(), 3, "broken".to_string()) + ] + ); + + // Nothing changed + assert_eq!(fixture.fetch(), []); + assert_eq!( + fixture.last_request_state().config_states, + [("b".to_string(), 1, String::new())] + ); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn rebind_reports_only_differences() { + let mut fixture = Fixture::new(); + fixture.start(); + + fixture.add_file("only_first", &["first"], "1"); + fixture.add_file("shared", &["first", "second"], "2"); + fixture.add_file("only_second", &["second"], "3"); + assert_eq!(fixture.fetch().len(), 2); + + let url = fixture.server.endpoint.url.to_string(); + let target = fixture.target("second"); + let endpoint = ddog_endpoint_from_url(url.as_str().into()).unwrap(); + unsafe { ddog_rc_client_rebind(fixture.client(), &target, Some(&endpoint)) }.unwrap(); + assert_eq!( + fixture.fetch(), + [ + (REMOVE, path("only_first"), None), + (UPSERT, path("only_second"), Some("3".to_string())), + ] + ); + let state = fixture.last_request_state(); + assert_eq!(state.service, "second"); + assert_eq!(state.targets_version, 0); + assert_eq!(state.cached_files, 2); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn contents_outlive_the_client() { + let mut fixture = Fixture::new(); + fixture.start(); + fixture.add_file("a", &["first"], "contents"); + + let mut changes = RcChanges::default(); + ddog_rc_client_fetch(fixture.client(), &mut changes).unwrap(); + let change = unsafe { &*changes.ptr }; + let (ptr, len, owner) = ( + change.contents_ptr, + change.contents_len, + change.contents_owner, + ); + unsafe { + ddog_rc_changes_drop(changes); + ddog_rc_client_drop(fixture.client); + } + fixture.client = std::ptr::null_mut(); + assert_eq!(unsafe { std::slice::from_raw_parts(ptr, len) }, b"contents"); + unsafe { ddog_rc_content_drop(owner) }; + } + + #[test] + #[cfg_attr(miri, ignore)] + fn cancelled_client_fails_fast() { + let mut fixture = Fixture::new(); + // Nothing listens there: the fetch would otherwise fail by itself + fixture.create("http://127.0.0.1:1").unwrap(); + ddog_rc_client_cancel(fixture.client()); + let mut changes = RcChanges::default(); + let VoidResult::Err(err) = ddog_rc_client_fetch(fixture.client(), &mut changes) else { + panic!("expected an error"); + }; + assert!(err.as_ref().contains("cancelled"), "{}", err.as_ref()); + } +} diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..241143b --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,11 @@ +unstable_features = true + +ignore = [ +] + +format_macro_matchers = true +format_code_in_doc_comments=true +wrap_comments = true +max_width=100 +comment_width=100 +doc_comment_code_block_width=100 diff --git a/tools/build-ffi.sh b/tools/build-ffi.sh new file mode 100755 index 0000000..17d2936 --- /dev/null +++ b/tools/build-ffi.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# +# Builds the datadog-dotnet-ffi library (libdatadog's profiling FFI plus the .NET specific FFI, +# e.g. remote config) and replaces the profiling shared library of the package produced by +# libdatadog's builder with it, keeping its name. +# +# Usage: tools/build-ffi.sh TARGET PROFILE PACKAGE_DIR +# Runs on the host (macOS) or inside the build containers, right after the builder, so that +# it gets the same environment (compilers, CARGO_ENCODED_RUSTFLAGS, ...). + +set -e + +TARGET="$1" +PROFILE="$2" +PACKAGE_DIR="$3" + +cd "$(dirname "$0")/.." + +# Build with the dependency versions libdatadog itself is tested with. +cp libdatadog/Cargo.lock Cargo.lock + +case "$TARGET" in + *-apple-darwin) + LIB=libdatadog_profiling.dylib + BUILT=libdatadog_dotnet_ffi.dylib + LINK_ARG="-Wl,-install_name,@rpath/$LIB" + ;; + *) + LIB=libdatadog_profiling.so + BUILT=libdatadog_dotnet_ffi.so + LINK_ARG="-Wl,-soname,$LIB" + ;; +esac + +# The musl builds pass their flags (including the soname) via CARGO_ENCODED_RUSTFLAGS. +if [ -z "$CARGO_ENCODED_RUSTFLAGS" ]; then + export RUSTFLAGS="-C relocation-model=pic -C link-arg=$LINK_ARG" +fi + +case "$PROFILE" in + debug|dev) CARGO_PROFILE=dev; PROFILE_DIR=debug ;; + *) CARGO_PROFILE="$PROFILE"; PROFILE_DIR="$PROFILE" ;; +esac + +cargo build -p datadog-dotnet-ffi --target "$TARGET" --profile "$CARGO_PROFILE" + +cp "target/$TARGET/$PROFILE_DIR/$BUILT" "$PACKAGE_DIR/lib/$LIB" + +# Same post-processing as libdatadog's builder (builder/src/arch/*.rs) +case "$TARGET" in + *-apple-darwin) + strip -S "$PACKAGE_DIR/lib/$LIB" + ;; + *) + objcopy --only-keep-debug "$PACKAGE_DIR/lib/$LIB" "$PACKAGE_DIR/lib/libdatadog_profiling.debug" + strip -S "$PACKAGE_DIR/lib/$LIB" + objcopy --add-gnu-debuglink="$PACKAGE_DIR/lib/libdatadog_profiling.debug" "$PACKAGE_DIR/lib/$LIB" + ;; +esac + +echo "Replaced $PACKAGE_DIR/lib/$LIB with the datadog-dotnet-ffi library" From ae38177198828ede3468a9ff645dcc62ebf7651e Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Wed, 14 Oct 2026 16:46:14 +0200 Subject: [PATCH 3/5] Remove LIBDATADOG_VERSION in favor of the git dependencies The libdatadog revision is pinned by the git dependencies of datadog-dotnet-ffi only. The builder is installed from cargo's checkout of them (tools/libdatadog.sh), so the headers and static libraries match the shipped library; --libdatadog-path patches them to a local checkout. datadog-dotnet-ffi gets its own target directory: some libdatadog crates have library file names without a hash, which the builder's and our build overwrote for each other. Co-Authored-By: Claude Opus 5.5 --- .../skills/bump-libdatadog-version/SKILL.md | 56 ++++++++------- .github/workflows/build-platform.yml | 2 +- .github/workflows/release.yml | 2 +- .gitignore | 3 - AGENTS.md | 22 +++--- Cargo.toml | 3 - LIBDATADOG_VERSION | 1 - README.md | 11 ++- build.ps1 | 68 +++++++++++-------- build.sh | 61 ++++++++--------- datadog-dotnet-ffi/Cargo.toml | 2 - tools/build-ffi.sh | 9 ++- tools/libdatadog.sh | 28 ++++++++ 13 files changed, 149 insertions(+), 119 deletions(-) delete mode 100644 LIBDATADOG_VERSION create mode 100755 tools/libdatadog.sh diff --git a/.cursor/skills/bump-libdatadog-version/SKILL.md b/.cursor/skills/bump-libdatadog-version/SKILL.md index f44eeb6..7a099fe 100644 --- a/.cursor/skills/bump-libdatadog-version/SKILL.md +++ b/.cursor/skills/bump-libdatadog-version/SKILL.md @@ -4,17 +4,19 @@ description: >- Bump the pinned upstream libdatadog version for libdatadog-dotnet. Use when the user says "Bump to the latest version of libdatadog", "Bump to libdatadog vX.Y.Z", or otherwise asks to upgrade / update the libdatadog version in this - repo. Handles the LIBDATADOG_VERSION file and any required Rust toolchain pin - update. + repo. Handles the libdatadog git dependencies in datadog-dotnet-ffi/Cargo.toml + and any required Rust toolchain pin update. disable-model-invocation: true --- # Bump libdatadog Version Upgrades the pinned upstream [libdatadog](https://github.com/DataDog/libdatadog) -version for this packaging repo. The version lives in a single file -(`LIBDATADOG_VERSION`, no `v` prefix), and a correct bump may also require a -Rust toolchain pin update. +version for this packaging repo. The version is the `tag` (e.g. +`tag = "v32.0.0"`) of all libdatadog git dependencies in +`datadog-dotnet-ffi/Cargo.toml` (a `rev = ""` while unreleased libdatadog +changes are used), and a correct bump may also require a Rust toolchain pin +update. ## Workflow @@ -22,7 +24,7 @@ Copy this checklist and track progress: ``` - [ ] Step 1: Resolve the target version -- [ ] Step 2: Update LIBDATADOG_VERSION +- [ ] Step 2: Update the libdatadog dependencies in datadog-dotnet-ffi/Cargo.toml - [ ] Step 3: Check upstream Rust MSRV; update the pin if changed - [ ] Step 4: Check the macOS runner pin (only if MSRV/toolchain shifted) - [ ] Step 5: Update AGENTS.md "Recent Changes" + README if needed @@ -40,14 +42,19 @@ curl -fsSL https://api.github.com/repos/DataDog/libdatadog/releases/latest \ | grep -m1 '"tag_name"' | sed -E 's/.*"tag_name": *"v?([^"]+)".*/\1/' ``` -Read the current pin with the Read tool on `LIBDATADOG_VERSION`. If it already -equals the target, tell the user and stop. Otherwise **remember this value as -`OLD_VERSION`** — Step 2 overwrites the file, and Step 3 needs the old version -to detect an MSRV change. +Read the current pin (the `tag` or `rev` of the libdatadog dependencies) with +the Read tool on `datadog-dotnet-ffi/Cargo.toml`. If it already is +`tag = "v"`, tell the user and stop. Otherwise **remember the tag or +commit as `OLD_REF`** — Step 2 overwrites it, and Step 3 needs the old one to +detect an MSRV change. -### Step 2: Update LIBDATADOG_VERSION +### Step 2: Update the libdatadog dependencies -Write the bare version (no `v`, single trailing newline) to `LIBDATADOG_VERSION`. +Set `tag = "v"` (replacing `tag = ...` or `rev = ...`) on **every** +libdatadog git dependency in `datadog-dotnet-ffi/Cargo.toml` — they must all +use the same version — and update the comment above them. Then make sure it +still builds (`cargo test -p datadog-dotnet-ffi`), and that the +`libdd-profiling-ffi` feature list still matches `builder/src/features.rs`. ### Step 3: Check upstream Rust MSRV; update the pin if changed @@ -56,20 +63,20 @@ with a different toolchain than upstream can introduce subtle codegen / ABI differences. The MSRV lives in `rust-version` under `[workspace.package]` in libdatadog's root `Cargo.toml`. -Compare the MSRV at the **target** tag against the MSRV at the **`OLD_VERSION`** -tag (the value captured in Step 1) — don't compare against a hardcoded number, -since the repo's pin moves over time, and don't re-read `LIBDATADOG_VERSION` +Compare the MSRV at the **target** tag against the MSRV at **`OLD_REF`** (the +value captured in Step 1) — don't compare against a hardcoded number, since the +repo's pin moves over time, and don't re-read `datadog-dotnet-ffi/Cargo.toml` here (Step 2 already overwrote it with `TARGET`, so it would falsely report no change): ```bash -extract_msrv() { # $1 = libdatadog tag without leading v - curl -fsSL "https://raw.githubusercontent.com/DataDog/libdatadog/v$1/Cargo.toml" \ +extract_msrv() { # $1 = libdatadog tag (with leading v) or commit + curl -fsSL "https://raw.githubusercontent.com/DataDog/libdatadog/$1/Cargo.toml" \ | grep -i 'rust-version' | head -n1 \ | sed -E 's/.*"([0-9]+\.[0-9]+(\.[0-9]+)?)".*/\1/' } -echo "old: $(extract_msrv )" # the pin captured in Step 1 -echo "target: $(extract_msrv )" +echo "old: $(extract_msrv )" # the pin captured in Step 1 +echo "target: $(extract_msrv v)" ``` - **Same value** → MSRV unchanged, leave the toolchain alone. Skip to Step 4. @@ -89,7 +96,7 @@ Then update **all** of these from the old MSRV to the target MSRV: - `tools/docker/Dockerfile.musl-aarch64` — `ARG RUST_VERSION` - `README.md` — the prerequisites line -Keep this in the **same commit** as the `LIBDATADOG_VERSION` bump — the two are +Keep this in the **same commit** as the libdatadog bump — the two are coupled (building the new version with the old toolchain is exactly the mismatch the pin guards against). The change is picked up automatically on the next build; there are no prebuilt/pushed images to refresh: @@ -115,8 +122,9 @@ revisit it if upstream moved its macOS build image; the `os:` fields live in - Add a dated entry to the top of the **Recent Changes** list in `AGENTS.md` (e.g. `- **YYYY-MM**: Bumped to libdatadog v.` and note the MSRV change if any). -- The README's libdatadog references are version-agnostic (they read the file), - so only edit it if the Rust pin changed (Step 3). +- The README's libdatadog references are version-agnostic (they point to + `datadog-dotnet-ffi/Cargo.toml`), so only edit it if the Rust pin changed + (Step 3). ### Step 6: Summarize and propose next steps @@ -128,11 +136,11 @@ Report what changed (version, and MSRV pin if touched). Then offer to: Do not commit or open a PR unless the user asks. **Always flag the coordinated-rollout caveat** so the bump isn't mistaken for a -complete, self-contained change: bumping `LIBDATADOG_VERSION` (and cutting a +complete, self-contained change: bumping libdatadog (and cutting a release) here is fine on its own, but libdatadog's profiling FFI API drifts between tags. The new version is only proven compatible once the dd-trace-dotnet PR that adopts the new libdatadog-dotnet **release tag** (e.g. `v1.3.5` — a -different number from `LIBDATADOG_VERSION`) compiles its native profiler +different number from the libdatadog version) compiles its native profiler (`cor_profiler.cpp`, `dd_profiler_constants.h`) against the matching profiling headers in the same rollout. This is a coordination requirement on the tracer side, **not** a precondition that blocks the bump here. diff --git a/.github/workflows/build-platform.yml b/.github/workflows/build-platform.yml index 485cec4..8f937c1 100644 --- a/.github/workflows/build-platform.yml +++ b/.github/workflows/build-platform.yml @@ -91,7 +91,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ runner.os }}-cargo-${{ hashFiles('LIBDATADOG_VERSION') }} + key: ${{ runner.os }}-cargo-${{ hashFiles('datadog-dotnet-ffi/Cargo.toml') }} restore-keys: | ${{ runner.os }}-cargo- diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7b43ae2..d740449 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -211,7 +211,7 @@ jobs: cat > release-notes.md << 'NOTES_EOF' ## Build Information - - **Libdatadog version**: see `LIBDATADOG_VERSION` in this repository + - **Libdatadog version**: see the libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml` in this repository ## Checksums diff --git a/.gitignore b/.gitignore index 4223179..2399aae 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,3 @@ desktop.ini .claude/settings.local.json /output-test libdatadog/.claude/settings.local.json - -# libdatadog sources (checked out by the build scripts, or a symlink to a local checkout) -/libdatadog diff --git a/AGENTS.md b/AGENTS.md index 6ce63ef..b546519 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,12 +8,11 @@ A thin packaging wrapper around the official [libdatadog](https://github.com/Dat ## Build Approach -We **don't** orchestrate cbindgen ourselves. We check out libdatadog at the pinned tag into `libdatadog/` (gitignored), install its own `release` binary (from its `builder` crate) and let it produce the package, then replace the package's shared library with the `datadog-dotnet-ffi` build: +We **don't** orchestrate cbindgen ourselves. We install libdatadog's own `release` binary (from its `builder` crate) from the sources `datadog-dotnet-ffi` is built from — cargo's checkout of its libdatadog dependencies, found by `tools/libdatadog.sh` via `cargo metadata` — and let it produce the package, then replace the package's shared library with the `datadog-dotnet-ffi` build: ``` -git clone --depth 1 --branch "v${LIBDATADOG_VERSION}" https://github.com/DataDog/libdatadog libdatadog cargo install \ - --path libdatadog/builder \ + --path "$(tools/libdatadog.sh dir)/builder" \ --bin release \ --no-default-features \ --features "profiling,crashtracker,symbolizer,library-config" \ @@ -24,17 +23,17 @@ tools/build-ffi.sh The builder handles the FFI cargo build, header generation (cbindgen + dedup), library stripping, and packaging. We orchestrate per-platform Docker containers and (on Windows) reshape the resulting zip to match what dd-trace-dotnet expects. -`datadog-dotnet-ffi` (the only Rust code here) is a cdylib that depends on libdatadog's crates by git revision (the `LIBDATADOG_VERSION` tag's commit, or a commit on top of it with unreleased changes — the headers come from the builder at the tag) and re-exports `libdd-profiling-ffi` (with the feature list the builder computes for our builder features — keep `datadog-dotnet-ffi/Cargo.toml` in sync with `builder/src/features.rs`), plus the .NET specific FFI (`src/remote_config.rs`: the remote configuration client used by dd-trace-dotnet). Its library is named `datadog_dotnet_ffi` (the dependency's own cdylib would collide otherwise), and `tools/build-ffi.sh` / `build.ps1` copy it over the builder's library under the original names (setting the soname / install name, and on Windows generating an import library for `datadog_profiling_ffi.dll`). It is built with libdatadog's `Cargo.lock`. +`datadog-dotnet-ffi` (the only Rust code here) is a cdylib that depends on libdatadog's crates from git (see [Version Pinning](#version-pinning)) and re-exports `libdd-profiling-ffi` (with the feature list the builder computes for our builder features — keep `datadog-dotnet-ffi/Cargo.toml` in sync with `builder/src/features.rs`), plus the .NET specific FFI (`src/remote_config.rs`: the remote configuration client used by dd-trace-dotnet). Its library is named `datadog_dotnet_ffi` (the dependency's own cdylib would collide otherwise), and `tools/build-ffi.sh` / `build.ps1` copy it over the builder's library under the original names (setting the soname / install name, and on Windows generating an import library for `datadog_profiling_ffi.dll`). It is built with libdatadog's `Cargo.lock`. -Use `--libdatadog-path ../libdatadog` (`-LibdatadogPath`) to run the builder from a local libdatadog checkout; `libdatadog/` then is a symlink (junction on Windows), which is mounted at the same path into the build containers. To build `datadog-dotnet-ffi` against a local checkout, add a `[patch."https://github.com/DataDog/libdatadog"]` section with path dependencies. +Use `--libdatadog-path ../libdatadog` (`-LibdatadogPath`) to build against a local libdatadog checkout, e.g. to test libdatadog changes: the build scripts patch the libdatadog dependencies of `datadog-dotnet-ffi` to it (a `[patch]` in `target/libdatadog-patch.toml`, passed to cargo with `--config` via `LIBDATADOG_PATCH`), so the builder comes from there too. It is mounted at the same path into the build containers. ## Version Pinning -`LIBDATADOG_VERSION` (single file, no `v` prefix, e.g. `32.0.0`) is the **upstream** libdatadog version this repo builds from. It is distinct from libdatadog-dotnet's own release tag (e.g. `v1.3.5`) that dd-trace-dotnet pins — don't expect the two numbers to be equal. +The `tag` (e.g. `tag = "v32.0.0"`) of the libdatadog git dependencies in `datadog-dotnet-ffi/Cargo.toml` is the **upstream** libdatadog version this repo builds from — all of them must use the same one. To depend on unreleased libdatadog changes, use `rev = ""` instead, and go back to a tag once they are released. The builder comes from the same sources, so the headers always match the library; the package version passed to it (pkg-config) is the libdatadog workspace version of those sources. It is distinct from libdatadog-dotnet's own release tag (e.g. `v1.3.5`) that dd-trace-dotnet pins — don't expect the two numbers to be equal. ⚠️ **The chosen libdatadog version must be API-compatible with dd-trace-dotnet's native profiler C++.** The tracer's profiler (`cor_profiler.cpp`, `dd_profiler_constants.h`) calls libdatadog's profiling FFI (`ddog_prof_SampleType`, `DDOG_PROF_SAMPLE_TYPE_*`, …), and that API drifts between libdatadog tags. A mismatch surfaces in the tracer build as cryptic C++ errors like `error C2061: 'ddog_prof_SampleType'`. -This is a **coordinated** change, not a precondition. You *can* bump `LIBDATADOG_VERSION` and cut a release ahead of the tracer — the tracer won't reference the new release yet, and that's expected. The requirement is only that the dd-trace-dotnet PR which adopts the new libdatadog-dotnet release also builds against its profiling headers in the same rollout, so the native profiler compiles against the matching API. +This is a **coordinated** change, not a precondition. You *can* bump the libdatadog version and cut a release ahead of the tracer — the tracer won't reference the new release yet, and that's expected. The requirement is only that the dd-trace-dotnet PR which adopts the new libdatadog-dotnet release also builds against its profiling headers in the same rollout, so the native profiler compiles against the matching API. ## Per-Platform Build Setup @@ -102,12 +101,13 @@ So `build.ps1`: ``` libdatadog-dotnet/ -├── LIBDATADOG_VERSION # Pinned upstream libdatadog tag (no "v") ├── Cargo.toml # Workspace (release profile = libdatadog's) -├── datadog-dotnet-ffi/ # The shipped library: profiling FFI + .NET specific FFI +├── datadog-dotnet-ffi/ # The shipped library: profiling FFI + .NET specific FFI; +│ # its Cargo.toml pins the upstream libdatadog version ├── build.sh # Linux/macOS — docker orchestration + macOS native ├── build.ps1 # Windows — runs builder twice, re-assembles legacy zip ├── tools/build-ffi.sh # Builds datadog-dotnet-ffi into a builder package +├── tools/libdatadog.sh # Locates the libdatadog sources (for the builder) ├── tools/docker/ │ ├── Dockerfile.centos # x86_64-gnu: cross-rs centos7 + devtoolset-10 │ ├── Dockerfile.centos-aarch64 # aarch64-gnu: manylinux2014_aarch64 + rustup @@ -121,7 +121,7 @@ libdatadog-dotnet/ ## Common Tasks -**Update libdatadog version**: edit `LIBDATADOG_VERSION` (the upstream libdatadog version this repo builds from). Ensure the target libdatadog's profiling FFI is API-compatible with dd-trace-dotnet's native profiler C++ — the tracer adopts the resulting libdatadog-dotnet release in a coordinated PR; it won't already reference it. See [Version Pinning](#version-pinning). +**Update libdatadog version**: change the `tag` of the libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml` (the upstream libdatadog version this repo builds from). Ensure the target libdatadog's profiling FFI is API-compatible with dd-trace-dotnet's native profiler C++ — the tracer adopts the resulting libdatadog-dotnet release in a coordinated PR; it won't already reference it. See [Version Pinning](#version-pinning). **Change feature set**: edit the `FEATURES` default in `build.sh`, the `Features` default in `build.ps1`, and the `features` input default in `build-platform.yml` / `release.yml` / `build.yml`. Feature names are the builder crate's high-level features (`profiling`, `crashtracker`, `data-pipeline`, `symbolizer`, `library-config`, `log`, `telemetry`, `ddsketch`, `ffe`, `otel-thread-ctx`, `shared-runtime`, `regex-lite`), not the underlying cargo features — e.g. the builder's `otel-thread-ctx` feature internally maps to the `otel-thread-ctx-ffi` FFI crate (see `builder/src/bin/release.rs` in libdatadog), so pass `otel-thread-ctx` here, never the FFI crate name. @@ -152,7 +152,7 @@ Output lands in `output/libdatadog-/`. For aarch64 Linux targets you n ## Recent Changes (Reverse Chronological) -- **2026-10**: Added `datadog-dotnet-ffi`, which replaces the builder's shared library, with the remote configuration client FFI (`ddog_rc_*`) for dd-trace-dotnet. The builder is now installed from a `libdatadog/` checkout of the tag (or `--libdatadog-path`) instead of `cargo install --git`. `datadog-dotnet-ffi` uses libdatadog v45 plus the unreleased remote config changes (DataDog/libdatadog#2662) by git revision. +- **2026-10**: Added `datadog-dotnet-ffi`, which replaces the builder's shared library, with the remote configuration client FFI (`ddog_rc_*`) for dd-trace-dotnet. The libdatadog version is now pinned by its git dependencies (replacing the `LIBDATADOG_VERSION` file), currently v45 plus the unreleased remote config changes of DataDog/libdatadog#2662; the builder is installed from cargo's checkout of them (`tools/libdatadog.sh`) instead of `cargo install --git --tag`. - **2026-10**: Bumped to libdatadog v45 (from v38). Rust toolchain pin still `1.87.0` (v45's MSRV). The profiling, crashtracker and library-config headers are source compatible with v38 (only additions), so dd-trace-dotnet's native profiler builds unchanged; the musl builds import a few more libc symbols. - **2026-07**: Bumped to libdatadog v38 (from v36). Rust toolchain pin already at `1.87.0`, which matches v38's MSRV, so no toolchain change was needed. diff --git a/Cargo.toml b/Cargo.toml index b7be311..f52d891 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -# -# ./libdatadog is the libdatadog checkout build.sh / build.ps1 install the builder from. [workspace] members = ["datadog-dotnet-ffi"] -exclude = ["libdatadog"] resolver = "2" # Same as libdatadog's release profile, which the builder uses for the profiling library. diff --git a/LIBDATADOG_VERSION b/LIBDATADOG_VERSION deleted file mode 100644 index 74578d1..0000000 --- a/LIBDATADOG_VERSION +++ /dev/null @@ -1 +0,0 @@ -45.0.0 diff --git a/README.md b/README.md index 585c444..1203d67 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ A thin packaging layer over upstream libdatadog. Ships only the FFI components t Output lands in `output/libdatadog-/`. -To upgrade the upstream libdatadog version, edit the `LIBDATADOG_VERSION` file (e.g. `32.0.0` — no `v` prefix). This is the upstream libdatadog version, distinct from libdatadog-dotnet's own release tag (e.g. `v1.3.5`) that `dd-trace-dotnet` pins. The chosen version must be API-compatible with `dd-trace-dotnet`'s native profiler C++ (it calls libdatadog's profiling FFI); otherwise the tracer's C++ build fails on missing identifiers like `ddog_prof_SampleType`. It's a coordinated change — bump + release here, then the tracer adopts the new release and builds against its profiling headers in the same rollout. +To upgrade the upstream libdatadog version, change the `tag` (e.g. `tag = "v32.0.0"`; or `rev` for an unreleased commit) of all libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml`. This is the upstream libdatadog version, distinct from libdatadog-dotnet's own release tag (e.g. `v1.3.5`) that `dd-trace-dotnet` pins. The chosen version must be API-compatible with `dd-trace-dotnet`'s native profiler C++ (it calls libdatadog's profiling FFI); otherwise the tracer's C++ build fails on missing identifiers like `ddog_prof_SampleType`. It's a coordinated change — bump + release here, then the tracer adopts the new release and builds against its profiling headers in the same rollout. ### Features @@ -43,12 +43,11 @@ These are the builder-crate feature flags upstream libdatadog exposes — names ## How It Works -We check out libdatadog at the pinned tag (into `libdatadog/`), install its own `release` binary (from its `builder` crate), let it produce the package, and then replace the package's shared library with our own build: +We install libdatadog's own `release` binary (from its `builder` crate) from cargo's checkout of the pinned libdatadog revision (`tools/libdatadog.sh dir`), let it produce the package, and then replace the package's shared library with our own build: ``` -git clone --depth 1 --branch "v${LIBDATADOG_VERSION}" https://github.com/DataDog/libdatadog libdatadog cargo install \ - --path libdatadog/builder \ + --path "$(tools/libdatadog.sh dir)/builder" \ --bin release \ --no-default-features \ --features "" \ @@ -61,7 +60,7 @@ The builder handles the FFI cargo build, header generation (cbindgen + dedup), l The shared library itself (`libdatadog_profiling.{so,dylib}`, `datadog_profiling_ffi.dll`) comes from `datadog-dotnet-ffi`, this repository's crate: it re-exports libdatadog's profiling FFI (with the same features) and adds .NET specific FFI, like the remote configuration client (`ddog_rc_*`). It keeps the library name, so it's a drop-in replacement for the C++ profiler and the tracer. Only the .NET tracer uses the additional exports, so there are no headers for them. -`datadog-dotnet-ffi` depends on libdatadog's crates by git revision (see `datadog-dotnet-ffi/Cargo.toml`), so it builds on its own; this can be a commit on top of the tag with unreleased changes. To run the builder from a local libdatadog checkout instead of the tag, pass `--libdatadog-path ../libdatadog` (`-LibdatadogPath` on Windows); to build `datadog-dotnet-ffi` against it, add a `[patch."https://github.com/DataDog/libdatadog"]` section with path dependencies. +To build against a local libdatadog checkout, pass `--libdatadog-path ../libdatadog` (`-LibdatadogPath` on Windows): the libdatadog dependencies of `datadog-dotnet-ffi` are then patched to it, so the builder comes from there too. **Windows quirk**: the builder produces a flat `lib/datadog_profiling.{dll,lib,pdb}` layout, but dd-trace-dotnet's vcpkg portfile expects the legacy `release/{dynamic,static}` + `debug/{dynamic,static}` tree with `_ffi`-suffixed filenames. `build.ps1` runs the builder twice (release + debug) and reassembles that layout from cargo's raw `target/` output. @@ -87,7 +86,7 @@ Manual dispatch: **Actions → Release → Run workflow**. The workflow builds a | `version_increment` | `patch` | `patch` / `minor` / `major` — ignored if `release_version` is set | | `release_version` | _(empty)_ | Manual override, e.g. `v1.4.0` | -The upstream libdatadog version isn't a workflow input — it's pinned in the `LIBDATADOG_VERSION` file at the time of the release commit. +The upstream libdatadog version isn't a workflow input — it's pinned by the libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml` at the time of the release commit. For CI runs without publishing a release, use the **Build** workflow (auto-triggered on every PR and push to `main`). diff --git a/build.ps1 b/build.ps1 index 5b8d9e9..49c52f8 100644 --- a/build.ps1 +++ b/build.ps1 @@ -7,7 +7,7 @@ # Copyright 2025-present Datadog, Inc. # Build script for libdatadog-dotnet on Windows. -# The libdatadog version is controlled by the LIBDATADOG_VERSION file. +# The libdatadog revision is pinned by the libdatadog dependencies in datadog-dotnet-ffi/Cargo.toml. # # Produces a Windows zip with the legacy layout the .NET tracer's vcpkg # portfile and runtime DLL loader still expect: @@ -34,7 +34,7 @@ param( [string]$OutputDir = "output", [string]$Features = "profiling,crashtracker,symbolizer,library-config", [switch]$Clean, - # Build from a local libdatadog checkout instead of the tag in LIBDATADOG_VERSION + # Build from a local libdatadog checkout instead of the revision in datadog-dotnet-ffi/Cargo.toml [string]$LibdatadogPath = "" ) @@ -53,15 +53,11 @@ $Target = if ($env:CARGO_BUILD_TARGET) { $Platform } -# Read the libdatadog version. Update LIBDATADOG_VERSION to upgrade. -$Version = (Get-Content LIBDATADOG_VERSION).Trim() - Write-Host "Building libdatadog-dotnet" -ForegroundColor Cyan Write-Host " Platform : $Platform" -ForegroundColor Gray Write-Host " Target : $Target" -ForegroundColor Gray Write-Host " Features : $Features" -ForegroundColor Gray Write-Host " Output : $OutputDir" -ForegroundColor Gray -Write-Host " Version : $Version" -ForegroundColor Gray if (-not (Get-Command cargo -ErrorAction SilentlyContinue)) { Write-Host "Error: cargo not found. Install Rust from https://rustup.rs/" -ForegroundColor Red @@ -77,28 +73,37 @@ New-Item -ItemType Directory -Force -Path $OutputDir | Out-Null $OutputDir = (Resolve-Path $OutputDir).Path $PackageDir = Join-Path $OutputDir "libdatadog-$Platform" -# The libdatadog sources the builder is installed from: either a checkout of the release -# tag, or a junction to a local checkout. -$LibdatadogDir = Join-Path $PWD "libdatadog" -$LibdatadogItem = Get-Item $LibdatadogDir -ErrorAction SilentlyContinue -$IsLink = $LibdatadogItem -and $LibdatadogItem.LinkType +# A local libdatadog checkout replaces the libdatadog dependencies of datadog-dotnet-ffi via a +# cargo [patch] (passed with --config), and with them the libdatadog sources found below. +$CargoConfig = @() if ($LibdatadogPath) { - if ($LibdatadogItem -and -not $IsLink) { - Write-Host "Error: $LibdatadogDir exists and is not a link, remove it to use -LibdatadogPath" -ForegroundColor Red - exit 1 - } - if ($IsLink) { $LibdatadogItem.Delete() } - New-Item -ItemType Junction -Path $LibdatadogDir -Target (Resolve-Path $LibdatadogPath).Path | Out-Null -} elseif ($IsLink) { - Write-Host "Error: $LibdatadogDir links to a local checkout, pass -LibdatadogPath or remove it" -ForegroundColor Red + $LibdatadogPath = (Resolve-Path $LibdatadogPath).Path + $Patch = Join-Path $PWD "target/libdatadog-patch.toml" + New-Item -ItemType Directory -Force -Path (Split-Path $Patch) | Out-Null + $Crates = Select-String -Path datadog-dotnet-ffi/Cargo.toml -Pattern '^([a-z0-9-]+) = \{ git = "https://github.com/DataDog/libdatadog"' | + ForEach-Object { $_.Matches[0].Groups[1].Value } | Sort-Object -Unique + @('[patch."https://github.com/DataDog/libdatadog"]') + ($Crates | ForEach-Object { "$_ = { path = '$(Join-Path $LibdatadogPath $_)' }" }) | + Set-Content -Encoding ascii $Patch + $CargoConfig = @("--config", $Patch) +} + +# The libdatadog sources datadog-dotnet-ffi is built from: cargo's checkout of its libdatadog +# dependencies, or the local checkout. The builder is installed from there, so that the +# headers etc. match the library. +$HostTriple = (rustc -vV 2>&1 | Where-Object { $_ -match "^host:" }) -replace "^host:\s*", "" +$Metadata = cargo metadata --format-version 1 --filter-platform $HostTriple @CargoConfig | ConvertFrom-Json +if ($LASTEXITCODE -ne 0) { + Write-Host "Error: cargo metadata failed" -ForegroundColor Red exit 1 -} elseif (-not $LibdatadogItem) { - git clone --quiet --depth 1 --branch "v${Version}" https://github.com/DataDog/libdatadog $LibdatadogDir - if ($LASTEXITCODE -ne 0) { Write-Host "Error: git clone failed" -ForegroundColor Red; exit 1 } -} elseif ((git -C $LibdatadogDir describe --tags --exact-match 2>$null) -ne "v${Version}") { - Write-Host "Error: $LibdatadogDir is not a checkout of v${Version}, remove it to check out the right version" -ForegroundColor Red +} +$ProfilingFfi = $Metadata.packages | Where-Object { $_.name -eq "libdd-profiling-ffi" } | Select-Object -First 1 +$LibdatadogDir = Split-Path (Split-Path $ProfilingFfi.manifest_path) +if ((Get-Content (Join-Path $LibdatadogDir "Cargo.toml") -Raw) -notmatch '(?ms)^\[workspace\.package\].*?^version = "([^"]+)"') { + Write-Host "Error: no version in $(Join-Path $LibdatadogDir "Cargo.toml")" -ForegroundColor Red exit 1 } +$Version = $Matches[1] +Write-Host " Libdatadog $Version from $LibdatadogDir" -ForegroundColor Gray # Install the builder binary once. Each subsequent profile run reuses it. # Clear CARGO_BUILD_TARGET so `cargo install` compiles the builder for the @@ -110,7 +115,7 @@ if ($LibdatadogPath) { $savedTarget = $env:CARGO_BUILD_TARGET $env:CARGO_BUILD_TARGET = $null cargo install ` - --path libdatadog/builder ` + --path (Join-Path $LibdatadogDir "builder") ` --bin release ` --root .builder ` --no-default-features ` @@ -125,7 +130,6 @@ if ($LASTEXITCODE -ne 0) { exit 1 } -$HostTriple = (rustc -vV 2>&1 | Where-Object { $_ -match "^host:" }) -replace "^host:\s*", "" $CargoTargetDir = Join-Path $PWD "target" # Run the builder once per profile. The builder leaves cargo artifacts in @@ -173,12 +177,15 @@ $DebugOut = Invoke-Builder -BuildProfile "debug" # Build datadog-dotnet-ffi, which replaces the profiling DLL. The PDB path embedded in the # DLL already gets the final name. Uses the dependency versions libdatadog is tested with. +# Not in the builder's target directory: some libdatadog crates have library file names without +# a hash, which the builder's and this build would overwrite for each other. Copy-Item -Path (Join-Path $LibdatadogDir "Cargo.lock") -Destination (Join-Path $PWD "Cargo.lock") -Force -$env:CARGO_TARGET_DIR = $CargoTargetDir +$FfiTargetDir = Join-Path $CargoTargetDir "dotnet-ffi" +$env:CARGO_TARGET_DIR = $FfiTargetDir $env:RUSTFLAGS = "-C relocation-model=pic -C target-feature=+crt-static -C link-arg=/PDBALTPATH:datadog_profiling_ffi.pdb" foreach ($p in @("release", "debug")) { $cargoProfile = if ($p -eq "debug") { "dev" } else { $p } - cargo build -p datadog-dotnet-ffi --target $Target --profile $cargoProfile + cargo build -p datadog-dotnet-ffi --target $Target --profile $cargoProfile @CargoConfig if ($LASTEXITCODE -ne 0) { Write-Host "Error: building datadog-dotnet-ffi ($p) failed" -ForegroundColor Red exit 1 @@ -246,12 +253,13 @@ foreach ($f in @("LICENSE", "NOTICE", "LICENSE-3rdparty.csv")) { # (the import library cargo produces refers to datadog_dotnet_ffi.dll). foreach ($p in @("release", "debug")) { $cargoOut = Join-Path $CargoTargetDir "$Target/$p" + $ffiOut = Join-Path $FfiTargetDir "$Target/$p" $dynDir = Join-Path $PackageDir "$p/dynamic" $staticDir = Join-Path $PackageDir "$p/static" New-Item -ItemType Directory -Force -Path $dynDir, $staticDir | Out-Null - Copy-Item -Path (Join-Path $cargoOut "datadog_dotnet_ffi.dll") -Destination (Join-Path $dynDir "datadog_profiling_ffi.dll") - Copy-Item -Path (Join-Path $cargoOut "datadog_dotnet_ffi.pdb") -Destination (Join-Path $dynDir "datadog_profiling_ffi.pdb") + Copy-Item -Path (Join-Path $ffiOut "datadog_dotnet_ffi.dll") -Destination (Join-Path $dynDir "datadog_profiling_ffi.dll") + Copy-Item -Path (Join-Path $ffiOut "datadog_dotnet_ffi.pdb") -Destination (Join-Path $dynDir "datadog_profiling_ffi.pdb") New-ImportLibrary -Dll (Join-Path $dynDir "datadog_profiling_ffi.dll") -DllName "datadog_profiling_ffi.dll" ` -OutLib (Join-Path $dynDir "datadog_profiling_ffi.lib") Copy-Item -Path (Join-Path $cargoOut "datadog_profiling_ffi.lib") -Destination (Join-Path $staticDir "datadog_profiling_ffi.lib") diff --git a/build.sh b/build.sh index 518bc64..4d8c3cf 100755 --- a/build.sh +++ b/build.sh @@ -7,7 +7,7 @@ # Copyright 2025-present Datadog, Inc. # Build script for libdatadog-dotnet. -# The libdatadog version is controlled by the LIBDATADOG_VERSION file. +# The libdatadog revision is pinned by the libdatadog dependencies in datadog-dotnet-ffi/Cargo.toml. # Linux builds run inside Docker (for GLIBC 2.17 / musl compatibility). # macOS builds run natively via cargo. @@ -40,7 +40,7 @@ while [[ $# -gt 0 ]]; do echo " symbolizer,library-config)" echo " --clean Remove output directory before building" echo " --libdatadog-path P Build from a local libdatadog checkout instead of" - echo " the tag in LIBDATADOG_VERSION" + echo " the revision in datadog-dotnet-ffi/Cargo.toml" echo " -h, --help Show this help" echo "" echo "Environment variables:" @@ -65,9 +65,6 @@ TARGET="${CARGO_BUILD_TARGET:-$PLATFORM}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" -# Read the libdatadog version. Update LIBDATADOG_VERSION to upgrade. -VERSION=$(cat LIBDATADOG_VERSION) - # Builder crate features compiled into the release binary. # These control which FFI modules are included in the output library. # Feature names map to flags in builder/src/bin/release.rs in libdatadog. @@ -82,27 +79,22 @@ mkdir -p "$OUTPUT_DIR" OUTPUT_DIR="$(cd "$OUTPUT_DIR" && pwd)" PACKAGE_DIR="$OUTPUT_DIR/libdatadog-${PLATFORM:-$TARGET}" -# The libdatadog sources the builder is installed from: either a checkout of the release -# tag, or a symlink to a local checkout. -LIBDATADOG_DIR="$SCRIPT_DIR/libdatadog" -DOCKER_LIBDATADOG_MOUNT=() +# A local libdatadog checkout replaces the libdatadog dependencies of datadog-dotnet-ffi via a +# cargo [patch] (passed with --config), and with them the sources tools/libdatadog.sh finds. +DOCKER_LIBDATADOG_ARGS=() if [[ -n "$LIBDATADOG_PATH" ]]; then LIBDATADOG_PATH="$(cd "$LIBDATADOG_PATH" && pwd)" - if [[ -e "$LIBDATADOG_DIR" && ! -L "$LIBDATADOG_DIR" ]]; then - echo "Error: $LIBDATADOG_DIR exists and is not a symlink, remove it to use --libdatadog-path" >&2 - exit 1 - fi - ln -sfn "$LIBDATADOG_PATH" "$LIBDATADOG_DIR" - # Mounted at the same path, so that the symlink also resolves inside the containers - DOCKER_LIBDATADOG_MOUNT=(-v "$LIBDATADOG_PATH:$LIBDATADOG_PATH") -elif [[ -L "$LIBDATADOG_DIR" ]]; then - echo "Error: $LIBDATADOG_DIR is a symlink to a local checkout, pass --libdatadog-path or remove it" >&2 - exit 1 -elif [[ ! -e "$LIBDATADOG_DIR" ]]; then - git clone --quiet --depth 1 --branch "v${VERSION}" https://github.com/DataDog/libdatadog "$LIBDATADOG_DIR" -elif [[ "$(git -C "$LIBDATADOG_DIR" describe --tags --exact-match 2>/dev/null)" != "v${VERSION}" ]]; then - echo "Error: $LIBDATADOG_DIR is not a checkout of v${VERSION}, remove it to check out the right version" >&2 - exit 1 + export LIBDATADOG_PATCH=target/libdatadog-patch.toml + mkdir -p target + { + echo '[patch."https://github.com/DataDog/libdatadog"]' + sed -n 's|^\([a-z0-9-]*\) = { git = "https://github.com/DataDog/libdatadog".*|\1|p' \ + datadog-dotnet-ffi/Cargo.toml | sort -u | while read -r crate; do + echo "$crate = { path = \"$LIBDATADOG_PATH/$crate\" }" + done + } > "$LIBDATADOG_PATCH" + # Mounted at the same path, so that the patch also applies inside the containers + DOCKER_LIBDATADOG_ARGS=(-v "$LIBDATADOG_PATH:$LIBDATADOG_PATH" -e LIBDATADOG_PATCH) fi # docker_run_gnu IMAGE TARGET PLATFORM @@ -125,11 +117,10 @@ docker_run_gnu() { -v "${cargo_home}:/usr/local/cargo" \ -v "${rustup_home}:/usr/local/rustup" \ -v "$SCRIPT_DIR:/workspace" \ - "${DOCKER_LIBDATADOG_MOUNT[@]}" \ + "${DOCKER_LIBDATADOG_ARGS[@]}" \ -w /workspace \ -e CARGO_HOME=/usr/local/cargo \ -e RUSTUP_HOME=/usr/local/rustup \ - -e BUILDER_VERSION="$VERSION" \ -e BUILDER_FEATURES="$FEATURES" \ -e BUILDER_PROFILE="$PROFILE" \ -e BUILDER_TARGET="$target" \ @@ -142,8 +133,9 @@ docker_run_gnu() { # Unset CARGO_ENCODED_RUSTFLAGS so cargo install builds the builder # binary without interference from any RUSTFLAGS overrides. unset CARGO_ENCODED_RUSTFLAGS + LIBDATADOG_DIR=$(sh tools/libdatadog.sh dir) cargo install \ - --path /workspace/libdatadog/builder \ + --path "${LIBDATADOG_DIR}/builder" \ --bin release \ --root /tmp/builder \ --no-default-features \ @@ -171,7 +163,7 @@ docker_run_gnu() { OPT_LEVEL="${OPT_LEVEL}" \ DEBUG="${DEBUG}" \ NUM_JOBS="$(nproc 2>/dev/null || echo 4)" \ - CARGO_PKG_VERSION="${BUILDER_VERSION}" \ + CARGO_PKG_VERSION="$(sh tools/libdatadog.sh version)" \ CARGO_TARGET_DIR="/workspace/target" \ /tmp/builder/bin/release \ --out "/workspace/output/libdatadog-${BUILDER_PLATFORM}" \ @@ -196,10 +188,9 @@ docker_run_musl() { -v "$HOME/.cargo/registry:/root/.cargo/registry" \ -v "$HOME/.cargo/git:/root/.cargo/git" \ -v "$SCRIPT_DIR:/workspace" \ - "${DOCKER_LIBDATADOG_MOUNT[@]}" \ + "${DOCKER_LIBDATADOG_ARGS[@]}" \ -w /workspace \ -e CARGO_HOME=/root/.cargo \ - -e BUILDER_VERSION="$VERSION" \ -e BUILDER_FEATURES="$FEATURES" \ -e BUILDER_PROFILE="$PROFILE" \ -e BUILDER_TARGET="$target" \ @@ -211,8 +202,9 @@ docker_run_musl() { # Unset CARGO_ENCODED_RUSTFLAGS so cargo install builds the builder # binary without interference from any RUSTFLAGS overrides. unset CARGO_ENCODED_RUSTFLAGS + LIBDATADOG_DIR=$(sh tools/libdatadog.sh dir) cargo install \ - --path /workspace/libdatadog/builder \ + --path "${LIBDATADOG_DIR}/builder" \ --bin release \ --root /tmp/builder \ --no-default-features \ @@ -251,7 +243,7 @@ docker_run_musl() { OPT_LEVEL="${OPT_LEVEL}" \ DEBUG="${DEBUG}" \ NUM_JOBS="$(nproc 2>/dev/null || echo 4)" \ - CARGO_PKG_VERSION="${BUILDER_VERSION}" \ + CARGO_PKG_VERSION="$(sh tools/libdatadog.sh version)" \ CARGO_TARGET_DIR="/workspace/target" \ /tmp/builder/bin/release \ --out "/workspace/output/libdatadog-${BUILDER_PLATFORM}" \ @@ -296,8 +288,9 @@ case "$TARGET" in # binary for the host. The builder receives --target as a CLI arg and # handles cross-compilation internally (e.g. x86_64 on an arm64 runner). unset CARGO_BUILD_TARGET + LIBDATADOG_DIR=$(sh tools/libdatadog.sh dir) cargo install \ - --path libdatadog/builder \ + --path "$LIBDATADOG_DIR/builder" \ --bin release \ --root .builder \ --no-default-features \ @@ -323,7 +316,7 @@ case "$TARGET" in OPT_LEVEL="$OPT_LEVEL" \ DEBUG="$DEBUG" \ NUM_JOBS="$(sysctl -n hw.ncpu 2>/dev/null || echo 4)" \ - CARGO_PKG_VERSION="$VERSION" \ + CARGO_PKG_VERSION="$(sh tools/libdatadog.sh version)" \ CARGO_TARGET_DIR="$SCRIPT_DIR/target" \ .builder/bin/release \ --out "$PACKAGE_DIR" \ diff --git a/datadog-dotnet-ffi/Cargo.toml b/datadog-dotnet-ffi/Cargo.toml index 945e3e7..b4687c2 100644 --- a/datadog-dotnet-ffi/Cargo.toml +++ b/datadog-dotnet-ffi/Cargo.toml @@ -23,8 +23,6 @@ strum = { version = "0.26", default-features = false } tokio = { version = "1.49", default-features = false, features = ["macros", "net", "rt", "time"] } tokio-util = { version = "0.7.11", default-features = false } -# libdatadog v45 (LIBDATADOG_VERSION, which the builder is built from) plus the unreleased -# remote config changes of DataDog/libdatadog#2662. libdd-capabilities-impl = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false } libdd-common = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false } libdd-common-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["std"] } diff --git a/tools/build-ffi.sh b/tools/build-ffi.sh index 17d2936..f199a02 100755 --- a/tools/build-ffi.sh +++ b/tools/build-ffi.sh @@ -18,7 +18,7 @@ PACKAGE_DIR="$3" cd "$(dirname "$0")/.." # Build with the dependency versions libdatadog itself is tested with. -cp libdatadog/Cargo.lock Cargo.lock +cp "$(sh tools/libdatadog.sh dir)/Cargo.lock" Cargo.lock case "$TARGET" in *-apple-darwin) @@ -43,9 +43,12 @@ case "$PROFILE" in *) CARGO_PROFILE="$PROFILE"; PROFILE_DIR="$PROFILE" ;; esac -cargo build -p datadog-dotnet-ffi --target "$TARGET" --profile "$CARGO_PROFILE" +# Not in the builder's target directory: some libdatadog crates have library file names without +# a hash, which the builder's and this build would overwrite for each other. +cargo build -p datadog-dotnet-ffi --target "$TARGET" --profile "$CARGO_PROFILE" \ + --target-dir target/dotnet-ffi ${LIBDATADOG_PATCH:+--config "$LIBDATADOG_PATCH"} -cp "target/$TARGET/$PROFILE_DIR/$BUILT" "$PACKAGE_DIR/lib/$LIB" +cp "target/dotnet-ffi/$TARGET/$PROFILE_DIR/$BUILT" "$PACKAGE_DIR/lib/$LIB" # Same post-processing as libdatadog's builder (builder/src/arch/*.rs) case "$TARGET" in diff --git a/tools/libdatadog.sh b/tools/libdatadog.sh new file mode 100755 index 0000000..8798e76 --- /dev/null +++ b/tools/libdatadog.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# SPDX-License-Identifier: Apache-2.0 +# +# Prints the directory (dir) or the version (version) of the libdatadog sources datadog-dotnet-ffi +# is built from: cargo's checkout of the libdatadog dependencies in datadog-dotnet-ffi/Cargo.toml, +# or the local checkout they are patched to (LIBDATADOG_PATCH, see build.sh --libdatadog-path). +# libdatadog's builder is installed from there, so that the headers etc. match the library. +# +# Usage: tools/libdatadog.sh dir|version + +set -e + +cd "$(dirname "$0")/.." + +HOST=$(rustc -vV | sed -n 's/^host: //p') +DIR=$(cargo metadata --format-version 1 --filter-platform "$HOST" ${LIBDATADOG_PATCH:+--config "$LIBDATADOG_PATCH"} | + grep -o '"manifest_path":"[^"]*/libdd-profiling-ffi/Cargo.toml"' | + sed 's|^"manifest_path":"\(.*\)/libdd-profiling-ffi/Cargo.toml"$|\1|') +if [ -z "$DIR" ]; then + echo "Error: libdd-profiling-ffi not found in the dependencies of datadog-dotnet-ffi" >&2 + exit 1 +fi + +case "$1" in + dir) echo "$DIR" ;; + version) sed -n '/^\[workspace\.package\]/,/^\[/s/^version = "\(.*\)"$/\1/p' "$DIR/Cargo.toml" ;; + *) echo "Usage: $0 dir|version" >&2; exit 1 ;; +esac From 572830b71f2cd78fbad3a16211cd695ae6d94277 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Wed, 14 Oct 2026 20:30:13 +0200 Subject: [PATCH 4/5] Take a cancellation token in the remote config fetch, without a mutex The client must not be used by multiple threads at once, and takes &mut. A fetch can be cancelled from another thread with libdatadog's ddog_CancellationToken API, instead of the client's own token. Co-Authored-By: Claude Opus 5.5 --- datadog-dotnet-ffi/src/remote_config.rs | 148 ++++++++++++++---------- 1 file changed, 86 insertions(+), 62 deletions(-) diff --git a/datadog-dotnet-ffi/src/remote_config.rs b/datadog-dotnet-ffi/src/remote_config.rs index 4f6f6e5..82b4571 100644 --- a/datadog-dotnet-ffi/src/remote_config.rs +++ b/datadog-dotnet-ffi/src/remote_config.rs @@ -12,6 +12,7 @@ use function_name::named; use libdd_capabilities_impl::{HttpClientCapability, NativeCapabilities}; use libdd_common::Endpoint; +use libdd_common_ffi::handle::{Handle, ToInner}; use libdd_common_ffi::slice::{AsBytes, CharSlice, Slice}; use libdd_common_ffi::{VoidResult, wrap_with_void_ffi_result}; use libdd_remote_config::fetch::{ @@ -24,7 +25,7 @@ use libdd_remote_config::{ }; use std::ffi::c_void; use std::str::FromStr; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::time::Duration; use strum::IntoEnumIterator; use tokio_util::sync::CancellationToken; @@ -44,7 +45,7 @@ impl ParseFile for SharedBytesParser { type File = RawFile>>; type Fetcher = SingleFetcher, NativeCapabilities>; -struct RcClientInner { +pub struct RcClient { runtime: tokio::runtime::Runtime, /// Only None while being replaced by a new instance, see [`RcClient::rebind`]. fetcher: Option, @@ -52,21 +53,16 @@ struct RcClientInner { tracker: ChangeTracker, } +// The tracer uses a client from whichever thread polls, one at a time +const _: fn() = || { + fn assert_send() {} + assert_send::(); +}; + fn fetcher_lost() -> anyhow::Error { anyhow::anyhow!("The remote config client is unusable after a failed rebind") } -impl RcClientInner { - fn fetcher(&mut self) -> anyhow::Result<&mut Fetcher> { - self.fetcher.as_mut().ok_or_else(fetcher_lost) - } -} - -pub struct RcClient { - inner: Mutex, - cancel: CancellationToken, -} - #[repr(C)] pub struct RcTarget<'a> { pub service: CharSlice<'a>, @@ -237,45 +233,39 @@ impl RcClient { ) .with_client_id(to_string(config.client_id)?); Ok(RcClient { - inner: Mutex::new(RcClientInner { - runtime, - fetcher: Some(fetcher), - tracker: ChangeTracker::default(), - }), - cancel: CancellationToken::new(), + runtime, + fetcher: Some(fetcher), + tracker: ChangeTracker::default(), }) } - fn lock(&self) -> anyhow::Result> { - self.inner - .lock() - .map_err(|_| anyhow::anyhow!("The remote config client is unusable after a panic")) + fn fetcher(&mut self) -> anyhow::Result<&mut Fetcher> { + self.fetcher.as_mut().ok_or_else(fetcher_lost) } /// Replaces the fetcher with a new instance for `target` and `endpoint` (if any, otherwise the /// current one), which takes over the known files of the previous one. - fn rebind(&self, target: Target, endpoint: Option) -> anyhow::Result<()> { - let mut guard = self.lock()?; - let inner = &mut *guard; - let previous = inner.fetcher.take().ok_or_else(fetcher_lost)?; - inner.fetcher = Some(inner.runtime.block_on(previous.rebind(target, endpoint))?); + fn rebind(&mut self, target: Target, endpoint: Option) -> anyhow::Result<()> { + let previous = self.fetcher.take().ok_or_else(fetcher_lost)?; + self.fetcher = Some(self.runtime.block_on(previous.rebind(target, endpoint))?); Ok(()) } - fn fetch(&self) -> anyhow::Result { - let mut guard = self.lock()?; - let RcClientInner { + fn fetch(&mut self, cancel: Option<&CancellationToken>) -> anyhow::Result { + let RcClient { runtime, fetcher, tracker, - } = &mut *guard; + } = self; let fetcher = fetcher.as_mut().ok_or_else(fetcher_lost)?; - let cancel = &self.cancel; let files = runtime.block_on(async { - tokio::select! { - biased; - _ = cancel.cancelled() => anyhow::bail!("The remote config client was cancelled"), - files = fetcher.fetch_once() => files, + match cancel { + Some(cancel) => tokio::select! { + biased; + _ = cancel.cancelled() => anyhow::bail!("The remote config fetch was cancelled"), + files = fetcher.fetch_once() => files, + }, + None => fetcher.fetch_once().await, } })?; @@ -328,13 +318,6 @@ pub unsafe extern "C" fn ddog_rc_client_drop(client: *mut RcClient) { } } -/// Aborts an ongoing fetch and makes all further fetches fail immediately. May be called from -/// any thread, e.g. while shutting down. -#[unsafe(no_mangle)] -pub extern "C" fn ddog_rc_client_cancel(client: &RcClient) { - client.cancel.cancel(); -} - /// Switches to another target (service, env, version, tags) and, if `endpoint` is not null, /// another agent endpoint (which is copied), with a new fetcher instance (and client session) /// taking over the known files. Unchanged files are neither downloaded again nor reported as @@ -346,7 +329,7 @@ pub extern "C" fn ddog_rc_client_cancel(client: &RcClient) { #[must_use] #[named] pub unsafe extern "C" fn ddog_rc_client_rebind( - client: &RcClient, + client: &mut RcClient, target: &RcTarget, endpoint: Option<&Endpoint>, ) -> VoidResult { @@ -365,14 +348,13 @@ pub unsafe extern "C" fn ddog_rc_client_rebind( #[must_use] #[named] pub unsafe extern "C" fn ddog_rc_client_set_products( - client: &RcClient, + client: &mut RcClient, products: Slice, capabilities: u64, ) -> VoidResult { wrap_with_void_ffi_result!({ let (products, unknown) = to_products(products)?; client - .lock()? .fetcher()? .set_product_capabilities(products, to_capabilities(capabilities)); report_unknown_products(unknown)?; @@ -387,26 +369,33 @@ pub unsafe extern "C" fn ddog_rc_client_set_products( #[must_use] #[named] pub unsafe extern "C" fn ddog_rc_client_set_extra_services( - client: &RcClient, + client: &mut RcClient, services: Slice, ) -> VoidResult { wrap_with_void_ffi_result!({ let services = to_strings(services)?; - client.lock()?.fetcher()?.set_extra_services(services); + client.fetcher()?.set_extra_services(services); }) } -/// Polls the agent once, blocking until the response is processed or the request timed out. +/// Polls the agent once, blocking until the response is processed, the request timed out, or +/// `cancel` is cancelled. To cancel from another thread, e.g. on shutdown, pass a token from +/// `ddog_CancellationToken_new` here and cancel a clone of it (`ddog_CancellationToken_clone`). /// On success, `out_changes` must be released with [`ddog_rc_changes_drop`]. +/// +/// # Safety +/// `cancel` must be null or a valid token. #[unsafe(no_mangle)] #[must_use] #[named] -pub extern "C" fn ddog_rc_client_fetch( - client: &RcClient, +pub unsafe extern "C" fn ddog_rc_client_fetch( + client: &mut RcClient, + mut cancel: *mut Handle, out_changes: &mut RcChanges, ) -> VoidResult { wrap_with_void_ffi_result!({ - *out_changes = client.fetch()?.into_ffi(); + let cancel = unsafe { cancel.to_inner_mut() }.ok(); + *out_changes = client.fetch(cancel.as_deref())?.into_ffi(); }) } @@ -419,7 +408,7 @@ pub extern "C" fn ddog_rc_client_fetch( #[must_use] #[named] pub unsafe extern "C" fn ddog_rc_client_set_apply_state( - client: &RcClient, + client: &mut RcClient, path: CharSlice, state: u32, error: CharSlice, @@ -432,7 +421,7 @@ pub unsafe extern "C" fn ddog_rc_client_set_apply_state( 3 => ConfigApplyState::Error(to_string(error)?), _ => anyhow::bail!("Invalid apply state {state}"), }; - client.lock()?.fetcher()?.set_config_state(&path, state); + client.fetcher()?.set_config_state(&path, state); }) } @@ -540,8 +529,10 @@ mod tests { self.set_products(&["APM_TRACING"]).unwrap(); } - fn client(&self) -> &RcClient { - unsafe { &*self.client } + // The tests only use one reference at a time + #[allow(clippy::mut_from_ref)] + fn client(&self) -> &mut RcClient { + unsafe { &mut *self.client } } fn add_file(&self, id: &str, services: &[&str], contents: &str) { @@ -566,7 +557,8 @@ mod tests { /// Returns (kind, path, contents) and releases everything. fn fetch(&self) -> Vec<(u32, String, Option)> { let mut changes = RcChanges::default(); - ddog_rc_client_fetch(self.client(), &mut changes).unwrap(); + unsafe { ddog_rc_client_fetch(self.client(), std::ptr::null_mut(), &mut changes) } + .unwrap(); let result = unsafe { std::slice::from_raw_parts(changes.ptr, changes.len) } .iter() .map(|c| unsafe { @@ -750,7 +742,8 @@ mod tests { fixture.add_file("a", &["first"], "contents"); let mut changes = RcChanges::default(); - ddog_rc_client_fetch(fixture.client(), &mut changes).unwrap(); + unsafe { ddog_rc_client_fetch(fixture.client(), std::ptr::null_mut(), &mut changes) } + .unwrap(); let change = unsafe { &*changes.ptr }; let (ptr, len, owner) = ( change.contents_ptr, @@ -768,15 +761,46 @@ mod tests { #[test] #[cfg_attr(miri, ignore)] - fn cancelled_client_fails_fast() { + fn cancelled_fetch_fails_fast() { let mut fixture = Fixture::new(); // Nothing listens there: the fetch would otherwise fail by itself fixture.create("http://127.0.0.1:1").unwrap(); - ddog_rc_client_cancel(fixture.client()); + let token = CancellationToken::new(); + token.cancel(); + let mut handle: Handle = token.into(); + let mut changes = RcChanges::default(); + let VoidResult::Err(err) = + (unsafe { ddog_rc_client_fetch(fixture.client(), &mut handle, &mut changes) }) + else { + panic!("expected an error"); + }; + assert!(err.as_ref().contains("cancelled"), "{}", err.as_ref()); + drop(unsafe { handle.take() }); + } + + #[test] + #[cfg_attr(miri, ignore)] + fn cancel_aborts_an_ongoing_fetch() { + let mut fixture = Fixture::new(); + // Accepts connections (in its backlog), but never responds + let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap(); + let url = format!("http://{}/", listener.local_addr().unwrap()); + fixture.create(&url).unwrap(); + let token = CancellationToken::new(); + let clone = token.clone(); + let canceller = std::thread::spawn(move || { + std::thread::sleep(Duration::from_millis(200)); + clone.cancel(); + }); + let mut handle: Handle = token.into(); let mut changes = RcChanges::default(); - let VoidResult::Err(err) = ddog_rc_client_fetch(fixture.client(), &mut changes) else { + let VoidResult::Err(err) = + (unsafe { ddog_rc_client_fetch(fixture.client(), &mut handle, &mut changes) }) + else { panic!("expected an error"); }; assert!(err.as_ref().contains("cancelled"), "{}", err.as_ref()); + canceller.join().unwrap(); + drop(unsafe { handle.take() }); } } From cf582bbb95660443039cdd6ba7714113769d9403 Mon Sep 17 00:00:00 2001 From: Bob Weinand Date: Wed, 14 Oct 2026 20:43:38 +0200 Subject: [PATCH 5/5] Commit Cargo.lock, and fix the feature set The shipped library is built with the committed Cargo.lock (--locked), which starts from libdatadog's lock at the pinned revision, instead of copying libdatadog's lock at build time. The builder features are no longer configurable (--features, -Features, workflow input): the shared library is built with the matching fixed libdd-profiling-ffi features, so other selections produced headers for APIs the library lacks. The bump skill updates Cargo.lock and the crate's rust-version. Co-Authored-By: Claude Opus 5.5 --- .../skills/bump-libdatadog-version/SKILL.md | 22 +- .github/workflows/build-platform.yml | 11 +- .github/workflows/build.yml | 1 - .github/workflows/release.yml | 1 - .gitignore | 1 - AGENTS.md | 10 +- Cargo.lock | 4122 +++++++++++++++++ README.md | 4 +- build.ps1 | 19 +- build.sh | 14 +- datadog-dotnet-ffi/Cargo.toml | 2 +- tools/build-ffi.sh | 10 +- tools/libdatadog.sh | 9 +- 13 files changed, 4180 insertions(+), 46 deletions(-) create mode 100644 Cargo.lock diff --git a/.cursor/skills/bump-libdatadog-version/SKILL.md b/.cursor/skills/bump-libdatadog-version/SKILL.md index 7a099fe..7e8eb47 100644 --- a/.cursor/skills/bump-libdatadog-version/SKILL.md +++ b/.cursor/skills/bump-libdatadog-version/SKILL.md @@ -52,9 +52,19 @@ detect an MSRV change. Set `tag = "v"` (replacing `tag = ...` or `rev = ...`) on **every** libdatadog git dependency in `datadog-dotnet-ffi/Cargo.toml` — they must all -use the same version — and update the comment above them. Then make sure it -still builds (`cargo test -p datadog-dotnet-ffi`), and that the -`libdd-profiling-ffi` feature list still matches `builder/src/features.rs`. +use the same version — and update the comment above them. + +Then update `Cargo.lock` (committed, the builds use `--locked`) to libdatadog's +dependency versions at that tag, which also makes sure it still builds: + +```bash +cargo metadata --format-version 1 > /dev/null # resolves the new revision +cp "$(sh tools/libdatadog.sh dir)/Cargo.lock" Cargo.lock +cargo test -p datadog-dotnet-ffi # adds our own dependencies on top +``` + +Also check that the `libdd-profiling-ffi` feature list still matches +`builder/src/features.rs`. ### Step 3: Check upstream Rust MSRV; update the pin if changed @@ -95,6 +105,7 @@ Then update **all** of these from the old MSRV to the target MSRV: - `tools/docker/Dockerfile.musl-x64` — `ARG RUST_VERSION` - `tools/docker/Dockerfile.musl-aarch64` — `ARG RUST_VERSION` - `README.md` — the prerequisites line +- `datadog-dotnet-ffi/Cargo.toml` — `rust-version` Keep this in the **same commit** as the libdatadog bump — the two are coupled (building the new version with the old toolchain is exactly the @@ -147,8 +158,9 @@ side, **not** a precondition that blocks the bump here. ## Notes -- Feature set is **not** part of a version bump — leave `FEATURES` / `Features` - / workflow `features` defaults alone unless the user explicitly asks. +- Feature set is **not** part of a version bump — leave `FEATURES` / `$Features` + (and the matching `libdd-profiling-ffi` features) alone unless the user + explicitly asks. - The `curl` commands need network access but no auth or extra tooling (they hit public release/raw endpoints). If `curl` is unavailable, `wget -qO-` works with the same URLs. diff --git a/.github/workflows/build-platform.yml b/.github/workflows/build-platform.yml index 8f937c1..8998246 100644 --- a/.github/workflows/build-platform.yml +++ b/.github/workflows/build-platform.yml @@ -10,11 +10,6 @@ name: Build Platform on: workflow_call: inputs: - features: - description: 'Comma-separated builder crate features (e.g. profiling,crashtracker,symbolizer,library-config)' - required: false - type: string - default: 'profiling,crashtracker,symbolizer,library-config' verify_artifacts: description: 'Whether to verify build artifacts after building' required: false @@ -91,7 +86,7 @@ jobs: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ runner.os }}-cargo-${{ hashFiles('datadog-dotnet-ffi/Cargo.toml') }} + key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo- @@ -109,10 +104,10 @@ jobs: CARGO_BUILD_TARGET: ${{ matrix.target }} run: | if [ "$RUNNER_OS" == "Windows" ]; then - pwsh -Command "./build.ps1 -Platform '${{ matrix.platform }}' -Features '${{ inputs.features }}' -Clean" + pwsh -Command "./build.ps1 -Platform '${{ matrix.platform }}' -Clean" else chmod +x build.sh - ./build.sh --platform "${{ matrix.platform }}" --features "${{ inputs.features }}" --clean + ./build.sh --platform "${{ matrix.platform }}" --clean fi shell: bash diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cc7f1f7..dc2e6f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,4 +26,3 @@ jobs: contents: read with: verify_artifacts: true - features: 'profiling,crashtracker,symbolizer,library-config' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d740449..c1ecd14 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,7 +36,6 @@ jobs: contents: read with: verify_artifacts: false - features: 'profiling,crashtracker,symbolizer,library-config' create-release: name: Create GitHub Release diff --git a/.gitignore b/.gitignore index 2399aae..38b8104 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Rust target/ -Cargo.lock **/*.rs.bk *.pdb diff --git a/AGENTS.md b/AGENTS.md index b546519..c71beb9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,9 +23,9 @@ tools/build-ffi.sh The builder handles the FFI cargo build, header generation (cbindgen + dedup), library stripping, and packaging. We orchestrate per-platform Docker containers and (on Windows) reshape the resulting zip to match what dd-trace-dotnet expects. -`datadog-dotnet-ffi` (the only Rust code here) is a cdylib that depends on libdatadog's crates from git (see [Version Pinning](#version-pinning)) and re-exports `libdd-profiling-ffi` (with the feature list the builder computes for our builder features — keep `datadog-dotnet-ffi/Cargo.toml` in sync with `builder/src/features.rs`), plus the .NET specific FFI (`src/remote_config.rs`: the remote configuration client used by dd-trace-dotnet). Its library is named `datadog_dotnet_ffi` (the dependency's own cdylib would collide otherwise), and `tools/build-ffi.sh` / `build.ps1` copy it over the builder's library under the original names (setting the soname / install name, and on Windows generating an import library for `datadog_profiling_ffi.dll`). It is built with libdatadog's `Cargo.lock`. +`datadog-dotnet-ffi` (the only Rust code here) is a cdylib that depends on libdatadog's crates from git (see [Version Pinning](#version-pinning)) and re-exports `libdd-profiling-ffi` (with the feature list the builder computes for our builder features — keep `datadog-dotnet-ffi/Cargo.toml` in sync with `builder/src/features.rs`), plus the .NET specific FFI (`src/remote_config.rs`: the remote configuration client used by dd-trace-dotnet). Its library is named `datadog_dotnet_ffi` (the dependency's own cdylib would collide otherwise), and `tools/build-ffi.sh` / `build.ps1` copy it over the builder's library under the original names (setting the soname / install name, and on Windows generating an import library for `datadog_profiling_ffi.dll`). Its dependencies are locked by the committed `Cargo.lock` (built with `--locked`), which starts from libdatadog's `Cargo.lock` at the pinned revision, see Common Tasks. -Use `--libdatadog-path ../libdatadog` (`-LibdatadogPath`) to build against a local libdatadog checkout, e.g. to test libdatadog changes: the build scripts patch the libdatadog dependencies of `datadog-dotnet-ffi` to it (a `[patch]` in `target/libdatadog-patch.toml`, passed to cargo with `--config` via `LIBDATADOG_PATCH`), so the builder comes from there too. It is mounted at the same path into the build containers. +Use `--libdatadog-path ../libdatadog` (`-LibdatadogPath`) to build against a local libdatadog checkout, e.g. to test libdatadog changes: the build scripts patch the libdatadog dependencies of `datadog-dotnet-ffi` to it (a `[patch]` in `target/libdatadog-patch.toml`, passed to cargo with `--config` via `LIBDATADOG_PATCH`), so the builder comes from there too. It is mounted at the same path into the build containers. The patch changes `Cargo.lock` locally; don't commit that. ## Version Pinning @@ -121,9 +121,9 @@ libdatadog-dotnet/ ## Common Tasks -**Update libdatadog version**: change the `tag` of the libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml` (the upstream libdatadog version this repo builds from). Ensure the target libdatadog's profiling FFI is API-compatible with dd-trace-dotnet's native profiler C++ — the tracer adopts the resulting libdatadog-dotnet release in a coordinated PR; it won't already reference it. See [Version Pinning](#version-pinning). +**Update libdatadog version**: change the `tag` of the libdatadog dependencies in `datadog-dotnet-ffi/Cargo.toml` (the upstream libdatadog version this repo builds from), and update `Cargo.lock` to libdatadog's dependency versions at that tag: `cargo metadata --format-version 1 > /dev/null` (resolves the new revision), `cp "$(sh tools/libdatadog.sh dir)/Cargo.lock" Cargo.lock`, then `cargo test -p datadog-dotnet-ffi` (adds our own dependencies on top). Ensure the target libdatadog's profiling FFI is API-compatible with dd-trace-dotnet's native profiler C++ — the tracer adopts the resulting libdatadog-dotnet release in a coordinated PR; it won't already reference it. See [Version Pinning](#version-pinning). -**Change feature set**: edit the `FEATURES` default in `build.sh`, the `Features` default in `build.ps1`, and the `features` input default in `build-platform.yml` / `release.yml` / `build.yml`. Feature names are the builder crate's high-level features (`profiling`, `crashtracker`, `data-pipeline`, `symbolizer`, `library-config`, `log`, `telemetry`, `ddsketch`, `ffe`, `otel-thread-ctx`, `shared-runtime`, `regex-lite`), not the underlying cargo features — e.g. the builder's `otel-thread-ctx` feature internally maps to the `otel-thread-ctx-ffi` FFI crate (see `builder/src/bin/release.rs` in libdatadog), so pass `otel-thread-ctx` here, never the FFI crate name. +**Change feature set**: edit `FEATURES` in `build.sh` and `$Features` in `build.ps1` (the builder features, which determine the headers etc.), together with the `libdd-profiling-ffi` features in `datadog-dotnet-ffi/Cargo.toml` (what the builder computes for them, see `builder/src/features.rs`), which the shipped library is built with. Feature names are the builder crate's high-level features (`profiling`, `crashtracker`, `data-pipeline`, `symbolizer`, `library-config`, `log`, `telemetry`, `ddsketch`, `ffe`, `otel-thread-ctx`, `shared-runtime`, `regex-lite`), not the underlying cargo features — e.g. the builder's `otel-thread-ctx` feature internally maps to the `otel-thread-ctx-ffi` FFI crate (see `builder/src/bin/release.rs` in libdatadog), so pass `otel-thread-ctx` here, never the FFI crate name. **Add a platform**: matrix entry in `build-platform.yml`; if it's not host-native, either add a Dockerfile + dispatch case in `build.sh`, or use QEMU. Update the release archive list in `release.yml`. @@ -152,7 +152,7 @@ Output lands in `output/libdatadog-/`. For aarch64 Linux targets you n ## Recent Changes (Reverse Chronological) -- **2026-10**: Added `datadog-dotnet-ffi`, which replaces the builder's shared library, with the remote configuration client FFI (`ddog_rc_*`) for dd-trace-dotnet. The libdatadog version is now pinned by its git dependencies (replacing the `LIBDATADOG_VERSION` file), currently v45 plus the unreleased remote config changes of DataDog/libdatadog#2662; the builder is installed from cargo's checkout of them (`tools/libdatadog.sh`) instead of `cargo install --git --tag`. +- **2026-10**: Added `datadog-dotnet-ffi`, which replaces the builder's shared library, with the remote configuration client FFI (`ddog_rc_*`) for dd-trace-dotnet. The libdatadog version is now pinned by its git dependencies (replacing the `LIBDATADOG_VERSION` file), currently v45 plus the unreleased remote config changes of DataDog/libdatadog#2662; the builder is installed from cargo's checkout of them (`tools/libdatadog.sh`) instead of `cargo install --git --tag`. `Cargo.lock` is committed, and the feature set is fixed (no more `--features` / workflow input), as the shipped library is built with the features in `datadog-dotnet-ffi/Cargo.toml`. - **2026-10**: Bumped to libdatadog v45 (from v38). Rust toolchain pin still `1.87.0` (v45's MSRV). The profiling, crashtracker and library-config headers are source compatible with v38 (only additions), so dd-trace-dotnet's native profiler builds unchanged; the musl builds import a few more libc symbols. - **2026-07**: Bumped to libdatadog v38 (from v36). Rust toolchain pin already at `1.87.0`, which matches v38's MSRV, so no toolchain change was needed. diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..21ea414 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4122 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" + +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitmaps" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" + +[[package]] +name = "blazesym" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48ceccc54b9c3e60e5f36b0498908c8c0f87387229cb0e0e5d65a074e00a8ba4" +dependencies = [ + "cpp_demangle 0.5.1", + "gimli", + "libc", + "memmap2", + "miniz_oxide", + "rustc-demangle", + "tracing", +] + +[[package]] +name = "blazesym-c" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35836355f6e78e299510f6d0dd0f09e01f1a80246da8b1730872f91e76c5757c" +dependencies = [ + "blazesym", + "libc", + "memoffset", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "borrow-or-share" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0b364ead1874514c8c2855ab558056ebfeb775653e7ae45ff72f28f8f3166c" + +[[package]] +name = "build_common" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "cbindgen", + "serde_json", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cadence" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62fd689c825a93386a2ac05a46f88342c6df9ec3e79416f665650614e92e7475" +dependencies = [ + "crossbeam-channel", +] + +[[package]] +name = "cbindgen" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "975982cdb7ad6a142be15bdf84aea7ec6a9e5d4d797c004d43185b24cfe4e684" +dependencies = [ + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn 2.0.87", + "tempfile", + "toml", +] + +[[package]] +name = "cc" +version = "1.2.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.6", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "const_format" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constcat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5cd0c57ef83705837b1cb872c973eff82b070846d3e23668322b2c0f8246d0" + +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpp_demangle" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpp_demangle" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0667304c32ea56cb4cd6d2d7c0cfe9a2f8041229db8c033af7f8d69492429def" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-channel" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "datadog-dotnet-ffi" +version = "0.1.0" +dependencies = [ + "anyhow", + "function_name", + "libdd-capabilities-impl", + "libdd-common", + "libdd-common-ffi", + "libdd-profiling-ffi", + "libdd-remote-config", + "strum", + "tokio", + "tokio-util", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fluent-uri" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" +dependencies = [ + "borrow-or-share", + "ref-cast", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "function_name" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ab577a896d09940b5fe12ec5ae71f9d8211fff62c919c03a3750a9901e98a7" +dependencies = [ + "function_name-proc-macro", +] + +[[package]] +name = "function_name-proc-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673464e1e314dd67a0fd9544abc99e8eb28d0c7e3b69b033bcff9b2d00b87333" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "h2" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hickory-proto" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.9.0", + "ring", + "thiserror 2.0.17", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "moka", + "once_cell", + "parking_lot", + "rand 0.9.0", + "resolv-conf", + "smallvec", + "thiserror 2.0.17", + "tokio", + "tracing", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.1", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.10", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.68", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libdd-alloc" +version = "1.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "allocator-api2", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "libdd-capabilities" +version = "4.0.1" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "bytes", + "futures-channel", + "futures-util", + "http", + "thiserror 2.0.17", +] + +[[package]] +name = "libdd-capabilities-impl" +version = "7.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "bytes", + "http", + "http-body-util", + "libdd-capabilities", + "libdd-common", + "tokio", +] + +[[package]] +name = "libdd-common" +version = "8.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "arc-swap", + "bytes", + "cc", + "const_format", + "futures", + "futures-util", + "hex", + "http", + "http-body", + "http-body-util", + "httparse", + "hyper", + "hyper-rustls", + "hyper-util", + "libc", + "mime", + "multer", + "nix 0.29.0", + "pin-project", + "rand 0.8.8", + "regex", + "reqwest", + "rustls", + "rustls-platform-verifier", + "serde", + "static_assertions", + "thiserror 2.0.17", + "tokio", + "tower-service", + "windows-sys 0.52.0", +] + +[[package]] +name = "libdd-common-ffi" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "build_common", + "chrono", + "crossbeam-queue", + "function_name", + "hyper", + "libdd-common", + "serde", +] + +[[package]] +name = "libdd-crashtracker" +version = "3.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "blazesym", + "cc", + "chrono", + "errno", + "http", + "libc", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-gotter", + "libdd-libunwind-sys", + "libdd-telemetry", + "nix 0.29.0", + "num-derive", + "num-traits", + "os_info", + "page_size", + "portable-atomic", + "rand 0.8.8", + "schemars", + "serde", + "serde_json", + "symbolic-common", + "symbolic-demangle", + "thiserror 2.0.17", + "tokio", + "uuid", + "windows 0.59.0", +] + +[[package]] +name = "libdd-crashtracker-ffi" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "build_common", + "function_name", + "libc", + "libdd-common", + "libdd-common-ffi", + "libdd-crashtracker", + "serde_json", + "symbolic-common", + "symbolic-demangle", + "windows 0.59.0", +] + +[[package]] +name = "libdd-data-pipeline" +version = "12.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "arc-swap", + "async-trait", + "bytes", + "either", + "futures", + "h2", + "http", + "http-body-util", + "hyper", + "hyper-util", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-data-pipeline-core", + "libdd-ddsketch", + "libdd-dogstatsd-client", + "libdd-shared-runtime", + "libdd-telemetry", + "libdd-tinybytes", + "libdd-trace-obfuscation", + "libdd-trace-protobuf", + "libdd-trace-stats", + "libdd-trace-utils", + "prost", + "rand 0.8.8", + "rmp-serde", + "serde", + "serde_json", + "sha2", + "tokio", + "tokio-util", + "tonic", + "tracing", + "uuid", + "web-time", +] + +[[package]] +name = "libdd-data-pipeline-core" +version = "3.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "http", + "libdd-capabilities", + "libdd-common", + "libdd-trace-obfuscation", + "libdd-trace-utils", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "libdd-data-pipeline-ffi" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "build_common", + "libdd-capabilities-impl", + "libdd-common", + "libdd-common-ffi", + "libdd-data-pipeline", + "libdd-shared-runtime", + "libdd-tinybytes", + "libdd-trace-obfuscation", + "libdd-trace-utils", + "rmp", + "serde_json", + "tokio-util", + "tracing", +] + +[[package]] +name = "libdd-ddsketch" +version = "1.1.3" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "prost", +] + +[[package]] +name = "libdd-dogstatsd-client" +version = "8.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "async-trait", + "cadence", + "http", + "libdd-common", + "libdd-shared-runtime", + "serde", + "tokio", + "tracing", +] + +[[package]] +name = "libdd-gotter" +version = "1.1.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "libc", +] + +[[package]] +name = "libdd-library-config" +version = "4.2.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "libc", + "libdd-trace-protobuf", + "memfd", + "prost", + "rand 0.8.8", + "rmp-serde", + "serde", + "yaml_serde", +] + +[[package]] +name = "libdd-library-config-ffi" +version = "0.0.2" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "build_common", + "constcat", + "function_name", + "libdd-common", + "libdd-common-ffi", + "libdd-library-config", +] + +[[package]] +name = "libdd-libunwind-sys" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4d5ce7d99aa9244d4dff12d25faf8ad96793183ed049b20f366ce88cf59e68" +dependencies = [ + "cc", + "libc", + "paste", +] + +[[package]] +name = "libdd-profiling" +version = "1.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "allocator-api2", + "anyhow", + "bitmaps", + "byteorder", + "chrono", + "crossbeam-channel", + "crossbeam-utils", + "hashbrown 0.17.1", + "http", + "indexmap", + "libdd-alloc", + "libdd-common", + "libdd-profiling-protobuf", + "parking_lot", + "prost", + "reqwest", + "rustc-hash", + "rustls", + "rustls-platform-verifier", + "serde", + "serde_json", + "target-triple", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "zrip", + "zstd", +] + +[[package]] +name = "libdd-profiling-ffi" +version = "1.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "allocator-api2", + "anyhow", + "build_common", + "function_name", + "hyper", + "libc", + "libdd-common", + "libdd-common-ffi", + "libdd-crashtracker-ffi", + "libdd-data-pipeline-ffi", + "libdd-library-config-ffi", + "libdd-profiling", + "libdd-shared-runtime-ffi", + "serde_json", + "symbolizer-ffi", + "thiserror 2.0.17", + "tokio-util", +] + +[[package]] +name = "libdd-profiling-protobuf" +version = "2.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "prost", +] + +[[package]] +name = "libdd-remote-config" +version = "7.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "base64", + "bytes", + "futures", + "futures-util", + "getrandom 0.2.15", + "hashbrown 0.17.1", + "http", + "http-body-util", + "hyper", + "hyper-util", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-trace-protobuf", + "manual_future", + "serde", + "serde_json", + "sha2", + "strum", + "strum_macros", + "thiserror 2.0.17", + "tokio", + "tokio-util", + "tracing", + "uuid", +] + +[[package]] +name = "libdd-shared-runtime" +version = "6.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "async-trait", + "futures", + "futures-util", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "tokio", + "tokio-util", + "tracing", + "wasm-bindgen-futures", +] + +[[package]] +name = "libdd-shared-runtime-ffi" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "build_common", + "libdd-shared-runtime", + "tracing", +] + +[[package]] +name = "libdd-telemetry" +version = "10.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "async-trait", + "base64", + "bytes", + "futures", + "hashbrown 0.17.1", + "http", + "libc", + "libdd-capabilities", + "libdd-common", + "libdd-ddsketch", + "libdd-shared-runtime", + "serde", + "serde_json", + "strum", + "strum_macros", + "sys-info", + "tokio", + "tokio-util", + "tracing", + "uuid", + "web-time", + "winver", +] + +[[package]] +name = "libdd-tinybytes" +version = "1.1.5" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "serde", +] + +[[package]] +name = "libdd-trace-normalization" +version = "4.2.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "libdd-trace-protobuf", +] + +[[package]] +name = "libdd-trace-obfuscation" +version = "10.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "fluent-uri", + "libdd-common", + "libdd-trace-protobuf", + "libdd-trace-utils", + "log", + "percent-encoding", + "serde", + "serde_json", + "thiserror 2.0.17", +] + +[[package]] +name = "libdd-trace-protobuf" +version = "5.1.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "prost", + "serde", + "serde_bytes", +] + +[[package]] +name = "libdd-trace-stats" +version = "11.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "arc-swap", + "async-trait", + "futures", + "hashbrown 0.17.1", + "http", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-ddsketch", + "libdd-dogstatsd-client", + "libdd-shared-runtime", + "libdd-telemetry", + "libdd-trace-obfuscation", + "libdd-trace-protobuf", + "libdd-trace-utils", + "rmp-serde", + "serde", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "libdd-trace-utils" +version = "14.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "anyhow", + "base64", + "bytes", + "crossbeam-channel", + "futures", + "getrandom 0.2.15", + "hex", + "http", + "http-body", + "http-body-util", + "indexmap", + "itoa", + "libdd-capabilities", + "libdd-capabilities-impl", + "libdd-common", + "libdd-tinybytes", + "libdd-trace-normalization", + "libdd-trace-protobuf", + "prost", + "rand 0.8.8", + "rmp", + "rmp-serde", + "rmpv", + "rustc-hash", + "serde", + "serde-transcode", + "serde_json", + "thin-vec", + "thread_local", + "tracing", +] + +[[package]] +name = "libyaml-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e126dda6f34391ab7b444f9922055facc83c07a910da3eb16f1e4d9c45dc777" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "manual_future" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943968aefb9b0fdf36cccc03f6cd9d6698b23574ab49eccc185ae6c5cb6ad43e" +dependencies = [ + "futures", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix 0.38.39", +] + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5faa9f23e86bd5768d76def086192ff5f869fb088da12a976ea21e9796b975f6" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "moka" +version = "0.12.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +dependencies = [ + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "equivalent", + "parking_lot", + "portable-atomic", + "smallvec", + "tagptr", + "uuid", +] + +[[package]] +name = "msvc-demangler" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4c25a3bb7d880e8eceab4822f3141ad0700d20f025991c1f03bd3d00219a5fc" +dependencies = [ + "bitflags", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" +dependencies = [ + "bitflags", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", + "dispatch2", + "objc2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" +dependencies = [ + "bitflags", + "dispatch2", + "objc2", + "objc2-core-foundation", + "objc2-io-surface", +] + +[[package]] +name = "objc2-core-image" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-location" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca347214e24bc973fc025fd0d36ebb179ff30536ed1f80252706db19ee452009" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-text" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" +dependencies = [ + "bitflags", + "block2", + "libc", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +dependencies = [ + "bitflags", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" +dependencies = [ + "bitflags", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image", + "objc2-core-location", + "objc2-core-text", + "objc2-foundation", + "objc2-quartz-core", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9df9128cbbfef73cda168416ccf7f837b62737d748333bfe9ab71c245d76613e" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +dependencies = [ + "critical-section", + "portable-atomic", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "os_info" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4022a17595a00d6a369236fdae483f0de7f0a339960a53118b818238e132224" +dependencies = [ + "android_system_properties", + "log", + "nix 0.30.1", + "objc2", + "objc2-foundation", + "objc2-ui-kit", + "windows-sys 0.61.2", +] + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +dependencies = [ + "serde", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy 0.7.35", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", + "zerocopy 0.8.24", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "hickory-resolver", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "resolv-conf" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + +[[package]] +name = "rmpv" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58450723cd9ee93273ce44a20b6ec4efe17f8ed2e3631474387bfdecf18bb2a9" +dependencies = [ + "num-traits", + "rmp", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "0.38.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.14", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustix" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "schemars" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1eee588578aff73f856ab961cd2f79e36bc45d7ded33a7562adba4667aecc0e" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.87", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-transcode" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "590c0e25c2a5bb6e85bf5c1bce768ceb86b316e7a01bdf07d2cb4ec2271990e2" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.87", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symbolic-common" +version = "12.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "366f1b4c6baf6cfefc234bbd4899535fca0b06c74443039a73f6dfb2fad88d77" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "12.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aba05ba5b9962ea5617baf556293720a8b2d0a282aa14ee4bf10e22efc7da8c8" +dependencies = [ + "cpp_demangle 0.4.4", + "msvc-demangler", + "rustc-demangle", + "symbolic-common", +] + +[[package]] +name = "symbolizer-ffi" +version = "45.0.0" +source = "git+https://github.com/DataDog/libdatadog?rev=6851293707e6b777b0dde428a13940b2293a8434#6851293707e6b777b0dde428a13940b2293a8434" +dependencies = [ + "blazesym-c", + "build_common", +] + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "sys-info" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "target-triple" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac9aa371f599d22256307c24a9d748c041e548cbf599f35d890f9d365361790" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.2", + "once_cell", + "rustix 1.1.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "thin-vec" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f7e269b48f0a7dd0146680fa24b50cc67fc0373f086a5b2f99bd084639b482" + +[[package]] +name = "thiserror" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +dependencies = [ + "thiserror-impl 1.0.68", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl 2.0.17", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2 0.6.1", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076" + +[[package]] +name = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "base64", + "bytes", + "http", + "http-body", + "http-body-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio-stream", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom 0.2.15", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +dependencies = [ + "windows-core 0.59.0", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-strings", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-strings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winver" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e0e7162b9e282fd75a0a832cce93994bdb21208d848a418cd05a5fdd9b9ab33" +dependencies = [ + "windows 0.48.0", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yaml_serde" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b729a08a9a6be689bbad3e2bf8015926db54b6622cc89c3a5f7dc174b9e918" +dependencies = [ + "indexmap", + "itoa", + "libyaml-rs", + "ryu", + "serde", +] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +dependencies = [ + "zerocopy-derive 0.8.24", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "zrip" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964fe9f1ea10a0d183fc143a7525266cbe16978883dbe304725da34b314c04cf" +dependencies = [ + "zrip-core", + "zrip-decode", + "zrip-encode", +] + +[[package]] +name = "zrip-core" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc201ba56175f86e67cc88bdaf1a7af9c061815c7dde719c7a6a1ed5aaa186b" + +[[package]] +name = "zrip-decode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038f795e49887bdeaab197fff84c8165644484a98dc3f2354e5df3d2e5f4f978" +dependencies = [ + "zrip-core", +] + +[[package]] +name = "zrip-encode" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3dfdcbb503db2045716492d5ab31cd82f2852d0d93d8edf6a9235653d9da685" +dependencies = [ + "zrip-core", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.14+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/README.md b/README.md index 1203d67..e42c692 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ To upgrade the upstream libdatadog version, change the `tag` (e.g. `tag = "v32.0 ### Features -Built with the comma-separated feature set the .NET tracer needs (see `build.ps1` / workflow inputs): +Built with the fixed feature set the .NET tracer needs (`FEATURES` in `build.sh` / `build.ps1`, matching the `libdd-profiling-ffi` features in `datadog-dotnet-ffi/Cargo.toml`): ``` profiling,crashtracker,symbolizer,library-config @@ -60,7 +60,7 @@ The builder handles the FFI cargo build, header generation (cbindgen + dedup), l The shared library itself (`libdatadog_profiling.{so,dylib}`, `datadog_profiling_ffi.dll`) comes from `datadog-dotnet-ffi`, this repository's crate: it re-exports libdatadog's profiling FFI (with the same features) and adds .NET specific FFI, like the remote configuration client (`ddog_rc_*`). It keeps the library name, so it's a drop-in replacement for the C++ profiler and the tracer. Only the .NET tracer uses the additional exports, so there are no headers for them. -To build against a local libdatadog checkout, pass `--libdatadog-path ../libdatadog` (`-LibdatadogPath` on Windows): the libdatadog dependencies of `datadog-dotnet-ffi` are then patched to it, so the builder comes from there too. +To build against a local libdatadog checkout, pass `--libdatadog-path ../libdatadog` (`-LibdatadogPath` on Windows): the libdatadog dependencies of `datadog-dotnet-ffi` are then patched to it, so the builder comes from there too. This changes `Cargo.lock` locally; don't commit that. **Windows quirk**: the builder produces a flat `lib/datadog_profiling.{dll,lib,pdb}` layout, but dd-trace-dotnet's vcpkg portfile expects the legacy `release/{dynamic,static}` + `debug/{dynamic,static}` tree with `_ffi`-suffixed filenames. `build.ps1` runs the builder twice (release + debug) and reassembles that layout from cargo's raw `target/` output. diff --git a/build.ps1 b/build.ps1 index 49c52f8..8296250 100644 --- a/build.ps1 +++ b/build.ps1 @@ -32,7 +32,6 @@ param( [string]$Platform = "x64-windows", [string]$OutputDir = "output", - [string]$Features = "profiling,crashtracker,symbolizer,library-config", [switch]$Clean, # Build from a local libdatadog checkout instead of the revision in datadog-dotnet-ffi/Cargo.toml [string]$LibdatadogPath = "" @@ -40,6 +39,10 @@ param( $ErrorActionPreference = "Stop" +# Builder crate features: which FFI modules (headers etc.) the package contains. Must match the +# libdd-profiling-ffi features in datadog-dotnet-ffi/Cargo.toml, which the shipped library is built with. +$Features = "profiling,crashtracker,symbolizer,library-config" + # Resolve target triple from platform name $TargetMap = @{ "x64-windows" = "x86_64-pc-windows-msvc" @@ -74,8 +77,9 @@ $OutputDir = (Resolve-Path $OutputDir).Path $PackageDir = Join-Path $OutputDir "libdatadog-$Platform" # A local libdatadog checkout replaces the libdatadog dependencies of datadog-dotnet-ffi via a -# cargo [patch] (passed with --config), and with them the libdatadog sources found below. -$CargoConfig = @() +# cargo [patch] (passed with --config), and with them the libdatadog sources found below. Otherwise +# the committed Cargo.lock is used as is. +$CargoArgs = @("--locked") if ($LibdatadogPath) { $LibdatadogPath = (Resolve-Path $LibdatadogPath).Path $Patch = Join-Path $PWD "target/libdatadog-patch.toml" @@ -84,14 +88,14 @@ if ($LibdatadogPath) { ForEach-Object { $_.Matches[0].Groups[1].Value } | Sort-Object -Unique @('[patch."https://github.com/DataDog/libdatadog"]') + ($Crates | ForEach-Object { "$_ = { path = '$(Join-Path $LibdatadogPath $_)' }" }) | Set-Content -Encoding ascii $Patch - $CargoConfig = @("--config", $Patch) + $CargoArgs = @("--config", $Patch) } # The libdatadog sources datadog-dotnet-ffi is built from: cargo's checkout of its libdatadog # dependencies, or the local checkout. The builder is installed from there, so that the # headers etc. match the library. $HostTriple = (rustc -vV 2>&1 | Where-Object { $_ -match "^host:" }) -replace "^host:\s*", "" -$Metadata = cargo metadata --format-version 1 --filter-platform $HostTriple @CargoConfig | ConvertFrom-Json +$Metadata = cargo metadata --format-version 1 --filter-platform $HostTriple @CargoArgs | ConvertFrom-Json if ($LASTEXITCODE -ne 0) { Write-Host "Error: cargo metadata failed" -ForegroundColor Red exit 1 @@ -176,16 +180,15 @@ $ReleaseOut = Invoke-Builder -BuildProfile "release" $DebugOut = Invoke-Builder -BuildProfile "debug" # Build datadog-dotnet-ffi, which replaces the profiling DLL. The PDB path embedded in the -# DLL already gets the final name. Uses the dependency versions libdatadog is tested with. +# DLL already gets the final name. # Not in the builder's target directory: some libdatadog crates have library file names without # a hash, which the builder's and this build would overwrite for each other. -Copy-Item -Path (Join-Path $LibdatadogDir "Cargo.lock") -Destination (Join-Path $PWD "Cargo.lock") -Force $FfiTargetDir = Join-Path $CargoTargetDir "dotnet-ffi" $env:CARGO_TARGET_DIR = $FfiTargetDir $env:RUSTFLAGS = "-C relocation-model=pic -C target-feature=+crt-static -C link-arg=/PDBALTPATH:datadog_profiling_ffi.pdb" foreach ($p in @("release", "debug")) { $cargoProfile = if ($p -eq "debug") { "dev" } else { $p } - cargo build -p datadog-dotnet-ffi --target $Target --profile $cargoProfile @CargoConfig + cargo build -p datadog-dotnet-ffi --target $Target --profile $cargoProfile @CargoArgs if ($LASTEXITCODE -ne 0) { Write-Host "Error: building datadog-dotnet-ffi ($p) failed" -ForegroundColor Red exit 1 diff --git a/build.sh b/build.sh index 4d8c3cf..7c237f3 100755 --- a/build.sh +++ b/build.sh @@ -16,7 +16,6 @@ set -e PLATFORM="" OUTPUT_DIR="output" PROFILE="release" -FEATURES="" CLEAN=false LIBDATADOG_PATH="" @@ -25,7 +24,6 @@ while [[ $# -gt 0 ]]; do --platform) PLATFORM="$2"; shift 2 ;; --output) OUTPUT_DIR="$2"; shift 2 ;; --profile) PROFILE="$2"; shift 2 ;; - --features) FEATURES="$2"; shift 2 ;; --clean) CLEAN=true; shift ;; --libdatadog-path) LIBDATADOG_PATH="$2"; shift 2 ;; -h|--help) @@ -35,9 +33,6 @@ while [[ $# -gt 0 ]]; do echo " --platform PLATFORM Target platform / output directory suffix" echo " --output DIR Output directory (default: output)" echo " --profile PROFILE Build profile: debug or release (default: release)" - echo " --features FEATURES Comma-separated builder crate features" - echo " (default: profiling,crashtracker," - echo " symbolizer,library-config)" echo " --clean Remove output directory before building" echo " --libdatadog-path P Build from a local libdatadog checkout instead of" echo " the revision in datadog-dotnet-ffi/Cargo.toml" @@ -65,11 +60,10 @@ TARGET="${CARGO_BUILD_TARGET:-$PLATFORM}" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" -# Builder crate features compiled into the release binary. -# These control which FFI modules are included in the output library. -# Feature names map to flags in builder/src/bin/release.rs in libdatadog. -# Override via --features on the command line. -FEATURES="${FEATURES:-profiling,crashtracker,symbolizer,library-config}" +# Builder crate features: which FFI modules (headers etc.) the package contains. Feature names map +# to flags in builder/src/bin/release.rs in libdatadog. Must match the libdd-profiling-ffi features +# in datadog-dotnet-ffi/Cargo.toml, which the shipped library is built with. +FEATURES="profiling,crashtracker,symbolizer,library-config" if [[ "$CLEAN" == true ]]; then rm -rf "$OUTPUT_DIR" diff --git a/datadog-dotnet-ffi/Cargo.toml b/datadog-dotnet-ffi/Cargo.toml index b4687c2..f2e37a0 100644 --- a/datadog-dotnet-ffi/Cargo.toml +++ b/datadog-dotnet-ffi/Cargo.toml @@ -28,7 +28,7 @@ libdd-common = { git = "https://github.com/DataDog/libdatadog", rev = "685129370 libdd-common-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["std"] } libdd-remote-config = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = ["client"] } # Must be the feature list the libdatadog builder computes for the libdatadog-dotnet builder -# features (profiling,crashtracker,symbolizer,library-config), see builder/src/features.rs. +# features (FEATURES in build.sh / build.ps1), see builder/src/features.rs. libdd-profiling-ffi = { git = "https://github.com/DataDog/libdatadog", rev = "6851293707e6b777b0dde428a13940b2293a8434", default-features = false, features = [ "ddcommon-ffi", "catch_panic", diff --git a/tools/build-ffi.sh b/tools/build-ffi.sh index f199a02..de1a969 100755 --- a/tools/build-ffi.sh +++ b/tools/build-ffi.sh @@ -17,8 +17,12 @@ PACKAGE_DIR="$3" cd "$(dirname "$0")/.." -# Build with the dependency versions libdatadog itself is tested with. -cp "$(sh tools/libdatadog.sh dir)/Cargo.lock" Cargo.lock +# The committed Cargo.lock, unless patched to a local libdatadog checkout (see build.sh) +if [ -n "$LIBDATADOG_PATCH" ]; then + CARGO_ARGS="--config $LIBDATADOG_PATCH" +else + CARGO_ARGS="--locked" +fi case "$TARGET" in *-apple-darwin) @@ -46,7 +50,7 @@ esac # Not in the builder's target directory: some libdatadog crates have library file names without # a hash, which the builder's and this build would overwrite for each other. cargo build -p datadog-dotnet-ffi --target "$TARGET" --profile "$CARGO_PROFILE" \ - --target-dir target/dotnet-ffi ${LIBDATADOG_PATCH:+--config "$LIBDATADOG_PATCH"} + --target-dir target/dotnet-ffi $CARGO_ARGS cp "target/dotnet-ffi/$TARGET/$PROFILE_DIR/$BUILT" "$PACKAGE_DIR/lib/$LIB" diff --git a/tools/libdatadog.sh b/tools/libdatadog.sh index 8798e76..069769e 100755 --- a/tools/libdatadog.sh +++ b/tools/libdatadog.sh @@ -12,8 +12,15 @@ set -e cd "$(dirname "$0")/.." +# The committed Cargo.lock, unless patched to a local libdatadog checkout (see build.sh) +if [ -n "$LIBDATADOG_PATCH" ]; then + CARGO_ARGS="--config $LIBDATADOG_PATCH" +else + CARGO_ARGS="--locked" +fi + HOST=$(rustc -vV | sed -n 's/^host: //p') -DIR=$(cargo metadata --format-version 1 --filter-platform "$HOST" ${LIBDATADOG_PATCH:+--config "$LIBDATADOG_PATCH"} | +DIR=$(cargo metadata --format-version 1 --filter-platform "$HOST" $CARGO_ARGS | grep -o '"manifest_path":"[^"]*/libdd-profiling-ffi/Cargo.toml"' | sed 's|^"manifest_path":"\(.*\)/libdd-profiling-ffi/Cargo.toml"$|\1|') if [ -z "$DIR" ]; then