Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# RcppParallel (development version)

* The mingw cpuid guard applied to TBB's `_machine.h` header during
installation is now logged, and a warning is emitted if the header does
not have the expected form and the guard cannot be applied.

* On Linux, the bundled TBB libraries are once again installed with versioned
names (e.g. `libtbb.so.2`) plus an unversioned `libtbb.so` symlink, matching
the layout shipped by RcppParallel 5.1.11 and earlier. The oneTBB cmake build
Expand Down
24 changes: 18 additions & 6 deletions src/install.libs.R
Original file line number Diff line number Diff line change
Expand Up @@ -270,16 +270,27 @@ useTbbPreamble <- function(tbbInc) {
# applied to the copied headers, not just the bundled sources.
patchTbbMachineHeader <- function(path) {

if (!file.exists(path))
return()
if (!file.exists(path)) {
writeLines(sprintf("** no tbb header at '%s'; skipping mingw cpuid guard", path))
return(invisible())
}

contents <- readLines(path)
if (any(grepl("push_macro", contents, fixed = TRUE)))
return()
if (any(grepl("push_macro", contents, fixed = TRUE))) {
writeLines(sprintf("** mingw cpuid guard already present in '%s'", path))
return(invisible())
}

index <- which(contents == "#include <intrin.h>")
if (length(index) != 1L)
return()
if (length(index) != 1L) {
fmt <- paste(
"expected exactly one '#include <intrin.h>' line in '%s', but found %i;",
"the mingw cpuid guard was not applied, and mingw builds using these",
"headers may fail -- see patches/mingw_cpuid.diff"
)
warning(sprintf(fmt, path, length(index)))
return(invisible())
}

replacement <- c(
"// GCC's <cpuid.h> defines a function-like '__cpuid' macro that mangles the",
Expand All @@ -297,6 +308,7 @@ patchTbbMachineHeader <- function(path) {

contents <- append(contents[-index], replacement, after = index - 1L)
writeLines(contents, path)
writeLines(sprintf("** applied mingw cpuid guard to '%s'", path))

}

Expand Down
32 changes: 32 additions & 0 deletions tests/test-install-libs.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ if (length(marker))
env <- new.env(parent = globalenv())
eval(parse(text = paste(lines, collapse = "\n")), envir = env)
splitCompilerVar <- get("splitCompilerVar", envir = env)
patchTbbMachineHeader <- get("patchTbbMachineHeader", envir = env)

# minimal assertion harness
failures <- 0L
Expand Down Expand Up @@ -112,6 +113,37 @@ Sys.unsetenv("TEST_CXX_UNSET")
check(identical(splitCompilerVar("TEST_CXX_UNSET", "TEST_CXXFLAGS"), FALSE),
"unset compiler variable returns FALSE")

# the mingw cpuid guard should be applied exactly once to a header with the
# expected form, and applying it again should leave the header untouched
header <- tempfile(fileext = ".h")
writeLines(c("#pragma once", "#include <intrin.h>", "int value;"), header)
patchTbbMachineHeader(header)
patched <- readLines(header)
check(any(grepl("push_macro", patched, fixed = TRUE)),
"cpuid guard is applied to a well-formed header")
patchTbbMachineHeader(header)
check(identical(readLines(header), patched),
"cpuid guard application is idempotent")

# a header without exactly one matching include line must not be modified,
# and the skipped patch must be surfaced as a warning (a silent no-op here
# would quietly reintroduce the mingw __cpuid build failure)
malformed <- tempfile(fileext = ".h")
original <- c("#pragma once", " #include <intrin.h>")
writeLines(original, malformed)
warned <- FALSE
withCallingHandlers(
patchTbbMachineHeader(malformed),
warning = function(w) {
warned <<- TRUE
invokeRestart("muffleWarning")
}
)
check(warned, "unexpected header form emits a warning")
check(identical(readLines(malformed), original),
"unexpected header form is left unmodified")
unlink(c(header, malformed))

if (failures > 0L)
stop(sprintf("%d install.libs.R helper test(s) failed", failures))

Expand Down
Loading