Skip to content

Commit a269874

Browse files
authored
apply cpuid guard to tbb headers copied at install time (#253)
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 a269874

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)