From 16854e0e3191bb837e59ca540d065ce03e9d61d2 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 21 Oct 2026 18:10:16 +0100 Subject: [PATCH 1/6] Derive the smoke test's dd-trace version from the built package ToolVersion existed only so one smoke test could install the dd-trace tool by exact version, which made the pipeline YAML an output of the version-bump tooling. The step now derives it from the nupkg the build produced, so the version does not have to be kept in step by hand. --- .azure-pipelines/ultimate-pipeline.yml | 5 +++-- tracer/build/_build/Build.GitHub.cs | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index e757b0cf324f..d8ecd9ff324d 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -159,7 +159,6 @@ variables: DD_LOGGER_DD_TAGS: test.configuration.job:$(System.JobDisplayName) DD_LOGGER_ENABLED: true DD_COLLECTOR_CPU_USAGE: true - ToolVersion: 3.57.0 # .NET SDK performance optimization variables DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -5722,7 +5721,9 @@ stages: - script: | dotnet --info - dotnet tool install dd-trace --tool-path $(smokeTestAppDir)/publish --add-source $(smokeTestAppDir)/artifacts/. --version $(ToolVersion) + TOOL_VERSION=$(basename $(smokeTestAppDir)/artifacts/dd-trace.*.nupkg | sed 's/^dd-trace\.//; s/\.nupkg$//') + echo "Installing dd-trace $TOOL_VERSION" + dotnet tool install dd-trace --tool-path $(smokeTestAppDir)/publish --add-source $(smokeTestAppDir)/artifacts/. --version "$TOOL_VERSION" displayName: Install tracer - script: | diff --git a/tracer/build/_build/Build.GitHub.cs b/tracer/build/_build/Build.GitHub.cs index 9e0fc4e14579..f1110381361f 100644 --- a/tracer/build/_build/Build.GitHub.cs +++ b/tracer/build/_build/Build.GitHub.cs @@ -448,7 +448,6 @@ await client.Issue.Milestone.Update( { var expectedFileChanges = new List { - ".azure-pipelines/ultimate-pipeline.yml", "profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt", "profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc", "profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h", From be3d3330f6b6043fd0944ca40eda0151dffafa40 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 21 Oct 2026 18:03:24 +0100 Subject: [PATCH 2/6] Consolidate the version number into version.props The SDK version was previously written into 19 source files, kept in step by a regex rewriter. This consolidates the version into just 2 files - dd_version.h and version.props - and derives all the values from it. - We use a source generator to make the version available to managed code. - CMake projects import via build/cmake/DdVersion.cmake The one remaining usage of a hard-coded version is in dd-dotnet.sh, fixed in the next commit. The generated output of the source generator is gitignored rather than committed, unlike our other generators. This isn't strictly necessary today, but it opens the way for having dynamic "dev" builds. --- .github/workflows/_create_draft_release.yml | 1 - .../workflows/auto_create_version_bump_pr.yml | 10 +- .gitignore | 4 + CMakeLists.txt | 3 +- build/DdVersion.props | 29 +++ build/cmake/DdVersion.cmake | 42 ++++ profiler/Directory.Build.props | 5 + .../Datadog.Linux.ApiWrapper/CMakeLists.txt | 3 +- .../CMakeLists.txt | 3 +- .../Resource.rc | 10 +- .../dd_profiler_version.h | 2 +- .../src/ProfilerEngine/ProductVersion.props | 5 +- shared/Directory.Build.props | 1 + .../CMakeLists.txt | 3 +- .../Directory.Build.props | 1 + .../Resource.rc | 10 +- .../msi-installer/WindowsInstaller.wixproj | 8 +- shared/src/native-src/dd_version.h | 29 +++ shared/src/native-src/version.h | 9 +- .../Directory.Build.props | 1 + tracer/Directory.Build.props | 16 ++ tracer/build/_build/Build.GitHub.cs | 31 +-- tracer/build/_build/Build.Steps.cs | 1 - tracer/build/_build/Build.Utilities.cs | 19 +- tracer/build/_build/Build.cs | 9 +- .../_build/PrepareRelease/SetAllVersions.cs | 215 ++++-------------- tracer/build/_build/_build.csproj | 12 + ...og.Trace.ClrProfiler.Managed.Loader.csproj | 7 +- .../Startup.cs | 4 +- .../CreatedumpCommand.cs | 4 +- .../Datadog.Trace.Tools.dd_dotnet.csproj | 3 +- tracer/src/Datadog.Trace/Datadog.Trace.csproj | 6 + tracer/src/Datadog.Trace/TracerConstants.cs | 10 +- .../src/Datadog.Tracer.Native/CMakeLists.txt | 3 +- .../Directory.Build.props | 1 + tracer/src/Datadog.Tracer.Native/Resource.rc | 10 +- .../dd_profiler_constants.h | 5 +- tracer/src/Directory.Build.props | 2 +- .../Checks/ProcessBasicChecksTests.cs | 8 +- ...ce.Tools.dd_dotnet.IntegrationTests.csproj | 13 +- .../Directory.Build.props | 1 + .../MismatchedTracerVersions/Build-Tracer.ps1 | 2 +- tracer/tools/Build-AzureFunctionsNuget.ps1 | 8 +- version.props | 31 +++ 44 files changed, 327 insertions(+), 273 deletions(-) create mode 100644 build/DdVersion.props create mode 100644 build/cmake/DdVersion.cmake create mode 100644 shared/src/native-src/dd_version.h create mode 100644 version.props diff --git a/.github/workflows/_create_draft_release.yml b/.github/workflows/_create_draft_release.yml index 3cb5e7bf0b5b..7a4d95e20465 100644 --- a/.github/workflows/_create_draft_release.yml +++ b/.github/workflows/_create_draft_release.yml @@ -132,7 +132,6 @@ jobs: if: ${{ !inputs.is_hotfix }} run: ./tracer/build.sh RenameVNextMilestone env: - Version: ${{steps.versions.outputs.full_version}} GITHUB_TOKEN: "${{ steps.generate-token.outputs.token }}" - name: Create Release diff --git a/.github/workflows/auto_create_version_bump_pr.yml b/.github/workflows/auto_create_version_bump_pr.yml index 68f7ac163ddd..82264a09c01e 100644 --- a/.github/workflows/auto_create_version_bump_pr.yml +++ b/.github/workflows/auto_create_version_bump_pr.yml @@ -61,6 +61,11 @@ jobs: run: .\tracer\build.ps1 CalculateNextVersion id: versions + # Must run before "Bump Version": CloseMilestone closes the milestone matching the version in + # version.props, which is the just-released version until the bump rewrites it. + - name: "Close previous milestone" + run: .\tracer\build.ps1 CloseMilestone + - name: "Bump Version" run: .\tracer\build.ps1 UpdateVersion env: @@ -83,11 +88,6 @@ jobs: reviewers: "DataDog/apm-dotnet" body: "${{steps.changes.outputs.release_notes}}" - - name: "Close previous milestone" - run: .\tracer\build.ps1 CloseMilestone - env: - Version: ${{steps.versions.outputs.previous_version}} - - name: Display output run: | echo "Pull Request Number - ${{ steps.pr.outputs.pull-request-number }}" diff --git a/.gitignore b/.gitignore index f70f54c49eb0..5c1e22440a8c 100644 --- a/.gitignore +++ b/.gitignore @@ -402,3 +402,7 @@ tools/dumps/ # test optimization temp/run folder .dd/ + +# NetEscapades.ProjectInfo output. Unlike our other generators, this one emits the version +# number, so a committed copy would have to be regenerated on every version bump. +**/Generated/**/NetEscapades.ProjectInfo/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 88325575aa6f..a1683434f83e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,8 @@ endif() # Project definition # ****************************************************** -project("Datadog.APM.Native" VERSION 2.18.0) +include("${CMAKE_CURRENT_LIST_DIR}/build/cmake/DdVersion.cmake") +project("Datadog.APM.Native" VERSION ${DD_VERSION}) # ****************************************************** # Environment detection diff --git a/build/DdVersion.props b/build/DdVersion.props new file mode 100644 index 000000000000..eadfd0b8ba7c --- /dev/null +++ b/build/DdVersion.props @@ -0,0 +1,29 @@ + + + + + + + + DD_VERSION_MAJOR=$([System.Version]::Parse('$(DD_VersionPrefix)').Major);DD_VERSION_MINOR=$([System.Version]::Parse('$(DD_VersionPrefix)').Minor);DD_VERSION_PATCH=$([System.Version]::Parse('$(DD_VersionPrefix)').Build) + + + + + $(DD_NativeVersionDefinitions);%(PreprocessorDefinitions) + + + $(DD_NativeVersionDefinitions);%(PreprocessorDefinitions) + + + + diff --git a/build/cmake/DdVersion.cmake b/build/cmake/DdVersion.cmake new file mode 100644 index 000000000000..8849941d5d77 --- /dev/null +++ b/build/cmake/DdVersion.cmake @@ -0,0 +1,42 @@ +# Exposes the version from /version.props as DD_VERSION, for project(... VERSION ...), +# which accepts only a numeric major[.minor[.patch[.tweak]]]. Also adds the DD_VERSION_* compile +# definitions that shared/src/native-src/dd_version.h expects (build/DdVersion.props defines the same set +# for the MSBuild builds). +# +# Deliberately re-read on every include and stored as a normal (not cached) variable, so that a +# version bump is picked up by an existing build directory, and you don't get weird instrumentation +# mismatches locally, just after a release. + +get_filename_component(DD_REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) + +set(DD_VERSION_PROPS "${DD_REPO_ROOT}/version.props") +if(NOT EXISTS "${DD_VERSION_PROPS}") + message(FATAL_ERROR "Could not find ${DD_VERSION_PROPS}. This file holds the SDK version number.") +endif() + +# Re-run configure whenever version.props changes +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${DD_VERSION_PROPS}") + +file(READ "${DD_VERSION_PROPS}" _dd_version_props_content) +string(REGEX MATCH "(([0-9]+)\.([0-9]+)\.([0-9]+))" + _dd_version_match "${_dd_version_props_content}") +if(NOT _dd_version_match) + message(FATAL_ERROR "Could not parse out of ${DD_VERSION_PROPS}.") +endif() + +set(DD_VERSION "${CMAKE_MATCH_1}") +message(STATUS "Datadog SDK version: ${DD_VERSION}") + +# Directory-scoped, so they apply to every target in this directory and below. The subproject +# CMakeLists include this file again, so only add them once: normal variables are inherited by +# subdirectories. +if(NOT DD_VERSION_DEFINITIONS_ADDED) + add_compile_definitions( + DD_VERSION_MAJOR=${CMAKE_MATCH_2} + DD_VERSION_MINOR=${CMAKE_MATCH_3} + DD_VERSION_PATCH=${CMAKE_MATCH_4}) + set(DD_VERSION_DEFINITIONS_ADDED TRUE) +endif() + +unset(_dd_version_props_content) +unset(_dd_version_match) diff --git a/profiler/Directory.Build.props b/profiler/Directory.Build.props index c2bb9c32222f..827543fcb94b 100644 --- a/profiler/Directory.Build.props +++ b/profiler/Directory.Build.props @@ -7,6 +7,11 @@ + + + + diff --git a/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt b/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt index 2ce485ced6b7..32d51a978c4e 100644 --- a/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt +++ b/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt @@ -2,7 +2,8 @@ # Project definition # ****************************************************** -project("Datadog.Linux.ApiWrapper" VERSION 3.57.0) +include("${CMAKE_CURRENT_LIST_DIR}/../../../../build/cmake/DdVersion.cmake") +project("Datadog.Linux.ApiWrapper" VERSION ${DD_VERSION}) # ****************************************************** # Compiler options diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt index f3a26c4f0eae..6dc8a186ed2f 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt @@ -2,7 +2,8 @@ # Project definition # ****************************************************** -project("Datadog.Profiler.Native.Linux" VERSION 3.57.0) +include("${CMAKE_CURRENT_LIST_DIR}/../../../../build/cmake/DdVersion.cmake") +project("Datadog.Profiler.Native.Linux" VERSION ${DD_VERSION}) option(RUN_ASAN "Build with Clang Undefined-Behavior Sanitizer" OFF) option(RUN_UBSAN "Build with Clang Undefined-Behavior Sanitizer" OFF) diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc index 6f00f555a1c2..6dd8332ff031 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc @@ -61,9 +61,11 @@ END #endif // not APSTUDIO_INVOKED // ------- version info ------------------------------------------------------- +#include "../../../../shared/src/native-src/dd_version.h" + VS_VERSION_INFO VERSIONINFO -FILEVERSION 3,57,0,0 -PRODUCTVERSION 3,57,0,0 +FILEVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION +PRODUCTVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION FILEFLAGSMASK VS_FF_PRERELEASE FILEOS VOS_NT FILETYPE VFT_DLL @@ -74,12 +76,12 @@ BEGIN BEGIN VALUE "CompanyName", "Datadog" VALUE "FileDescription", "Continuous Profiler for .NET Applications" - VALUE "FileVersion", "3.57.0.0" + VALUE "FileVersion", DD_FOUR_PART_VERSION_STR VALUE "InternalName", "Native Profiler Engine" VALUE "LegalCopyright", "(c) Datadog 2020-2022" VALUE "OriginalFilename", "Datadog.Profiler.Native.dll" VALUE "ProductName", "Continuous Profiler for .NET Applications" - VALUE "ProductVersion", "3.57.0.0" + VALUE "ProductVersion", DD_FOUR_PART_VERSION_STR END END BLOCK "VarFileInfo" diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h index f62a7da7ec69..8139661fde3f 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h @@ -3,4 +3,4 @@ #pragma once -constexpr auto PROFILER_VERSION = "3.57.0"; +#include "../../../../shared/src/native-src/version.h" diff --git a/profiler/src/ProfilerEngine/ProductVersion.props b/profiler/src/ProfilerEngine/ProductVersion.props index 912ea669192e..49f894b8638c 100644 --- a/profiler/src/ProfilerEngine/ProductVersion.props +++ b/profiler/src/ProfilerEngine/ProductVersion.props @@ -3,11 +3,10 @@ - + - 3.57.0 + $(DD_VersionPrefix) - +$([System.DateTime]::UtcNow.ToString('yyyyMMddHHmmss')) diff --git a/shared/Directory.Build.props b/shared/Directory.Build.props index ab263820c0bf..5f2c590c7f62 100644 --- a/shared/Directory.Build.props +++ b/shared/Directory.Build.props @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt b/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt index b602aed1eb37..7257d32c34ea 100644 --- a/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt +++ b/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt @@ -12,7 +12,8 @@ endif() # Project definition # ****************************************************** -project("Datadog.Trace.ClrProfiler.Native" VERSION 3.57.0) +include("${CMAKE_CURRENT_LIST_DIR}/../../../build/cmake/DdVersion.cmake") +project("Datadog.Trace.ClrProfiler.Native" VERSION ${DD_VERSION}) if (UNIVERSAL) find_package(GlibcCompat REQUIRED) diff --git a/shared/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props b/shared/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props index 8c119d5413b5..48b5a10540c0 100644 --- a/shared/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props +++ b/shared/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props @@ -1,2 +1,3 @@ + diff --git a/shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc b/shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc index 49257d86c26a..16eefe4ca56b 100644 --- a/shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc +++ b/shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc @@ -50,6 +50,8 @@ END // Version // +#include "../native-src/dd_version.h" + VS_VERSION_INFO VERSIONINFO FILEFLAGSMASK 0x3fL #ifdef _DEBUG @@ -57,8 +59,8 @@ VS_VERSION_INFO VERSIONINFO #else FILEFLAGS 0x0L #endif - FILEVERSION 3,57,0,0 - PRODUCTVERSION 3,57,0,0 + FILEVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION + PRODUCTVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION FILEOS VOS_NT FILETYPE VFT_DLL BEGIN @@ -68,12 +70,12 @@ BEGIN BEGIN VALUE "CompanyName", "Datadog" VALUE "FileDescription", "Native loader for Datadog .NET APM" - VALUE "FileVersion", "3.57.0.0" + VALUE "FileVersion", DD_FOUR_PART_VERSION_STR VALUE "InternalName", "Native loader" VALUE "LegalCopyright", "(c) Datadog 2020-2022" VALUE "OriginalFilename", "Datadog.Trace.ClrProfiler.Native.dll" VALUE "ProductName", "Native loader for Datadog .NET APM" - VALUE "ProductVersion", "3.57.0.0" + VALUE "ProductVersion", DD_FOUR_PART_VERSION_STR END END BLOCK "VarFileInfo" diff --git a/shared/src/msi-installer/WindowsInstaller.wixproj b/shared/src/msi-installer/WindowsInstaller.wixproj index 4718ea0cb83e..c4d2c3c2265a 100644 --- a/shared/src/msi-installer/WindowsInstaller.wixproj +++ b/shared/src/msi-installer/WindowsInstaller.wixproj @@ -7,9 +7,13 @@ bin\$(Configuration)\$(Platform)\ $(MsiOutputPath) obj\$(Configuration)\$(Platform)\ - datadog-dotnet-apm-3.57.0-$(Platform) + datadog-dotnet-apm-$(DD_SemVer)-$(Platform) $(MSBuildThisFileDirectory)..\..\bin\monitoring-home - InstallerVersion=3.57.0;MonitoringHomeDirectory=$(MonitoringHomeDirectory); + + InstallerVersion=$(DD_VersionPrefix);MonitoringHomeDirectory=$(MonitoringHomeDirectory); $(DefineConstants);Debug diff --git a/shared/src/native-src/dd_version.h b/shared/src/native-src/dd_version.h new file mode 100644 index 000000000000..67c025a3e6f4 --- /dev/null +++ b/shared/src/native-src/dd_version.h @@ -0,0 +1,29 @@ +#ifndef DD_VERSION_H +#define DD_VERSION_H + +// The SDK version for native code and the Windows resource scripts. The build passes only the major, +// minor and patch numbers, as preprocessor definitions derived from version.props: see +// build/DdVersion.props for MSBuild and build/cmake/DdVersion.cmake for CMake. Everything else is +// derived here, so adding a new derived value only requires changing this file. +// +// #define rather than constexpr, and include guards rather than #pragma once, because rc.exe +// preprocesses this file too and supports neither. + +#if !defined(DD_VERSION_MAJOR) || !defined(DD_VERSION_MINOR) || !defined(DD_VERSION_PATCH) +#error "The DD_VERSION_* definitions are missing. They come from build/DdVersion.props (MSBuild) or build/cmake/DdVersion.cmake (CMake)." +#endif + +// The native tracer and the managed loader both resolve Datadog.Trace by its exact strong name, so the +// revision stays at zero. +#define DD_VERSION_REVISION 0 + +// Two levels are needed: # stringifies its argument exactly as written, so DD_STRINGIFY_IMPL(DD_VERSION_MAJOR) +// would produce the macro's name rather than its value. Passing through DD_STRINGIFY first expands the +// macros to their values, so DD_STRINGIFY(DD_VERSION_MAJOR.DD_VERSION_MINOR) produces "1.2". +#define DD_STRINGIFY_IMPL(x) #x +#define DD_STRINGIFY(x) DD_STRINGIFY_IMPL(x) + +#define DD_THREE_PART_VERSION_STR DD_STRINGIFY(DD_VERSION_MAJOR.DD_VERSION_MINOR.DD_VERSION_PATCH) +#define DD_FOUR_PART_VERSION_STR DD_STRINGIFY(DD_VERSION_MAJOR.DD_VERSION_MINOR.DD_VERSION_PATCH.DD_VERSION_REVISION) + +#endif // DD_VERSION_H diff --git a/shared/src/native-src/version.h b/shared/src/native-src/version.h index 929206863176..a910de5ff1de 100644 --- a/shared/src/native-src/version.h +++ b/shared/src/native-src/version.h @@ -1,3 +1,10 @@ #pragma once -constexpr auto PROFILER_VERSION = "3.57.0"; +#include "dd_version.h" + +// This must stay a bare numeric version (no suffix): +// - Instrumentation.cs compares GetNativeTracerVersion() (which the native profiler IL-rewrites +// to this value) against TracerConstants.ThreePartVersion for an exact string match. +// - generated_calltargets.g.cpp builds the managed assembly's strong name by concatenating +// "Datadog.Trace, Version=" + PROFILER_VERSION + ".0, Culture=...". +constexpr auto PROFILER_VERSION = DD_THREE_PART_VERSION_STR; diff --git a/shared/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props b/shared/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props index 8c119d5413b5..48b5a10540c0 100644 --- a/shared/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props +++ b/shared/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props @@ -1,2 +1,3 @@ + diff --git a/tracer/Directory.Build.props b/tracer/Directory.Build.props index 9d5912bbc11b..0062fcc7f8fe 100644 --- a/tracer/Directory.Build.props +++ b/tracer/Directory.Build.props @@ -1,4 +1,6 @@ + + false true @@ -18,6 +20,20 @@ $(NoWarn);SYSLIB0014;NU1901;NU1902;NU1903;NU1904 + + + + + + diff --git a/tracer/build/_build/Build.GitHub.cs b/tracer/build/_build/Build.GitHub.cs index f1110381361f..c1a5ebbbd39b 100644 --- a/tracer/build/_build/Build.GitHub.cs +++ b/tracer/build/_build/Build.GitHub.cs @@ -71,7 +71,7 @@ partial class Build const string GitHubRepositoryOwner = "DataDog"; const string AzureDevopsOrganisation = "https://dev.azure.com/datadoghq"; - string FullVersion => IsPrerelease ? $"{Version}-prerelease" : Version; + string FullVersion => ProjectInfo.SemVer; Target AssignPullRequestToMilestone => _ => _ .Unlisted() @@ -320,7 +320,6 @@ LabbelerConfiguration GetLabellerConfiguration() Target CloseMilestone => _ => _ .Unlisted() .Requires(() => GitHubToken) - .Requires(() => Version) .Executes(async() => { var client = GetGitHubClient(); @@ -355,7 +354,6 @@ await client.Issue.Milestone.Update( .Unlisted() .Requires(() => GitHubRepositoryName) .Requires(() => GitHubToken) - .Requires(() => Version) .Executes(async() => { var client = GetGitHubClient(); @@ -386,7 +384,6 @@ await client.Issue.Milestone.Update( Target OutputCurrentVersionToGitHub => _ => _ .Unlisted() .After(UpdateVersion) - .Requires(() => Version) .Executes(async () => { Console.WriteLine("Using version to " + FullVersion); @@ -409,7 +406,6 @@ await client.Issue.Milestone.Update( Target CalculateNextVersion => _ => _ .Unlisted() - .Requires(() => Version) .Executes(() => { Console.WriteLine("Current version is " + Version); @@ -446,19 +442,14 @@ await client.Issue.Milestone.Update( .After(UpdateVersion, UpdateChangeLog) .Executes(() => { + // Most of the repository derives its version from version.props - see + // version.props and build/cmake/DdVersion.cmake - so a bump only has to touch the + // canonical file and the samples. var expectedFileChanges = new List { - "profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt", - "profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc", - "profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h", - "profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt", - "profiler/src/ProfilerEngine/ProductVersion.props", - "shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt", - "shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc", - "shared/src/msi-installer/WindowsInstaller.wixproj", - "shared/src/native-src/version.h", + "version.props", + "shared/src/native-src/dd_version.h", "tracer/build/artifacts/dd-dotnet.sh", - "tracer/build/_build/Build.cs", "tracer/samples/AutomaticTraceIdInjection/MicrosoftExtensionsExample/MicrosoftExtensionsExample.csproj", "tracer/samples/AutomaticTraceIdInjection/Log4NetExample/Log4NetExample.csproj", "tracer/samples/AutomaticTraceIdInjection/NLog40Example/NLog40Example.csproj", @@ -470,12 +461,6 @@ await client.Issue.Milestone.Update( "tracer/samples/ConsoleApp/Debian.dockerfile", "tracer/samples/OpenTelemetry/Debian.dockerfile", "tracer/samples/WindowsContainer/Dockerfile", - "tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs", - "tracer/src/Datadog.Tracer.Native/CMakeLists.txt", - "tracer/src/Datadog.Tracer.Native/dd_profiler_constants.h", - "tracer/src/Datadog.Tracer.Native/Resource.rc", - "tracer/src/Directory.Build.props", - "tracer/src/Datadog.Trace/TracerConstants.cs", }; if (ExpectChangelogUpdate) @@ -546,7 +531,6 @@ await client.Issue.Milestone.Update( Target UpdateChangeLog => _ => _ .Unlisted() - .Requires(() => Version) .Executes(() => { var releaseNotes = Environment.GetEnvironmentVariable("RELEASE_NOTES"); @@ -587,7 +571,6 @@ await client.Issue.Milestone.Update( .Unlisted() .Requires(() => GitHubRepositoryName) .Requires(() => GitHubToken) - .Requires(() => Version) .Executes(async () => { const string fixes = "Fixes"; @@ -746,7 +729,6 @@ await client.Issue.Milestone.Update( .Unlisted() .Description("Downloads the release artifacts from the specified Azure DevOps BuildId") .DependsOn(CreateRequiredDirectories) - .Requires(() => Version) .Requires(() => AzureDevopsBuildId) .Executes(async () => { @@ -768,7 +750,6 @@ await client.Issue.Milestone.Update( .Description("Downloads the latest artifacts from Azure Devops and Gitlab that has the provided version") .DependsOn(CreateRequiredDirectories) .Requires(() => AzureDevopsToken) - .Requires(() => Version) .Requires(() => TargetBranch) .Executes(async () => { diff --git a/tracer/build/_build/Build.Steps.cs b/tracer/build/_build/Build.Steps.cs index 70c75627ef9d..325286ace4f0 100644 --- a/tracer/build/_build/Build.Steps.cs +++ b/tracer/build/_build/Build.Steps.cs @@ -1238,7 +1238,6 @@ async Task DownloadWafVersion(string libddwafVersion = null, string uncompressFo .After(BuildTracerHome, BuildManagedTracerHome, BuildNativeTracerHome, BuildProfilerHome, BuildNativeLoader) .DependsOn(CopyDdDotnet) .OnlyWhenStatic(() => IsLinux) - .Requires(() => Version) .Executes(() => { var tar = Tar.Value; diff --git a/tracer/build/_build/Build.Utilities.cs b/tracer/build/_build/Build.Utilities.cs index 373c3916401f..9c411cc56d45 100644 --- a/tracer/build/_build/Build.Utilities.cs +++ b/tracer/build/_build/Build.Utilities.cs @@ -640,20 +640,27 @@ static Func BuildCooldownModeSelector(string[] includePack .Description("Update the version number for the tracer") .Before(Clean, BuildTracerHome) .Before(Clean, BuildProfilerHome) - .Requires(() => Version) .Requires(() => NewVersion) .Requires(() => NewIsPrerelease) .Executes(() => { - if (NewVersion == Version && IsPrerelease == NewIsPrerelease) + var source = new SetAllVersions.Source(TracerDirectory, NewVersion, NewIsPrerelease!.Value); + + // The version number has to change: the samples are rewritten from the *pre-bump* + // version (they should track the release on nuget.org, not the one under development). + if (source.TracerVersion == new System.Version(Version)) { - throw new Exception($"Cannot set versions, new version {NewVersion} was the same as {Version} and {IsPrerelease} == {NewIsPrerelease}"); + throw new Exception( + $"Cannot set versions: {NewVersion} is already the current version. Changing only " + + "the prerelease flag is not supported - the version number has to change too."); } - // Samples need to use the latest version (i.e. the _current_ build version, before updating) + // Samples reference the version that is published on nuget.org, which is the one we are + // bumping *away* from, so they lag the source by one release. new SetAllVersions.Samples(TracerDirectory, Version, IsPrerelease).Run(); - // Source needs to use the _actual_ version - new SetAllVersions.Source(TracerDirectory, NewVersion, NewIsPrerelease.Value!).Run(); + + // version.props, which everything else derives from. + source.Run(); }); Target AnalyzePipelineCriticalPath => _ => _ diff --git a/tracer/build/_build/Build.cs b/tracer/build/_build/Build.cs index 1606b4f20679..20523923b8f0 100644 --- a/tracer/build/_build/Build.cs +++ b/tracer/build/_build/Build.cs @@ -64,11 +64,12 @@ partial class Build : NukeBuild [Parameter("The current latest tracer version")] const int LatestMajorVersion = 3; - [Parameter("The current version of the source and build")] - readonly string Version = "3.57.0"; + /// Gets the version being built, read from version.props. Three parts, numeric only. + string Version => ProjectInfo.Version; - [Parameter("Whether the current build version is a prerelease(for packaging purposes)")] - readonly bool IsPrerelease = false; + /// Gets a value indicating whether this version publishes as X.Y.Z-prerelease. + /// Matched the way MSBuild matches it in version.props. + bool IsPrerelease => string.Equals(ProjectInfo.IsPrerelease, "true", StringComparison.OrdinalIgnoreCase); [Parameter("The new build version to set")] readonly string NewVersion; diff --git a/tracer/build/_build/PrepareRelease/SetAllVersions.cs b/tracer/build/_build/PrepareRelease/SetAllVersions.cs index 487b88415122..ed0b4acbf756 100644 --- a/tracer/build/_build/PrepareRelease/SetAllVersions.cs +++ b/tracer/build/_build/PrepareRelease/SetAllVersions.cs @@ -15,7 +15,15 @@ public abstract class SetAllVersions protected SetAllVersions(string tracerDirectory, string tracerVersion, bool isPrerelease) { TracerDirectory = tracerDirectory; + + // new Version() rejects suffixes like -prerelease; the parts check rejects 2- and 4-part versions. + // Validating here means a bad value fails before anything is written. TracerVersion = new Version(tracerVersion); + if (TracerVersion.Build < 0 || TracerVersion.Revision >= 0) + { + throw new ArgumentException($"Version must be a three-part numeric version (e.g. 3.58.0), but was '{tracerVersion}'", nameof(tracerVersion)); + } + IsPrerelease = isPrerelease; } @@ -25,10 +33,8 @@ protected SetAllVersions(string tracerDirectory, string tracerVersion, bool isPr public string TracerDirectory { get; } /// - /// Gets the current tracer version. - /// This is the single source of truth for the current tracer version. - /// When changing the tracer version, update this value and , - /// then run the "PrepareRelease" tool to update the entire solution. + /// Gets the version to write. The source of truth is version.props at the repository root; + /// change it with the UpdateVersion Nuke target rather than editing files by hand. /// public Version TracerVersion { get; } @@ -39,72 +45,16 @@ protected SetAllVersions(string tracerDirectory, string tracerVersion, bool isPr public abstract void Run(); - private string FunctionCallReplace(string text, string functionName) - { - const string split = ", "; - var pattern = @$"{functionName}\({VersionPattern(split, fourPartVersion: true)}\)"; - var replacement = $"{functionName}({FourPartVersionString(split)})"; - - return Regex.Replace(text, pattern, replacement, RegexOptions.Singleline); - } - - private string FourPartVersionReplace(string text) - { - return Regex.Replace(text, VersionPattern(fourPartVersion: true), FourPartVersionString(), RegexOptions.Singleline); - } - - private string ThreePartVersionReplace(string text) - { - return Regex.Replace(text, VersionPattern(), VersionString(), RegexOptions.Singleline); - } - private string FullVersionReplace(string text, string split, string prefix = "") { return Regex.Replace(text, prefix + VersionPattern(split), prefix + VersionString(split), RegexOptions.Singleline); } - private string FullAssemblyNameReplace(string text) - { - return Regex.Replace(text, AssemblyString(VersionPattern()), AssemblyString(VersionString()), RegexOptions.Singleline); - } - - private string DatadogTraceNugetDependencyVersionReplace(string text) - { - return Regex.Replace(text, $"", $"", RegexOptions.Singleline); - } - private string DatadogTraceBundleNugetDependencyVersionReplace(string text) { return Regex.Replace(text, $"", $"", RegexOptions.Singleline); } - private string NugetVersionReplace(string text) - { - return Regex.Replace(text, $"{VersionPattern(withPrereleasePostfix: true)}", $"{VersionString(withPrereleasePostfix: true)}", RegexOptions.Singleline); - } - - private string PropsVersionReplace(string text) - { - return Regex.Replace(text, $"{VersionPattern(withPrereleasePostfix: false)}", $"{VersionString(withPrereleasePostfix: false)}", RegexOptions.Singleline); - } - - private string WixProjReplace(string text) - { - text = Regex.Replace( - text, - $"datadog-dotnet-apm-{VersionPattern(withPrereleasePostfix: true)}-\\$\\(Platform\\)", - $"datadog-dotnet-apm-{VersionString(withPrereleasePostfix: true)}-$(Platform)", - RegexOptions.Singleline); - - text = Regex.Replace( - text, - $"InstallerVersion={VersionPattern()}", - $"InstallerVersion={VersionString()}", - RegexOptions.Singleline); - - return text; - } - private void SynchronizeVersion(string path, Func transform) { var fullPath = Path.Combine(TracerDirectory, path); @@ -119,12 +69,15 @@ private void SynchronizeVersion(string path, Func transform) var fileContent = File.ReadAllText(fullPath); var newFileContent = transform(fileContent); - File.WriteAllText(fullPath, newFileContent, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); - } + if (newFileContent == fileContent) + { + throw new Exception( + $"No version strings were replaced in {path}. Either its format changed and the " + + "pattern in SetAllVersions no longer matches, or the file already holds this " + + "version - check which before changing the pattern."); + } - private string FourPartVersionString(string split = ".") - { - return $"{TracerVersion.Major}{split}{TracerVersion.Minor}{split}{TracerVersion.Build}{split}0"; + File.WriteAllText(fullPath, newFileContent, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); } private string VersionString(string split = ".", bool withPrereleasePostfix = false) @@ -143,7 +96,7 @@ private string VersionString(string split = ".", bool withPrereleasePostfix = fa return newVersion; } - private string VersionPattern(string split = ".", bool withPrereleasePostfix = false, bool fourPartVersion = false) + private string VersionPattern(string split = ".", bool withPrereleasePostfix = false) { if (split == ".") { @@ -152,11 +105,6 @@ private string VersionPattern(string split = ".", bool withPrereleasePostfix = f var pattern = $@"\d+{split}\d+{split}\d+"; - if (fourPartVersion) - { - pattern = pattern + $@"{split}\d+"; - } - if (withPrereleasePostfix) { pattern = pattern + "(\\-prerelease)?"; @@ -165,11 +113,6 @@ private string VersionPattern(string split = ".", bool withPrereleasePostfix = f return pattern; } - private string AssemblyString(string versionText) - { - return $"Datadog.Trace, Version={versionText}.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"; - } - public class Samples : SetAllVersions { public Samples(string tracerDirectory, string tracerVersion, bool isPrerelease) @@ -238,115 +181,37 @@ public override void Run() { Console.WriteLine($"Updating source version instances to {VersionString()}"); - // Pipeline - SynchronizeVersion( - "../.azure-pipelines/ultimate-pipeline.yml", - text => Regex.Replace(text, $"ToolVersion: {VersionPattern(withPrereleasePostfix: true)}", $"ToolVersion: {VersionString(withPrereleasePostfix: true)}")); - - // Nuke build - SynchronizeVersion( - "build/_build/Build.cs", - text => Regex.Replace(text, $"readonly string Version = \"{VersionPattern()}\"", $"readonly string Version = \"{VersionString()}\"")); - + // The only copy of the version. Managed projects import it directly, native projects + // through build/DdVersion.props, and CMake reads it in build/cmake/DdVersion.cmake. + // Always changes, because UpdateVersion rejects a bump that does not change the + // version number. SynchronizeVersion( - "build/_build/Build.cs", - text => Regex.Replace(text, "readonly bool IsPrerelease = (true|false)", $"readonly bool IsPrerelease = {(IsPrerelease ? "true" : "false")}")); - - SynchronizeVersion( - "src/Directory.Build.props", - NugetVersionReplace); - - // Fully qualified name updates - SynchronizeVersion( - "src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs", - FullAssemblyNameReplace); - - SynchronizeVersion( - "src/Datadog.Tracer.Native/dd_profiler_constants.h", - FullAssemblyNameReplace); - - SynchronizeVersion( - "src/Datadog.Tracer.Native/dd_profiler_constants.h", - text => FunctionCallReplace(text, "WithVersion")); - - // Four-part AssemblyVersion update - SynchronizeVersion( - "src/Datadog.Trace/TracerConstants.cs", - // upgrading four part, then three part *seems* safe - text => ThreePartVersionReplace(FourPartVersionReplace(text))); - - // Native clr profiler updates - SynchronizeVersion( - "src/Datadog.Tracer.Native/CMakeLists.txt", - text => FullVersionReplace(text, ".", prefix: "\"Datadog.Tracer.Native\" VERSION ")); - - SynchronizeVersion( - "src/Datadog.Tracer.Native/Resource.rc", + "../version.props", text => { - text = FullVersionReplace(text, ","); - text = FullVersionReplace(text, "."); - return text; + text = ReplaceElement(text, "DD_VersionPrefix", VersionString()); + return ReplaceElement(text, "DD_IsPrerelease", IsPrerelease ? "true" : "false"); }); - // .NET profiler - + // A shell script that ships inside the tracer home, so it cannot read anything else. SynchronizeVersion( - "../profiler/src/ProfilerEngine/Datadog.Profiler.Native.Windows/Resource.rc", - text => - { - text = FullVersionReplace(text, ","); - text = FullVersionReplace(text, "."); - return text; - }); - - SynchronizeVersion( - "../profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt", - text => FullVersionReplace(text, ".", prefix: "\"Datadog.Profiler.Native.Linux\" VERSION ")); - - SynchronizeVersion( - "../profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt", - text => FullVersionReplace(text, ".", prefix: "\"Datadog.Linux.ApiWrapper\" VERSION ")); - - SynchronizeVersion( - "../profiler/src/ProfilerEngine/Datadog.Profiler.Native/dd_profiler_version.h", - text => FullVersionReplace(text, ".")); - - // Native loader - - SynchronizeVersion( - "../shared/src/Datadog.Trace.ClrProfiler.Native/Resource.rc", - text => - { - text = FullVersionReplace(text, ","); - text = FullVersionReplace(text, "."); - return text; - }); - - SynchronizeVersion( - "../shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt", - text => FullVersionReplace(text, ".", prefix: "\"Datadog.Trace.ClrProfiler.Native\" VERSION ")); - - SynchronizeVersion( - "../shared/src/native-src/version.h", - text => FullVersionReplace(text, ".")); - - // Misc - - SynchronizeVersion( - "../profiler/src/ProfilerEngine/ProductVersion.props", - PropsVersionReplace); - - SynchronizeVersion("build/artifacts/dd-dotnet.sh", + "build/artifacts/dd-dotnet.sh", text => FullVersionReplace(text, ".")); - // Deployment updates - SynchronizeVersion( - "../shared/src/msi-installer/WindowsInstaller.wixproj", - WixProjReplace); - Console.WriteLine($"Completed synchronizing source versions to {VersionString()}"); } + + private static string ReplaceElement(string text, string element, string value) + { + // version.props documents that each element appears exactly once, and is never mentioned in comments + var pattern = $"<{element}>[^<]*"; + if (!Regex.IsMatch(text, pattern)) + { + throw new Exception($"Could not find <{element}> in version.props"); + } + + return Regex.Replace(text, pattern, $"<{element}>{value}"); + } } } } diff --git a/tracer/build/_build/_build.csproj b/tracer/build/_build/_build.csproj index 5829cd60f705..bbae4f18abc3 100644 --- a/tracer/build/_build/_build.csproj +++ b/tracer/build/_build/_build.csproj @@ -1,5 +1,8 @@  + + + Exe net11.0 @@ -65,6 +68,15 @@ + + + + + + + + diff --git a/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj b/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj index 5c75868c1d78..811bfe39b21b 100644 --- a/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj +++ b/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj @@ -13,4 +13,9 @@ false - \ No newline at end of file + + + + + + diff --git a/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs b/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs index e0d5242c703f..e41c7470a852 100644 --- a/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs +++ b/tracer/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs @@ -17,9 +17,9 @@ namespace Datadog.Trace.ClrProfiler.Managed.Loader /// public sealed partial class Startup { - // internal so ManagedProfilerAssemblyResolver can reference it. Safe because const strings are inlined at compile time. + // internal so ManagedProfilerAssemblyResolver can reference it, and const so it stays inlined. // Do not add non-const static members on Startup that the resolver needs - that would re-introduce the .cctor deadlock. - internal const string AssemblyName = "Datadog.Trace, Version=3.57.0.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"; + internal const string AssemblyName = "Datadog.Trace, Version=" + ProjectInfo.AssemblyVersion + ", Culture=neutral, PublicKeyToken=def86d061d0d2eeb"; private const string AzureAppServicesSiteExtensionKey = "DD_AZURE_APP_SERVICES"; // only set when using the AAS site extension private const string TracerHomePathKey = "DD_DOTNET_TRACER_HOME"; diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CreatedumpCommand.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CreatedumpCommand.cs index a29e3cc4a07a..f0cd44a0fabd 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CreatedumpCommand.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CreatedumpCommand.cs @@ -1081,7 +1081,7 @@ private unsafe bool SetMetadata(ICrashReport crashReport, ClrRuntime runtime, Cl } } - var tags = new (string Key, string Value)[] { ("language", "dotnet"), ("runtime_version", $"{flavor} {version}"), ("library_version", TracerConstants.AssemblyVersion) }; + var tags = new (string Key, string Value)[] { ("language", "dotnet"), ("runtime_version", $"{flavor} {version}"), ("library_version", ProjectInfo.AssemblyVersion) }; if (exception != null) { @@ -1100,7 +1100,7 @@ private unsafe bool SetMetadata(ICrashReport crashReport, ClrRuntime runtime, Cl var libraryName = Marshal.StringToHGlobalAnsi("dd-dotnet"); bag.Add(libraryName); - var libraryVersion = Marshal.StringToHGlobalAnsi(TracerConstants.AssemblyVersion); + var libraryVersion = Marshal.StringToHGlobalAnsi(ProjectInfo.AssemblyVersion); bag.Add(libraryVersion); var family = Marshal.StringToHGlobalAnsi("dotnet"); diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj index 18a3d4e976f9..1bb2bf1c9dfa 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj @@ -54,7 +54,6 @@ - @@ -77,6 +76,8 @@ + + diff --git a/tracer/src/Datadog.Trace/Datadog.Trace.csproj b/tracer/src/Datadog.Trace/Datadog.Trace.csproj index c252944976e1..c26429ac3b87 100644 --- a/tracer/src/Datadog.Trace/Datadog.Trace.csproj +++ b/tracer/src/Datadog.Trace/Datadog.Trace.csproj @@ -84,6 +84,12 @@ + + + + + + diff --git a/tracer/src/Datadog.Trace/TracerConstants.cs b/tracer/src/Datadog.Trace/TracerConstants.cs index 6dcbdf258ced..96da3aba9da7 100644 --- a/tracer/src/Datadog.Trace/TracerConstants.cs +++ b/tracer/src/Datadog.Trace/TracerConstants.cs @@ -11,9 +11,13 @@ internal static class TracerConstants { public const string TelemetrySdkName = "datadog"; public const string Language = "dotnet"; - public const string AssemblyVersion = "3.57.0.0"; - public const string ThreePartVersion = "3.57.0"; - public static ReadOnlySpan AssemblyVersionBytes => "3.57.0.0"u8; + public const string AssemblyVersion = ProjectInfo.AssemblyVersion; + + // Instrumentation.cs compares this against the native tracer's PROFILER_VERSION for an exact + // string match, so it must stay a bare numeric three-part version. + public const string ThreePartVersion = ProjectInfo.ThreePartVersion; + + public static ReadOnlySpan AssemblyVersionBytes => ProjectInfo.AssemblyVersionBytes; } } diff --git a/tracer/src/Datadog.Tracer.Native/CMakeLists.txt b/tracer/src/Datadog.Tracer.Native/CMakeLists.txt index bf07e13cf2de..81bb915bd44c 100644 --- a/tracer/src/Datadog.Tracer.Native/CMakeLists.txt +++ b/tracer/src/Datadog.Tracer.Native/CMakeLists.txt @@ -12,7 +12,8 @@ endif() # Project definition # ****************************************************** -project("Datadog.Tracer.Native" VERSION 3.57.0) +include("${CMAKE_CURRENT_LIST_DIR}/../../../build/cmake/DdVersion.cmake") +project("Datadog.Tracer.Native" VERSION ${DD_VERSION}) # ****************************************************** # Environment detection diff --git a/tracer/src/Datadog.Tracer.Native/Directory.Build.props b/tracer/src/Datadog.Tracer.Native/Directory.Build.props index 8c119d5413b5..48b5a10540c0 100644 --- a/tracer/src/Datadog.Tracer.Native/Directory.Build.props +++ b/tracer/src/Datadog.Tracer.Native/Directory.Build.props @@ -1,2 +1,3 @@ + diff --git a/tracer/src/Datadog.Tracer.Native/Resource.rc b/tracer/src/Datadog.Tracer.Native/Resource.rc index 356926b5e849..60f2f664bea0 100644 --- a/tracer/src/Datadog.Tracer.Native/Resource.rc +++ b/tracer/src/Datadog.Tracer.Native/Resource.rc @@ -49,9 +49,11 @@ END // Version // +#include "../../../shared/src/native-src/dd_version.h" + VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,57,0,0 - PRODUCTVERSION 3,57,0,0 + FILEVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION + PRODUCTVERSION DD_VERSION_MAJOR,DD_VERSION_MINOR,DD_VERSION_PATCH,DD_VERSION_REVISION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -68,12 +70,12 @@ BEGIN BEGIN VALUE "CompanyName", "Datadog, Inc." VALUE "FileDescription", "Datadog CLR Profiler" - VALUE "FileVersion", "3.57.0.0" + VALUE "FileVersion", DD_FOUR_PART_VERSION_STR VALUE "InternalName", "Datadog.Tracer.Native.DLL" VALUE "LegalCopyright", "Copyright 2017 Datadog, Inc." VALUE "OriginalFilename", "Datadog.Tracer.Native.DLL" VALUE "ProductName", "Datadog .NET Tracer" - VALUE "ProductVersion", "3.57.0" + VALUE "ProductVersion", DD_THREE_PART_VERSION_STR END END BLOCK "VarFileInfo" diff --git a/tracer/src/Datadog.Tracer.Native/dd_profiler_constants.h b/tracer/src/Datadog.Tracer.Native/dd_profiler_constants.h index 3862796b2194..967581beb006 100644 --- a/tracer/src/Datadog.Tracer.Native/dd_profiler_constants.h +++ b/tracer/src/Datadog.Tracer.Native/dd_profiler_constants.h @@ -3,6 +3,7 @@ #include +#include "../../../shared/src/native-src/version.h" #include "environment_variables.h" #include "logger.h" @@ -80,7 +81,7 @@ const shared::WSTRING system_private_corelib_assemblyName = WStr("System.Private const shared::WSTRING datadog_trace_clrprofiler_managed_loader_assemblyName = WStr("Datadog.Trace.ClrProfiler.Managed.Loader"); const shared::WSTRING managed_profiler_full_assembly_version = - WStr("Datadog.Trace, Version=3.57.0.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"); + WStr("Datadog.Trace, Version=") DD_FOUR_PART_VERSION_STR ", Culture=neutral, PublicKeyToken=def86d061d0d2eeb"; const shared::WSTRING managed_profiler_name = WStr("Datadog.Trace"); const shared::WSTRING manual_instrumentation_name = WStr("Datadog.Trace.Manual"); @@ -140,7 +141,7 @@ const AssemblyProperty managed_profiler_assembly_property = AssemblyProperty( 49, 105, 236, 40, 21, 176, 12, 238, 238, 204, 141, 90, 27, 244, 61, 182, 125, 41, 97, 163, 233, 190, 161, 57, 127, 4, 62, 192, 116, 145, 112, 150, 73, 37, 47, 85, 101, 183, 86, 197}, 160, 32772, 1) - .WithVersion(3, 57, 0, 0); + .WithVersion(DD_VERSION_MAJOR, DD_VERSION_MINOR, DD_VERSION_PATCH, DD_VERSION_REVISION); } // namespace trace diff --git a/tracer/src/Directory.Build.props b/tracer/src/Directory.Build.props index 4d54feaaac21..664edda2dfd5 100644 --- a/tracer/src/Directory.Build.props +++ b/tracer/src/Directory.Build.props @@ -4,7 +4,7 @@ net461;netstandard2.0;netcoreapp3.1;net6.0 true - 3.57.0 + $(DD_SemVer) latest diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs index 3af9aee915f5..5a3a700c3ab7 100644 --- a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs @@ -97,7 +97,7 @@ public async Task VersionConflict1X() console.Output.Should().Contain(VersionConflict); - console.Output.Should().Contain(MultipleTracers(new[] { "1.29.0.0", TracerConstants.AssemblyVersion })); + console.Output.Should().Contain(MultipleTracers(["1.29.0.0", ProjectInfo.AssemblyVersion])); } [SkippableFact] @@ -208,12 +208,12 @@ public async Task Working() result.Should().BeTrue(); console.Output.Should().Contain( - TracerVersion(TracerConstants.AssemblyVersion), + TracerVersion(ProjectInfo.AssemblyVersion), ContinuousProfilerNotSet); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - console.Output.Should().Contain(ProfilerVersion(TracerConstants.AssemblyVersion)); + console.Output.Should().Contain(ProfilerVersion(ProjectInfo.AssemblyVersion)); } console.Output.Should().NotContainAny( @@ -266,7 +266,7 @@ public async Task WorkingWithContinuousProfiler() result.Should().BeTrue(); console.Output.Should().ContainAll( - TracerVersion(TracerConstants.AssemblyVersion), + TracerVersion(ProjectInfo.AssemblyVersion), ContinuousProfilerEnabled, CorrectlySetupEnvironment(CorProfilerKey, Utils.Profilerid), CorrectlySetupEnvironment(CorEnableKey, "1"), diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Datadog.Trace.Tools.dd_dotnet.IntegrationTests.csproj b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Datadog.Trace.Tools.dd_dotnet.IntegrationTests.csproj index 8c0e28f44f36..50513dd3aff3 100644 --- a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Datadog.Trace.Tools.dd_dotnet.IntegrationTests.csproj +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Datadog.Trace.Tools.dd_dotnet.IntegrationTests.csproj @@ -1,27 +1,24 @@  - net10.0;net11.0 SA1300;NU1901;NU1902;NU1903;NU1904 enable - - PreserveNewest - + + - @@ -29,14 +26,8 @@ - - - - - - diff --git a/tracer/test/Datadog.Tracer.Native.Tests/Directory.Build.props b/tracer/test/Datadog.Tracer.Native.Tests/Directory.Build.props index 8c119d5413b5..48b5a10540c0 100644 --- a/tracer/test/Datadog.Tracer.Native.Tests/Directory.Build.props +++ b/tracer/test/Datadog.Tracer.Native.Tests/Directory.Build.props @@ -1,2 +1,3 @@ + diff --git a/tracer/test/test-applications/regression/MismatchedTracerVersions/Build-Tracer.ps1 b/tracer/test/test-applications/regression/MismatchedTracerVersions/Build-Tracer.ps1 index f6e32317b351..96e663fcdca2 100644 --- a/tracer/test/test-applications/regression/MismatchedTracerVersions/Build-Tracer.ps1 +++ b/tracer/test/test-applications/regression/MismatchedTracerVersions/Build-Tracer.ps1 @@ -30,7 +30,7 @@ foreach ($TracerVersion in $TracerVersions) { & "$SolutionDirectory/build.ps1" UpdateVersion -NewVersion $TracerVersion -NewIsPrerelease $false -NoLogo -Verbosity minimal Write-Host "Building tracer ${TracerVersion} into ${TracerHomeDirectory}" - & "$SolutionDirectory/build.ps1" Clean BuildTracerHome PackageTracerHome -Version $TracerVersion -TracerHome $TracerHomeDirectory -NoLogo -Verbosity minimal + & "$SolutionDirectory/build.ps1" Clean BuildTracerHome PackageTracerHome -TracerHome $TracerHomeDirectory -NoLogo -Verbosity minimal if ($IsWindows) { Write-Host "Copying `$SolutionDirectory/bin/artifacts/nuget/Datadog.Trace.${TracerVersion}.nupkg to ${DestinationDirectory}" diff --git a/tracer/tools/Build-AzureFunctionsNuget.ps1 b/tracer/tools/Build-AzureFunctionsNuget.ps1 index df4e194bf1b8..28f5a7b1910d 100644 --- a/tracer/tools/Build-AzureFunctionsNuget.ps1 +++ b/tracer/tools/Build-AzureFunctionsNuget.ps1 @@ -23,7 +23,7 @@ .PARAMETER Version Optional explicit package version. If not provided, a unique prerelease version is - generated from the base version in Directory.Build.props with a timestamp suffix + generated from the base version in version.props with a timestamp suffix (e.g. 3.38.0-dev20260209143022). .EXAMPLE @@ -83,10 +83,10 @@ Write-Verbose "Tracer directory: $tracerDir" # Generate package version if (-not $Version) { - # Read the base version from Directory.Build.props - $propsPath = "$tracerDir/src/Directory.Build.props" + # Read the base version from version.props + $propsPath = "$(Split-Path -Parent $tracerDir)/version.props" [xml]$propsXml = Get-Content $propsPath - $baseVersion = $propsXml.Project.PropertyGroup.Version + $baseVersion = $propsXml.Project.PropertyGroup.DD_VersionPrefix | Where-Object { $_ } | Select-Object -First 1 if (-not $baseVersion) { throw "Could not read Version from $propsPath" diff --git a/version.props b/version.props new file mode 100644 index 000000000000..4522496e6ee4 --- /dev/null +++ b/version.props @@ -0,0 +1,31 @@ + + + + + + 3.57.0 + + + false + + + + $(DD_VersionPrefix) + $(DD_VersionPrefix)-prerelease + + + $(DD_VersionPrefix).0 + + + From 0854618b989b310f3a2f80e7b309efe3a6685b1d Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Wed, 21 Oct 2026 18:28:35 +0100 Subject: [PATCH 3/6] Substitute the version into dd-dotnet.sh when it is copied dd-dotnet.sh ships inside the tracer home and so cannot read the version from anywhere else, but it only needs it to name the package the user should have downloaded, in an error message. It now carries a placeholder filled in at the two points where the script is copied into a tracer home, rather than being rewritten in place by the version-bump tooling. --- tracer/build/_build/Build.GitHub.cs | 2 -- tracer/build/_build/Build.Steps.cs | 31 ++++++++++++++++--- .../_build/PrepareRelease/SetAllVersions.cs | 10 ------ tracer/build/artifacts/dd-dotnet.sh | 5 ++- 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/tracer/build/_build/Build.GitHub.cs b/tracer/build/_build/Build.GitHub.cs index c1a5ebbbd39b..8e579769de88 100644 --- a/tracer/build/_build/Build.GitHub.cs +++ b/tracer/build/_build/Build.GitHub.cs @@ -448,8 +448,6 @@ await client.Issue.Milestone.Update( var expectedFileChanges = new List { "version.props", - "shared/src/native-src/dd_version.h", - "tracer/build/artifacts/dd-dotnet.sh", "tracer/samples/AutomaticTraceIdInjection/MicrosoftExtensionsExample/MicrosoftExtensionsExample.csproj", "tracer/samples/AutomaticTraceIdInjection/Log4NetExample/Log4NetExample.csproj", "tracer/samples/AutomaticTraceIdInjection/NLog40Example/NLog40Example.csproj", diff --git a/tracer/build/_build/Build.Steps.cs b/tracer/build/_build/Build.Steps.cs index 325286ace4f0..644722b10855 100644 --- a/tracer/build/_build/Build.Steps.cs +++ b/tracer/build/_build/Build.Steps.cs @@ -1136,9 +1136,26 @@ async Task DownloadWafVersion(string libddwafVersion = null, string uncompressFo // Add the dd-dotnet scripts CopyFileToDirectory(BuildDirectory / "artifacts" / "dd-dotnet.cmd", BundleHomeDirectory, FileExistsPolicy.Overwrite); - CopyFileToDirectory(BuildDirectory / "artifacts" / "dd-dotnet.sh", BundleHomeDirectory, FileExistsPolicy.Overwrite); + CopyDdDotnetScript(BundleHomeDirectory); }); + private void CopyDdDotnetScript(AbsolutePath destination) + { + const string placeholder = "@DD_VERSION@"; + + // Copy first and rewrite in place, so the destination directory and executable bit are handled for us + CopyFileToDirectory(BuildDirectory / "artifacts" / "dd-dotnet.sh", destination, FileExistsPolicy.Overwrite); + var script = destination / "dd-dotnet.sh"; + var original = File.ReadAllText(script); + if (!original.Contains(placeholder)) + { + throw new InvalidOperationException($"Expected to find the {placeholder} placeholder in {script}"); + } + + // Always LF: this is a shell script that ships to Linux. + File.WriteAllText(script, original.Replace(placeholder, Version).Replace("\r\n", "\n")); + } + Target CreateBenchmarkIntegrationHome => _ => _ .Unlisted() .After(BuildTracerHome) @@ -1198,12 +1215,18 @@ async Task DownloadWafVersion(string libddwafVersion = null, string uncompressFo .After(BuildDdDotnet) .Executes(() => { - var script = IsWin ? "dd-dotnet.cmd" : "dd-dotnet.sh"; - CopyFileToDirectory(BuildDirectory / "artifacts" / script, MonitoringHomeDirectory, FileExistsPolicy.Overwrite); + if (IsWin) + { + CopyFileToDirectory(BuildDirectory / "artifacts" / "dd-dotnet.cmd", MonitoringHomeDirectory, FileExistsPolicy.Overwrite); + } + else + { + CopyDdDotnetScript(MonitoringHomeDirectory); + } if (IsLinux) { - Chmod.Value.Invoke("+x " + MonitoringHomeDirectory / script); + Chmod.Value.Invoke("+x " + MonitoringHomeDirectory / "dd-dotnet.sh"); } }); diff --git a/tracer/build/_build/PrepareRelease/SetAllVersions.cs b/tracer/build/_build/PrepareRelease/SetAllVersions.cs index ed0b4acbf756..6392db3e160d 100644 --- a/tracer/build/_build/PrepareRelease/SetAllVersions.cs +++ b/tracer/build/_build/PrepareRelease/SetAllVersions.cs @@ -45,11 +45,6 @@ protected SetAllVersions(string tracerDirectory, string tracerVersion, bool isPr public abstract void Run(); - private string FullVersionReplace(string text, string split, string prefix = "") - { - return Regex.Replace(text, prefix + VersionPattern(split), prefix + VersionString(split), RegexOptions.Singleline); - } - private string DatadogTraceBundleNugetDependencyVersionReplace(string text) { return Regex.Replace(text, $"", $"", RegexOptions.Singleline); @@ -193,11 +188,6 @@ public override void Run() return ReplaceElement(text, "DD_IsPrerelease", IsPrerelease ? "true" : "false"); }); - // A shell script that ships inside the tracer home, so it cannot read anything else. - SynchronizeVersion( - "build/artifacts/dd-dotnet.sh", - text => FullVersionReplace(text, ".")); - Console.WriteLine($"Completed synchronizing source versions to {VersionString()}"); } diff --git a/tracer/build/artifacts/dd-dotnet.sh b/tracer/build/artifacts/dd-dotnet.sh index 2e42b4416910..243ae500c50f 100755 --- a/tracer/build/artifacts/dd-dotnet.sh +++ b/tracer/build/artifacts/dd-dotnet.sh @@ -1,6 +1,9 @@ #!/bin/sh -TRACER_VERSION="3.57.0" +# Substituted when this script is copied into the tracer home - see CopyDdDotnetScript in +# tracer/build/_build/Build.Steps.cs. Only used to name the package the user should have +# downloaded, in an error message. +TRACER_VERSION="@DD_VERSION@" # Get the directory of the script DIR=$(dirname "$(readlink -f "$0")") From 92e1f61b7537db6b41707614207f8c7469ea2b63 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Mon, 26 Oct 2026 15:42:16 +0000 Subject: [PATCH 4/6] Move to build folder to fix --- build/DdVersion.props | 11 +++++------ build/cmake/DdVersion.cmake | 11 ++++++----- profiler/Directory.Build.props | 2 +- profiler/src/ProfilerEngine/ProductVersion.props | 2 +- shared/Directory.Build.props | 2 +- tracer/Directory.Build.props | 2 +- tracer/build/_build/Build.GitHub.cs | 2 +- tracer/build/_build/PrepareRelease/SetAllVersions.cs | 4 ++-- tracer/build/_build/_build.csproj | 2 +- version.props => tracer/build/_build/version.props | 3 +++ tracer/tools/Build-AzureFunctionsNuget.ps1 | 2 +- 11 files changed, 23 insertions(+), 20 deletions(-) rename version.props => tracer/build/_build/version.props (88%) diff --git a/build/DdVersion.props b/build/DdVersion.props index eadfd0b8ba7c..76f3ed8837b5 100644 --- a/build/DdVersion.props +++ b/build/DdVersion.props @@ -4,14 +4,13 @@ The SDK version for native (.vcxproj) projects: they import this file instead of version.props, which managed projects import directly. It is the MSBuild equivalent of build/cmake/DdVersion.cmake. - As well as the properties from /version.props, it adds the DD_VERSION_* preprocessor - definitions that shared/src/native-src/dd_version.h expects - the same set that DdVersion.cmake - defines. The *_PART_VERSION values are deliberately bare tokens (1.2.3, not "1.2.3"): - ResourceCompile passes quoted values to rc.exe as empty strings, and escaping the quotes breaks - cl.exe instead. + As well as the properties from tracer/build/_build/version.props, it adds the DD_VERSION_MAJOR, + DD_VERSION_MINOR and DD_VERSION_PATCH preprocessor definitions that shared/src/native-src/dd_version.h + expects - the same set that DdVersion.cmake defines. dd_version.h derives everything else from them, + so new derived values belong there, not here. --> - + DD_VERSION_MAJOR=$([System.Version]::Parse('$(DD_VersionPrefix)').Major);DD_VERSION_MINOR=$([System.Version]::Parse('$(DD_VersionPrefix)').Minor);DD_VERSION_PATCH=$([System.Version]::Parse('$(DD_VersionPrefix)').Build) diff --git a/build/cmake/DdVersion.cmake b/build/cmake/DdVersion.cmake index 8849941d5d77..60670ec5af88 100644 --- a/build/cmake/DdVersion.cmake +++ b/build/cmake/DdVersion.cmake @@ -1,7 +1,8 @@ -# Exposes the version from /version.props as DD_VERSION, for project(... VERSION ...), -# which accepts only a numeric major[.minor[.patch[.tweak]]]. Also adds the DD_VERSION_* compile -# definitions that shared/src/native-src/dd_version.h expects (build/DdVersion.props defines the same set -# for the MSBuild builds). +# Exposes the version from tracer/build/_build/version.props as DD_VERSION, for project(... VERSION ...), +# which accepts only a numeric major[.minor[.patch[.tweak]]]. Also adds the DD_VERSION_MAJOR, +# DD_VERSION_MINOR and DD_VERSION_PATCH compile definitions that shared/src/native-src/dd_version.h +# expects (build/DdVersion.props defines the same set for the MSBuild builds). dd_version.h derives +# everything else from them, so new derived values belong there, not here. # # Deliberately re-read on every include and stored as a normal (not cached) variable, so that a # version bump is picked up by an existing build directory, and you don't get weird instrumentation @@ -9,7 +10,7 @@ get_filename_component(DD_REPO_ROOT "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) -set(DD_VERSION_PROPS "${DD_REPO_ROOT}/version.props") +set(DD_VERSION_PROPS "${DD_REPO_ROOT}/tracer/build/_build/version.props") if(NOT EXISTS "${DD_VERSION_PROPS}") message(FATAL_ERROR "Could not find ${DD_VERSION_PROPS}. This file holds the SDK version number.") endif() diff --git a/profiler/Directory.Build.props b/profiler/Directory.Build.props index 827543fcb94b..540a3fb218a6 100644 --- a/profiler/Directory.Build.props +++ b/profiler/Directory.Build.props @@ -9,7 +9,7 @@ - + diff --git a/profiler/src/ProfilerEngine/ProductVersion.props b/profiler/src/ProfilerEngine/ProductVersion.props index 49f894b8638c..f5e24e27728b 100644 --- a/profiler/src/ProfilerEngine/ProductVersion.props +++ b/profiler/src/ProfilerEngine/ProductVersion.props @@ -3,7 +3,7 @@ - + $(DD_VersionPrefix) diff --git a/shared/Directory.Build.props b/shared/Directory.Build.props index 5f2c590c7f62..1142c4269c8d 100644 --- a/shared/Directory.Build.props +++ b/shared/Directory.Build.props @@ -14,6 +14,6 @@ - + \ No newline at end of file diff --git a/tracer/Directory.Build.props b/tracer/Directory.Build.props index 0062fcc7f8fe..bcb44aecd10b 100644 --- a/tracer/Directory.Build.props +++ b/tracer/Directory.Build.props @@ -1,5 +1,5 @@ - + false diff --git a/tracer/build/_build/Build.GitHub.cs b/tracer/build/_build/Build.GitHub.cs index 8e579769de88..03156ef458f5 100644 --- a/tracer/build/_build/Build.GitHub.cs +++ b/tracer/build/_build/Build.GitHub.cs @@ -447,7 +447,7 @@ await client.Issue.Milestone.Update( // canonical file and the samples. var expectedFileChanges = new List { - "version.props", + "tracer/build/_build/version.props", "tracer/samples/AutomaticTraceIdInjection/MicrosoftExtensionsExample/MicrosoftExtensionsExample.csproj", "tracer/samples/AutomaticTraceIdInjection/Log4NetExample/Log4NetExample.csproj", "tracer/samples/AutomaticTraceIdInjection/NLog40Example/NLog40Example.csproj", diff --git a/tracer/build/_build/PrepareRelease/SetAllVersions.cs b/tracer/build/_build/PrepareRelease/SetAllVersions.cs index 6392db3e160d..82d69d3e9783 100644 --- a/tracer/build/_build/PrepareRelease/SetAllVersions.cs +++ b/tracer/build/_build/PrepareRelease/SetAllVersions.cs @@ -33,7 +33,7 @@ protected SetAllVersions(string tracerDirectory, string tracerVersion, bool isPr public string TracerDirectory { get; } /// - /// Gets the version to write. The source of truth is version.props at the repository root; + /// Gets the version to write. The source of truth is tracer/build/_build/version.props; /// change it with the UpdateVersion Nuke target rather than editing files by hand. /// public Version TracerVersion { get; } @@ -181,7 +181,7 @@ public override void Run() // Always changes, because UpdateVersion rejects a bump that does not change the // version number. SynchronizeVersion( - "../version.props", + "build/_build/version.props", text => { text = ReplaceElement(text, "DD_VersionPrefix", VersionString()); diff --git a/tracer/build/_build/_build.csproj b/tracer/build/_build/_build.csproj index bbae4f18abc3..cb41e3b82e83 100644 --- a/tracer/build/_build/_build.csproj +++ b/tracer/build/_build/_build.csproj @@ -1,7 +1,7 @@  - + Exe diff --git a/version.props b/tracer/build/_build/version.props similarity index 88% rename from version.props rename to tracer/build/_build/version.props index 4522496e6ee4..400297c6f2f0 100644 --- a/version.props +++ b/tracer/build/_build/version.props @@ -5,6 +5,9 @@ Always run the UpdateVersion Nuke target to change it; do not edit by hand. Native (.vcxproj) projects import build/DdVersion.props instead, which imports this file. + It lives next to _build.csproj, rather than at the repository root, because the Linux build + images compile Nuke using only this directory as the Docker build context, and Nuke needs it. + Keep exactly one DD_VersionPrefix element in this file, and never write its opening and closing tags anywhere else - not even in a comment. build/cmake/DdVersion.cmake and the UpdateVersion target both locate the version by matching those tags textually, and UpdateVersion rewrites diff --git a/tracer/tools/Build-AzureFunctionsNuget.ps1 b/tracer/tools/Build-AzureFunctionsNuget.ps1 index 28f5a7b1910d..34b6e1122995 100644 --- a/tracer/tools/Build-AzureFunctionsNuget.ps1 +++ b/tracer/tools/Build-AzureFunctionsNuget.ps1 @@ -84,7 +84,7 @@ Write-Verbose "Tracer directory: $tracerDir" if (-not $Version) { # Read the base version from version.props - $propsPath = "$(Split-Path -Parent $tracerDir)/version.props" + $propsPath = "$tracerDir/build/_build/version.props" [xml]$propsXml = Get-Content $propsPath $baseVersion = $propsXml.Project.PropertyGroup.DD_VersionPrefix | Where-Object { $_ } | Select-Object -First 1 if (-not $baseVersion) From 6bc8fd1726de9019ba85ebebe21aaf059c9611aa Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Tue, 27 Oct 2026 08:19:28 +0000 Subject: [PATCH 5/6] Pass the DD_VERSION_* definitions to CppCheck on Windows --- tracer/build/_build/Build.Profiler.Steps.cs | 2 +- tracer/build/_build/Build.Shared.Steps.cs | 4 ++-- tracer/build/_build/Build.Steps.cs | 4 ++-- tracer/build/_build/Build.cs | 9 +++++++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tracer/build/_build/Build.Profiler.Steps.cs b/tracer/build/_build/Build.Profiler.Steps.cs index 65c23f4460fc..dcc44cda3fc9 100644 --- a/tracer/build/_build/Build.Profiler.Steps.cs +++ b/tracer/build/_build/Build.Profiler.Steps.cs @@ -453,7 +453,7 @@ void RunCppCheck(string projectName, MSBuildTargetPlatform platform) { var project = ProfilerSolution.GetProject(projectName); var cppCheckResultFile = ProfilerBuildDataDirectory / $"{project.Name}-cppcheck-{platform}"; - CppCheck.Value($"--inline-suppr --enable=all --project={project.Path} --xml --output-file={cppCheckResultFile}.xml --suppressions-list={ProfilerDirectory}/cppcheck-suppressions.txt "); + CppCheck.Value($"--inline-suppr --enable=all --project={project.Path} {CppCheckVersionDefines} --xml --output-file={cppCheckResultFile}.xml --suppressions-list={ProfilerDirectory}/cppcheck-suppressions.txt "); } foreach (var platform in new[] { MSBuildTargetPlatform.x64, MSBuildTargetPlatform.x86 }) diff --git a/tracer/build/_build/Build.Shared.Steps.cs b/tracer/build/_build/Build.Shared.Steps.cs index 582b78bb3177..90f1cdafe0e2 100644 --- a/tracer/build/_build/Build.Shared.Steps.cs +++ b/tracer/build/_build/Build.Shared.Steps.cs @@ -221,8 +221,8 @@ partial class Build .Executes(() => { var (arch, ext) = GetUnixArchitectureAndExtension(); - CppCheck.Value(arguments: $"--inconclusive --project={NativeLoaderProject.Path} --output-file={BuildDataDirectory}/{NativeLoaderProject.Name}-cppcheck-{arch}.xml --xml --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); - CppCheck.Value(arguments: $"--inconclusive --project={NativeLoaderProject.Path} --output-file={BuildDataDirectory}/{NativeLoaderProject.Name}-cppcheck-{arch}.txt --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); + CppCheck.Value(arguments: $"--inconclusive --project={NativeLoaderProject.Path} {CppCheckVersionDefines} --output-file={BuildDataDirectory}/{NativeLoaderProject.Name}-cppcheck-{arch}.xml --xml --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); + CppCheck.Value(arguments: $"--inconclusive --project={NativeLoaderProject.Path} {CppCheckVersionDefines} --output-file={BuildDataDirectory}/{NativeLoaderProject.Name}-cppcheck-{arch}.txt --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); }); Target PublishNativeLoader => _ => _ diff --git a/tracer/build/_build/Build.Steps.cs b/tracer/build/_build/Build.Steps.cs index 644722b10855..82c13bf66583 100644 --- a/tracer/build/_build/Build.Steps.cs +++ b/tracer/build/_build/Build.Steps.cs @@ -503,8 +503,8 @@ private void VerifyOtelThreadContextSymbolIsExported() .Executes(() => { var (arch, ext) = GetUnixArchitectureAndExtension(); - CppCheck.Value(arguments: $"--inconclusive --project={NativeTracerProject.Path} --output-file={BuildDataDirectory}/{NativeTracerProject.Name}-cppcheck-{arch}.xml --xml --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); - CppCheck.Value(arguments: $"--inconclusive --project={NativeTracerProject.Path} --output-file={BuildDataDirectory}/{NativeTracerProject.Name}-cppcheck-{arch}.txt --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); + CppCheck.Value(arguments: $"--inconclusive --project={NativeTracerProject.Path} {CppCheckVersionDefines} --output-file={BuildDataDirectory}/{NativeTracerProject.Name}-cppcheck-{arch}.xml --xml --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); + CppCheck.Value(arguments: $"--inconclusive --project={NativeTracerProject.Path} {CppCheckVersionDefines} --output-file={BuildDataDirectory}/{NativeTracerProject.Name}-cppcheck-{arch}.txt --enable=all --suppress=\"noExplicitConstructor\" --suppress=\"cstyleCast\" --suppress=\"duplicateBreak\" --suppress=\"unreadVariable\" --suppress=\"functionConst\" --suppress=\"funcArgNamesDifferent\" --suppress=\"variableScope\" --suppress=\"useStlAlgorithm\" --suppress=\"functionStatic\" --suppress=\"initializerList\" --suppress=\"redundantAssignment\" --suppress=\"redundantInitialization\" --suppress=\"shadowVariable\" --suppress=\"constParameter\" --suppress=\"unusedPrivateFunction\" --suppress=\"unusedFunction\" --suppress=\"missingInclude\" --suppress=\"unmatchedSuppression\" --suppress=\"knownConditionTrueFalse\""); }); Target CppCheckNativeSrc => _ => _ diff --git a/tracer/build/_build/Build.cs b/tracer/build/_build/Build.cs index 20523923b8f0..06c819a8f57b 100644 --- a/tracer/build/_build/Build.cs +++ b/tracer/build/_build/Build.cs @@ -117,6 +117,15 @@ partial class Build : NukeBuild "See https://learn.microsoft.com/en-us/dotnet/core/rid-catalog")] string RuntimeIdentifier { get; } + string CppCheckVersionDefines + { + get + { + var version = new System.Version(Version); + return $"-DDD_VERSION_MAJOR={version.Major} -DDD_VERSION_MINOR={version.Minor} -DDD_VERSION_PATCH={version.Build}"; + } + } + public Build() { RuntimeIdentifier = GetDefaultRuntimeIdentifier(IsAlpine); From 6268b61f171e0e13d129f7fb8615568c43426525 Mon Sep 17 00:00:00 2001 From: Andrew Lock Date: Thu, 29 Oct 2026 13:43:37 +0000 Subject: [PATCH 6/6] Include DdVersion.cmake only from the root CMakeLists.txt Co-Authored-By: Claude Opus 5.5 --- build/cmake/DdVersion.cmake | 21 +++++++++---------- .../Datadog.Linux.ApiWrapper/CMakeLists.txt | 3 ++- .../CMakeLists.txt | 3 ++- .../CMakeLists.txt | 3 ++- .../src/Datadog.Tracer.Native/CMakeLists.txt | 3 ++- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/build/cmake/DdVersion.cmake b/build/cmake/DdVersion.cmake index 60670ec5af88..80327cb3296f 100644 --- a/build/cmake/DdVersion.cmake +++ b/build/cmake/DdVersion.cmake @@ -4,7 +4,11 @@ # expects (build/DdVersion.props defines the same set for the MSBuild builds). dd_version.h derives # everything else from them, so new derived values belong there, not here. # -# Deliberately re-read on every include and stored as a normal (not cached) variable, so that a +# Included only by the root CMakeLists.txt, before any add_subdirectory(), so that every subproject +# inherits DD_VERSION and the compile definitions. CMake must therefore be configured from the +# repository root. +# +# Deliberately re-read on every configure and stored as a normal (not cached) variable, so that a # version bump is picked up by an existing build directory, and you don't get weird instrumentation # mismatches locally, just after a release. @@ -28,16 +32,11 @@ endif() set(DD_VERSION "${CMAKE_MATCH_1}") message(STATUS "Datadog SDK version: ${DD_VERSION}") -# Directory-scoped, so they apply to every target in this directory and below. The subproject -# CMakeLists include this file again, so only add them once: normal variables are inherited by -# subdirectories. -if(NOT DD_VERSION_DEFINITIONS_ADDED) - add_compile_definitions( - DD_VERSION_MAJOR=${CMAKE_MATCH_2} - DD_VERSION_MINOR=${CMAKE_MATCH_3} - DD_VERSION_PATCH=${CMAKE_MATCH_4}) - set(DD_VERSION_DEFINITIONS_ADDED TRUE) -endif() +# Directory-scoped, so they apply to every target in this directory and below +add_compile_definitions( + DD_VERSION_MAJOR=${CMAKE_MATCH_2} + DD_VERSION_MINOR=${CMAKE_MATCH_3} + DD_VERSION_PATCH=${CMAKE_MATCH_4}) unset(_dd_version_props_content) unset(_dd_version_match) diff --git a/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt b/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt index 32d51a978c4e..577c305e039d 100644 --- a/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt +++ b/profiler/src/ProfilerEngine/Datadog.Linux.ApiWrapper/CMakeLists.txt @@ -2,7 +2,8 @@ # Project definition # ****************************************************** -include("${CMAKE_CURRENT_LIST_DIR}/../../../../build/cmake/DdVersion.cmake") +# DD_VERSION is set by build/cmake/DdVersion.cmake, which the root CMakeLists.txt includes, +# so configure CMake from the repository root rather than from this directory project("Datadog.Linux.ApiWrapper" VERSION ${DD_VERSION}) # ****************************************************** diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt index 6dc8a186ed2f..0da771f243fd 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native.Linux/CMakeLists.txt @@ -2,7 +2,8 @@ # Project definition # ****************************************************** -include("${CMAKE_CURRENT_LIST_DIR}/../../../../build/cmake/DdVersion.cmake") +# DD_VERSION is set by build/cmake/DdVersion.cmake, which the root CMakeLists.txt includes, +# so configure CMake from the repository root rather than from this directory project("Datadog.Profiler.Native.Linux" VERSION ${DD_VERSION}) option(RUN_ASAN "Build with Clang Undefined-Behavior Sanitizer" OFF) diff --git a/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt b/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt index 7257d32c34ea..618d5470503a 100644 --- a/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt +++ b/shared/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt @@ -12,7 +12,8 @@ endif() # Project definition # ****************************************************** -include("${CMAKE_CURRENT_LIST_DIR}/../../../build/cmake/DdVersion.cmake") +# DD_VERSION is set by build/cmake/DdVersion.cmake, which the root CMakeLists.txt includes, +# so configure CMake from the repository root rather than from this directory project("Datadog.Trace.ClrProfiler.Native" VERSION ${DD_VERSION}) if (UNIVERSAL) diff --git a/tracer/src/Datadog.Tracer.Native/CMakeLists.txt b/tracer/src/Datadog.Tracer.Native/CMakeLists.txt index 81bb915bd44c..29790d9d3fb6 100644 --- a/tracer/src/Datadog.Tracer.Native/CMakeLists.txt +++ b/tracer/src/Datadog.Tracer.Native/CMakeLists.txt @@ -12,7 +12,8 @@ endif() # Project definition # ****************************************************** -include("${CMAKE_CURRENT_LIST_DIR}/../../../build/cmake/DdVersion.cmake") +# DD_VERSION is set by build/cmake/DdVersion.cmake, which the root CMakeLists.txt includes, +# so configure CMake from the repository root rather than from this directory project("Datadog.Tracer.Native" VERSION ${DD_VERSION}) # ******************************************************