From b7e03028c2d7154782ba1ea3de9a28cfa06466b8 Mon Sep 17 00:00:00 2001 From: Kevin Ushey Date: Thu, 23 Jul 2026 15:48:05 -0700 Subject: [PATCH] apply cpuid guard to tbb headers copied at install time On Windows, RcppParallel ships the TBB headers provided by Rtools, not the bundled copy of oneTBB -- useTbbPreamble() copies them from TBB_INC at build time. The __cpuid guard added in #248 patched only the bundled sources, so installed packages on Windows never received it, and the cpuid.h/intrin.h include-order conflict persisted. Post-process the copied _machine.h in useTbbPreamble() instead, applying the same guard to whichever headers are actually installed. The patch function is idempotent and bails if the header does not have the expected form. --- NEWS.md | 3 ++- src/install.libs.R | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4bcdac2f..661b4c50 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,7 +7,8 @@ RcppParallel 6.0.0, such packages would fail to load with "LoadLibrary failure: The specified module could not be found". -* The bundled oneTBB headers now guard against GCC's `` being +* The TBB headers installed with RcppParallel (whether from Rtools or from + the bundled copy of oneTBB) now guard against GCC's `` being included before `` on Windows (mingw). Previously, translation units including `` before any TBB header would fail to compile, as the `__cpuid` macro from `` conflicts with the `__cpuid()` diff --git a/src/install.libs.R b/src/install.libs.R index 142914c4..06a7899b 100644 --- a/src/install.libs.R +++ b/src/install.libs.R @@ -88,6 +88,7 @@ } useTbbPreamble <- function(tbbInc) { + dir.create("../inst/include", recursive = TRUE, showWarnings = FALSE) for (suffix in c("oneapi", "serial", "tbb")) { tbbPath <- file.path(tbbInc, suffix) @@ -95,6 +96,45 @@ useTbbPreamble <- function(tbbInc) { file.copy(tbbPath, "../inst/include", recursive = TRUE) } } + + patchTbbMachineHeader("../inst/include/oneapi/tbb/detail/_machine.h") + +} + +# Guard the '#include ' in TBB's _machine.h against GCC's +# macro on mingw. The headers we ship may come from Rtools +# rather than from the bundled copy of oneTBB, so the guard must be +# applied to the copied headers, not just the bundled sources. +patchTbbMachineHeader <- function(path) { + + if (!file.exists(path)) + return() + + contents <- readLines(path) + if (any(grepl("push_macro", contents, fixed = TRUE))) + return() + + index <- which(contents == "#include ") + if (length(index) != 1L) + return() + + replacement <- c( + "// GCC's defines a function-like '__cpuid' macro that mangles the", + "// __cpuid() declarations in mingw's . Hide the macro while", + "// including so the two headers can coexist in any order.", + "#if defined(__MINGW32__) && defined(__cpuid)", + "#pragma push_macro(\"__cpuid\")", + "#undef __cpuid", + "#include ", + "#pragma pop_macro(\"__cpuid\")", + "#else", + "#include ", + "#endif" + ) + + contents <- append(contents[-index], replacement, after = index - 1L) + writeLines(contents, path) + } useSystemTbb <- function(tbbLib, tbbInc) {