From 444dc0fe12cad4ce6f55112fc50fdff2421bf2bd Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 7 May 2026 15:32:55 +0200 Subject: [PATCH 1/6] ci: use builder on windows platforms --- builder/src/arch/windows.rs | 12 +++-- builder/src/builder.rs | 13 +++--- builder/src/profiling.rs | 3 ++ windows/build-artifacts.ps1 | 89 ------------------------------------- 4 files changed, 19 insertions(+), 98 deletions(-) delete mode 100644 windows/build-artifacts.ps1 diff --git a/builder/src/arch/windows.rs b/builder/src/arch/windows.rs index 1d9313817f..b21030f80c 100644 --- a/builder/src/arch/windows.rs +++ b/builder/src/arch/windows.rs @@ -6,12 +6,13 @@ use std::fs; use std::path::PathBuf; pub const NATIVE_LIBS: &str = ""; -pub const PROF_DYNAMIC_LIB: &str = "datadog_profiling.dll"; -pub const PROF_STATIC_LIB: &str = "datadog_profiling.lib"; -pub const PROF_PDB: &str = "datadog_profiling.pdb"; +pub const PROF_DYNAMIC_LIB: &str = "datadog_profiling_ffi.dll"; +pub const PROF_STATIC_LIB: &str = "datadog_profiling_ffi.lib"; +pub const PROF_PDB: &str = "datadog_profiling_ffi.pdb"; pub const PROF_DYNAMIC_LIB_FFI: &str = "datadog_profiling_ffi.dll"; pub const PROF_STATIC_LIB_FFI: &str = "datadog_profiling_ffi.lib"; pub const PROF_PDB_FFI: &str = "datadog_profiling_ffi.pdb"; +pub const PROF_DLL_IMPORT_LIB_FFI: &str = "datadog_profiling_ffi.dll.lib"; pub const BUILD_CRASHTRACKER: bool = false; pub const RUSTFLAGS: [&str; 4] = [ "-C", @@ -25,6 +26,9 @@ pub fn strip_libraries(_lib_path: &str) {} pub fn add_additional_files(lib_path: &str, target_path: &OsStr) { let from_pdb: PathBuf = [lib_path, PROF_PDB_FFI].iter().collect(); let to_pdb: PathBuf = [target_path, OsStr::new(PROF_PDB)].iter().collect(); - fs::copy(from_pdb, to_pdb).expect("unable to copy pdb file"); + + let from_imp: PathBuf = [lib_path, PROF_DLL_IMPORT_LIB_FFI].iter().collect(); + let to_imp: PathBuf = [target_path, OsStr::new(PROF_DLL_IMPORT_LIB_FFI)].iter().collect(); + fs::copy(from_imp, to_imp).expect("unable to copy dll import lib"); } diff --git a/builder/src/builder.rs b/builder/src/builder.rs index 88169e71dc..bce396f102 100644 --- a/builder/src/builder.rs +++ b/builder/src/builder.rs @@ -116,11 +116,14 @@ impl Builder { fs::create_dir_all(Path::new(self.target_include.as_ref())) .expect("Failed to create include directory"); fs::create_dir_all(Path::new(self.target_lib.as_ref())) - .expect("Failed to create include directory"); - fs::create_dir_all(Path::new(self.target_bin.as_ref())) - .expect("Failed to create include directory"); - fs::create_dir_all(Path::new(self.target_pkconfig.as_ref())) - .expect("Failed to create include directory"); + .expect("Failed to create lib directory"); + #[cfg(not(target_os = "windows"))] + { + fs::create_dir_all(Path::new(self.target_bin.as_ref())) + .expect("Failed to create bin directory"); + fs::create_dir_all(Path::new(self.target_pkconfig.as_ref())) + .expect("Failed to create pkgconfig directory"); + } } pub fn add_cmake(&self) { diff --git a/builder/src/profiling.rs b/builder/src/profiling.rs index f3579be4d2..3e106b8187 100644 --- a/builder/src/profiling.rs +++ b/builder/src/profiling.rs @@ -118,6 +118,9 @@ impl Profiling { } fn add_pkg_config(&self) -> Result<()> { + #[cfg(target_os = "windows")] + return Ok(()); + let files: [&str; 3] = [ "datadog_profiling.pc", "datadog_profiling_with_rpath.pc", diff --git a/windows/build-artifacts.ps1 b/windows/build-artifacts.ps1 deleted file mode 100644 index 90a64dbef6..0000000000 --- a/windows/build-artifacts.ps1 +++ /dev/null @@ -1,89 +0,0 @@ -function Invoke-Call { - param ( - [scriptblock]$ScriptBlock - ) - & @ScriptBlock - if ($lastexitcode -ne 0) { - exit $lastexitcode - } -} - -function Add-DllImportToGlobals { - param ( - [string]$HeaderPath - ) - $content = [System.IO.File]::ReadAllText($HeaderPath) - $pattern = '(?m)^(\s*)extern\s+(?!\"C\")(?!.*LIBDD_DLLIMPORT)(?!.*\()(.+;)$' - $updated = [System.Text.RegularExpressions.Regex]::Replace( - $content, - $pattern, - '$1extern LIBDD_DLLIMPORT $2' - ) - if ($updated -ne $content) { - $utf8NoBom = New-Object System.Text.UTF8Encoding($false) - [System.IO.File]::WriteAllText($HeaderPath, $updated, $utf8NoBom) - } -} - -$output_dir = $args[0] - -if ([string]::IsNullOrEmpty($output_dir)) { - throw "You must specify an output directory. Ex: $($myInvocation.InvocationName) my_rust_project/ bin" -} - -if (![System.IO.Path]::IsPathRooted($output_dir)) { - $output_dir = [System.IO.Path]::Combine($(Get-Location), $output_dir) -} - -Write-Host "Building project into $($output_dir)" -ForegroundColor Magenta - -# build inside the crate to use the config.toml file -$features = @( - "data-pipeline-ffi", - "crashtracker-collector", - "crashtracker-receiver", - "ddtelemetry-ffi", - "demangler", - "datadog-library-config-ffi", - "datadog-ffe-ffi", - "datadog-log-ffi" -) -join "," - -Write-Host "Building for features: $features" -ForegroundColor Magenta - -pushd libdd-profiling-ffi -#i686 Release -Invoke-Call -ScriptBlock { cargo rustc --features $features --target i686-pc-windows-msvc --release --target-dir $output_dir --crate-type cdylib } -Invoke-Call -ScriptBlock { cargo rustc --features $features --target i686-pc-windows-msvc --release --target-dir $output_dir --crate-type staticlib } -#i686 Debug -Invoke-Call -ScriptBlock { cargo rustc --features $features --target i686-pc-windows-msvc --target-dir $output_dir --crate-type cdylib } -Invoke-Call -ScriptBlock { cargo rustc --features $features --target i686-pc-windows-msvc --target-dir $output_dir --crate-type staticlib } -#x86_64 Release -Invoke-Call -ScriptBlock { cargo rustc --features $features --target x86_64-pc-windows-msvc --release --target-dir $output_dir --crate-type cdylib} -Invoke-Call -ScriptBlock { cargo rustc --features $features --target x86_64-pc-windows-msvc --release --target-dir $output_dir --crate-type staticlib} -#x86_64 Debug -Invoke-Call -ScriptBlock { cargo rustc --features $features --target x86_64-pc-windows-msvc --target-dir $output_dir --crate-type cdylib} -Invoke-Call -ScriptBlock { cargo rustc --features $features --target x86_64-pc-windows-msvc --target-dir $output_dir --crate-type staticlib} -popd - -Write-Host "Building tools" -ForegroundColor Magenta -Set-Location tools -Invoke-Call -ScriptBlock { cargo build --release } -Set-Location .. - -Write-Host "Generating headers" -ForegroundColor Magenta -Invoke-Call -ScriptBlock { cbindgen --crate libdd-common-ffi --config libdd-common-ffi/cbindgen.toml --output $output_dir\common.h } -Invoke-Call -ScriptBlock { cbindgen --crate libdd-profiling-ffi --config libdd-profiling-ffi/cbindgen.toml --output $output_dir\profiling.h } -Invoke-Call -ScriptBlock { cbindgen --crate libdd-telemetry-ffi --config libdd-telemetry-ffi/cbindgen.toml --output $output_dir\telemetry.h } -Invoke-Call -ScriptBlock { cbindgen --crate libdd-data-pipeline-ffi --config libdd-data-pipeline-ffi/cbindgen.toml --output $output_dir"\data-pipeline.h" } -Invoke-Call -ScriptBlock { cbindgen --crate libdd-crashtracker-ffi --config libdd-crashtracker-ffi/cbindgen.toml --output $output_dir"\crashtracker.h" } -Invoke-Call -ScriptBlock { cbindgen --crate libdd-library-config-ffi --config libdd-library-config-ffi/cbindgen.toml --output $output_dir"\library-config.h" } -Add-DllImportToGlobals $output_dir"\common.h" -Add-DllImportToGlobals $output_dir"\profiling.h" -Add-DllImportToGlobals $output_dir"\telemetry.h" -Add-DllImportToGlobals $output_dir"\data-pipeline.h" -Add-DllImportToGlobals $output_dir"\crashtracker.h" -Add-DllImportToGlobals $output_dir"\library-config.h" -Invoke-Call -ScriptBlock { .\target\release\dedup_headers $output_dir"\common.h" $output_dir"\profiling.h" $output_dir"\telemetry.h" $output_dir"\data-pipeline.h" $output_dir"\crashtracker.h" $output_dir"\library-config.h"} - -Write-Host "Build finished" -ForegroundColor Magenta From bf221a580bbcc8bcd118499279299a333c83e021 Mon Sep 17 00:00:00 2001 From: Julio Date: Tue, 12 May 2026 12:12:22 +0200 Subject: [PATCH 2/6] refactor: move add_pkg_config to arch --- builder/src/arch/apple.rs | 5 ++++ builder/src/arch/linux.rs | 5 ++++ builder/src/arch/mod.rs | 50 +++++++++++++++++++++++++++++++++++++ builder/src/arch/musl.rs | 5 ++++ builder/src/arch/windows.rs | 9 ++++++- builder/src/profiling.rs | 47 +++++----------------------------- 6 files changed, 79 insertions(+), 42 deletions(-) diff --git a/builder/src/arch/apple.rs b/builder/src/arch/apple.rs index c40d17c67b..6011a8ae10 100644 --- a/builder/src/arch/apple.rs +++ b/builder/src/arch/apple.rs @@ -1,6 +1,7 @@ // Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; use std::ffi::OsStr; use std::process::Command; @@ -32,3 +33,7 @@ pub fn strip_libraries(lib_path: &str) { } pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {} + +pub fn add_pkg_config(crate_path: &str, target_path: &str, version: &str) -> Result<()> { + super::generate_pkg_config(crate_path, target_path, version, NATIVE_LIBS) +} diff --git a/builder/src/arch/linux.rs b/builder/src/arch/linux.rs index 65fa738355..f01c8a0c05 100644 --- a/builder/src/arch/linux.rs +++ b/builder/src/arch/linux.rs @@ -1,6 +1,7 @@ // Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; use std::ffi::OsStr; use std::process::Command; @@ -56,3 +57,7 @@ pub fn strip_libraries(lib_path: &str) { } pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {} + +pub fn add_pkg_config(crate_path: &str, target_path: &str, version: &str) -> Result<()> { + super::generate_pkg_config(crate_path, target_path, version, NATIVE_LIBS) +} diff --git a/builder/src/arch/mod.rs b/builder/src/arch/mod.rs index 948ffc79a4..7109de262b 100644 --- a/builder/src/arch/mod.rs +++ b/builder/src/arch/mod.rs @@ -1,6 +1,56 @@ // Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; +use std::ffi::OsStr; +use std::fs; +use std::path::{Path, PathBuf}; + +use crate::utils::{file_replace, project_root}; + +pub fn generate_pkg_config( + crate_path: &str, + target_path: &str, + version: &str, + native_libs: &str, +) -> Result<()> { + let files: [&str; 3] = [ + "datadog_profiling.pc", + "datadog_profiling_with_rpath.pc", + "datadog_profiling-static.pc", + ]; + + let pc_dir = Path::new(target_path); + fs::create_dir_all(pc_dir).expect("Failed to create pkgconfig directory"); + + for file in files.iter() { + let file_in = file.to_string() + ".in"; + + let mut pc_origin: PathBuf = project_root(); + pc_origin.push(crate_path); + pc_origin.push(file_in); + + let pc_target: PathBuf = [pc_dir.as_os_str(), OsStr::new(file)].iter().collect(); + + file_replace( + pc_origin.to_str().unwrap(), + pc_target.to_str().unwrap(), + "@Datadog_VERSION@", + version, + )?; + + if *file == files[2] { + file_replace( + pc_origin.to_str().unwrap(), + pc_target.to_str().unwrap(), + "@Datadog_LIBRARIES@", + native_libs, + )?; + } + } + Ok(()) +} + #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))] #[cfg(all(target_os = "linux", target_env = "gnu"))] mod linux; diff --git a/builder/src/arch/musl.rs b/builder/src/arch/musl.rs index 684b0c1f3b..1ac5e2a1a2 100644 --- a/builder/src/arch/musl.rs +++ b/builder/src/arch/musl.rs @@ -1,6 +1,7 @@ // Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; use std::ffi::OsStr; use std::process::Command; @@ -56,3 +57,7 @@ pub fn strip_libraries(lib_path: &str) { } pub fn add_additional_files(_lib_path: &str, _target_path: &OsStr) {} + +pub fn add_pkg_config(crate_path: &str, target_path: &str, version: &str) -> Result<()> { + super::generate_pkg_config(crate_path, target_path, version, NATIVE_LIBS) +} diff --git a/builder/src/arch/windows.rs b/builder/src/arch/windows.rs index b21030f80c..cc48262290 100644 --- a/builder/src/arch/windows.rs +++ b/builder/src/arch/windows.rs @@ -1,6 +1,7 @@ // Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/ // SPDX-License-Identifier: Apache-2.0 +use anyhow::Result; use std::ffi::OsStr; use std::fs; use std::path::PathBuf; @@ -29,6 +30,12 @@ pub fn add_additional_files(lib_path: &str, target_path: &OsStr) { fs::copy(from_pdb, to_pdb).expect("unable to copy pdb file"); let from_imp: PathBuf = [lib_path, PROF_DLL_IMPORT_LIB_FFI].iter().collect(); - let to_imp: PathBuf = [target_path, OsStr::new(PROF_DLL_IMPORT_LIB_FFI)].iter().collect(); + let to_imp: PathBuf = [target_path, OsStr::new(PROF_DLL_IMPORT_LIB_FFI)] + .iter() + .collect(); fs::copy(from_imp, to_imp).expect("unable to copy dll import lib"); } + +pub fn add_pkg_config(_crate_path: &str, _target_path: &str, _version: &str) -> Result<()> { + Ok(()) +} diff --git a/builder/src/profiling.rs b/builder/src/profiling.rs index 3e106b8187..ca3f9f6ada 100644 --- a/builder/src/profiling.rs +++ b/builder/src/profiling.rs @@ -3,7 +3,7 @@ use crate::arch; use crate::module::Module; -use crate::utils::{adjust_extern_symbols, file_replace, project_root, wait_for_success}; +use crate::utils::{adjust_extern_symbols, project_root, wait_for_success}; use anyhow::Result; use serde::Deserialize; use std::ffi::OsStr; @@ -118,46 +118,11 @@ impl Profiling { } fn add_pkg_config(&self) -> Result<()> { - #[cfg(target_os = "windows")] - return Ok(()); - - let files: [&str; 3] = [ - "datadog_profiling.pc", - "datadog_profiling_with_rpath.pc", - "datadog_profiling-static.pc", - ]; - - //Create directory - let pc_dir = Path::new(self.target_pkconfig.as_ref()); - fs::create_dir_all(pc_dir).expect("Failed to create pkgconfig directory"); - - // Create files - for file in files.iter() { - let file_in = file.to_string() + ".in"; - - let mut pc_origin: PathBuf = project_root(); - pc_origin.push(CRATE_FOLDER); - pc_origin.push(file_in); - - let pc_target: PathBuf = [pc_dir.as_os_str(), OsStr::new(file)].iter().collect(); - - file_replace( - pc_origin.to_str().unwrap(), - pc_target.to_str().unwrap(), - "@Datadog_VERSION@", - &self.version, - )?; - - if *file == files[2] { - file_replace( - pc_origin.to_str().unwrap(), - pc_target.to_str().unwrap(), - "@Datadog_LIBRARIES@", - arch::NATIVE_LIBS, - )?; - } - } - Ok(()) + arch::add_pkg_config( + CRATE_FOLDER, + self.target_pkconfig.as_ref(), + self.version.as_ref(), + ) } } From 2dbe302bd1f067da52ddd02866af972b5b6e56d9 Mon Sep 17 00:00:00 2001 From: Julio Date: Tue, 12 May 2026 13:39:39 +0200 Subject: [PATCH 3/6] chore: reference libddprof branch that matches the changes in the builder --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 255c62d7c6..c5b002070b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,7 @@ variables: # These are gitlab variables so that it's easier to do a manual deploy # If these are set witih value and description, then it gives you UI elements DOWNSTREAM_BRANCH: - value: "main" + value: "julio/use-builder-on-windows" description: "downstream jobs are triggered on this branch" include: From 8a4955fbcc57ecbba171109c578b3bb9cf22dd7b Mon Sep 17 00:00:00 2001 From: Julio Date: Wed, 13 May 2026 10:42:47 +0200 Subject: [PATCH 4/6] chore: modify csproj to update binary paths --- windows/libdatadog.csproj | 44 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/windows/libdatadog.csproj b/windows/libdatadog.csproj index e62ebbde6c..1daf53158a 100644 --- a/windows/libdatadog.csproj +++ b/windows/libdatadog.csproj @@ -27,53 +27,51 @@ - - - - - - - - - - - - - - - - - - - - - - From 47d804df4f69282810b68fd026b76b91e20863f0 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 21 May 2026 15:21:41 +0200 Subject: [PATCH 5/6] chore: reference main again --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c5b002070b..255c62d7c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,7 @@ variables: # These are gitlab variables so that it's easier to do a manual deploy # If these are set witih value and description, then it gives you UI elements DOWNSTREAM_BRANCH: - value: "julio/use-builder-on-windows" + value: "main" description: "downstream jobs are triggered on this branch" include: From d383f313feec1b4ccd85f390639c37aad7dc2342 Mon Sep 17 00:00:00 2001 From: Julio Date: Thu, 21 May 2026 22:42:20 +0200 Subject: [PATCH 6/6] fix: add release path to environment when running tests --- tools/src/bin/ffi_test.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/src/bin/ffi_test.rs b/tools/src/bin/ffi_test.rs index 262101f433..4ac1bb9cad 100644 --- a/tools/src/bin/ffi_test.rs +++ b/tools/src/bin/ffi_test.rs @@ -188,6 +188,31 @@ fn library_search_path_env(lib_dir: &Path) -> (String, String) { (search_path_var.to_string(), lib_path) } +/// Env vars applied to every spawned test, regardless of name. +/// +/// On Windows the test executables are dynamically linked against +/// `datadog_profiling_ffi.dll` (CMake's `find_library` picks the import library +/// over the static `.lib`). The DLL lives in `release/lib/` but the executables +/// run from a temp work directory, so without help Windows can't locate it and +/// every test exits with STATUS_DLL_NOT_FOUND (0xC0000135). +#[cfg(windows)] +fn base_env_vars(project_root: &Path) -> Vec<(String, String)> { + let lib_dir = project_root.join("release").join("lib"); + if !lib_dir.exists() { + return vec![]; + } + let new_path = match std::env::var("PATH") { + Ok(existing) if !existing.is_empty() => format!("{};{}", lib_dir.display(), existing), + _ => lib_dir.display().to_string(), + }; + vec![("PATH".to_string(), new_path)] +} + +#[cfg(not(windows))] +fn base_env_vars(_project_root: &Path) -> Vec<(String, String)> { + vec![] +} + /// Per-test environment variables. The runner sets these before spawning /// the test executable so that tests which need external resources (e.g. the /// receiver binary) can find them without hard-coding paths. @@ -528,7 +553,8 @@ fn run_test( ) -> TestResult { let is_expected_failure = expected_failures().contains_key(name); let expected_crash = expected_crashes().get(name); - let env_vars = per_test_env(name, project_root, work_dir); + let mut env_vars = base_env_vars(project_root); + env_vars.extend(per_test_env(name, project_root, work_dir)); let start = Instant::now(); let child = match spawn_test(exe_path, work_dir, &env_vars) {