Skip to content

Commit b7e0302

Browse files
committed
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.
1 parent 5a7c5f7 commit b7e0302

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

NEWS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
RcppParallel 6.0.0, such packages would fail to load with "LoadLibrary
88
failure: The specified module could not be found".
99

10-
* The bundled oneTBB headers now guard against GCC's `<cpuid.h>` being
10+
* The TBB headers installed with RcppParallel (whether from Rtools or from
11+
the bundled copy of oneTBB) now guard against GCC's `<cpuid.h>` being
1112
included before `<intrin.h>` on Windows (mingw). Previously, translation
1213
units including `<cpuid.h>` before any TBB header would fail to compile,
1314
as the `__cpuid` macro from `<cpuid.h>` conflicts with the `__cpuid()`

src/install.libs.R

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,53 @@
8888
}
8989

9090
useTbbPreamble <- function(tbbInc) {
91+
9192
dir.create("../inst/include", recursive = TRUE, showWarnings = FALSE)
9293
for (suffix in c("oneapi", "serial", "tbb")) {
9394
tbbPath <- file.path(tbbInc, suffix)
9495
if (file.exists(tbbPath)) {
9596
file.copy(tbbPath, "../inst/include", recursive = TRUE)
9697
}
9798
}
99+
100+
patchTbbMachineHeader("../inst/include/oneapi/tbb/detail/_machine.h")
101+
102+
}
103+
104+
# Guard the '#include <intrin.h>' in TBB's _machine.h against GCC's
105+
# <cpuid.h> macro on mingw. The headers we ship may come from Rtools
106+
# rather than from the bundled copy of oneTBB, so the guard must be
107+
# applied to the copied headers, not just the bundled sources.
108+
patchTbbMachineHeader <- function(path) {
109+
110+
if (!file.exists(path))
111+
return()
112+
113+
contents <- readLines(path)
114+
if (any(grepl("push_macro", contents, fixed = TRUE)))
115+
return()
116+
117+
index <- which(contents == "#include <intrin.h>")
118+
if (length(index) != 1L)
119+
return()
120+
121+
replacement <- c(
122+
"// GCC's <cpuid.h> defines a function-like '__cpuid' macro that mangles the",
123+
"// __cpuid() declarations in mingw's <intrin.h>. Hide the macro while",
124+
"// including <intrin.h> so the two headers can coexist in any order.",
125+
"#if defined(__MINGW32__) && defined(__cpuid)",
126+
"#pragma push_macro(\"__cpuid\")",
127+
"#undef __cpuid",
128+
"#include <intrin.h>",
129+
"#pragma pop_macro(\"__cpuid\")",
130+
"#else",
131+
"#include <intrin.h>",
132+
"#endif"
133+
)
134+
135+
contents <- append(contents[-index], replacement, after = index - 1L)
136+
writeLines(contents, path)
137+
98138
}
99139

100140
useSystemTbb <- function(tbbLib, tbbInc) {

0 commit comments

Comments
 (0)