diff --git a/NEWS.md b/NEWS.md index 99d10cf8..58d86609 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,9 +16,16 @@ user's toolchain, and left downstream packages with no TBB library to link against. Building it ourselves gives every platform the same oneTBB and makes the ABI a property of RcppParallel. `TBB_LIB` / `TBB_INC` are still honoured - for anyone supplying their own build. This requires cmake, which Rtools has - shipped since Rtools42; toolchains without one continue to use the tinythread - fallback. + for anyone supplying their own build. + +* Building RcppParallel now requires cmake (>= 3.5) on all platforms, as + `SystemRequirements` has always declared. Previously a missing or unusable + cmake was fatal everywhere except Windows, where it instead produced a + package with no TBB backend at all -- a silently degraded install that was + easy to end up with and hard to notice. TBB is now always enabled. Rtools has + shipped cmake since Rtools42, so this should not affect Windows users in + practice. Note that the tinythread backend remains selectable at runtime via + `RCPP_PARALLEL_BACKEND=tinythread`; it is only no longer a build outcome. * As a consequence, `RcppParallel::RcppParallelLibs()` now emits `-ltbb` and `-ltbbmalloc` on Windows, in addition to `-lRcppParallel` (which remains diff --git a/src/install.libs.R b/src/install.libs.R index 1e56e968..3b3cfdaa 100644 --- a/src/install.libs.R +++ b/src/install.libs.R @@ -481,18 +481,15 @@ args <- commandArgs(trailingOnly = TRUE) if (identical(args, "build")) { if (nzchar(tbbLib) && nzchar(tbbInc)) { useSystemTbb(tbbLib, tbbInc) - } else if (.Platform$OS.type == "windows" && !nzchar(Sys.getenv("CMAKE"))) { - # configure found neither a usable TBB nor a cmake to build one with - writeLines("** building RcppParallel without tbb backend") } else { useBundledTbb() } } else { - # prefer the configure-detected TBB_LIB when the environment variable - # is unset; otherwise, e.g. on Windows (where configure detects the - # Rtools copy of TBB), we'd wrongly take the bundled-TBB branch below, - # and ship any stale artifacts present in tbb/build/lib_release + # prefer the configure-detected TBB_LIB when the environment variable is + # unset; otherwise a TBB configured via TBB_ROOT (which sets TBB_LIB only in + # the generated tbb-autodetected.R) would wrongly take the bundled-TBB + # branch below, and ship any stale artifacts in tbb/build/lib_release source("../R/tbb-autodetected.R") if (!nzchar(tbbLib)) tbbLib <- TBB_LIB diff --git a/tools/config/configure.R b/tools/config/configure.R index d3d1311f..6293fe13 100644 --- a/tools/config/configure.R +++ b/tools/config/configure.R @@ -111,11 +111,12 @@ if (tryAutoDetect) { } -# if we didn't find a TBB to use, we'll build the bundled copy from -# sources -- which requires cmake. on Windows, a cmake that is missing, -# unusable or too old is not fatal: toolchains that can't build oneTBB -# (e.g. Rtools40, which provides neither cmake nor a TBB) fall back to -# tinythread instead +# if we didn't find a TBB to use, we'll build the bundled copy from sources -- +# which requires cmake, on every platform. this is what 'SystemRequirements: +# CMake (>= 3.5)' in DESCRIPTION declares, so a missing or unusable cmake is an +# unmet system requirement and fails the install rather than quietly producing +# a package with no TBB backend. (the tinythread backend is still selectable at +# runtime via RCPP_PARALLEL_BACKEND; it is only no longer a build outcome.) define(CMAKE = "") buildBundledTbb <- FALSE @@ -146,8 +147,8 @@ if (is.na(tbbLib)) { # (use the resolved path; cmake may not be on the PATH) # # any failure here -- a CMAKE pointing at nothing runnable, version output - # we can't parse -- is treated as 'no usable cmake' rather than allowed to - # propagate, so that Windows can still fall back to tinythread below + # we can't parse -- is reported as 'no usable cmake', so that the error + # names the actual problem rather than surfacing as a parse failure cmakeVersion <- NA if (!is.na(cmake)) { cmakeVersion <- tryCatch({ @@ -158,11 +159,7 @@ if (is.na(tbbLib)) { buildBundledTbb <- !is.na(cmakeVersion) && cmakeVersion >= "3.5" - if (buildBundledTbb) { - - define(CMAKE = cmake) - - } else { + if (!buildBundledTbb) { reason <- if (is.na(cmake)) { "cmake was not found" @@ -172,16 +169,12 @@ if (is.na(tbbLib)) { sprintf("cmake %s is too old (need >= 3.5)", cmakeVersion) } - # not fatal on Windows: toolchains that can build neither an oneTBB nor - # anything else (e.g. Rtools40, which provides no cmake and no TBB) use - # the tinythread backend instead - if (.Platform$OS.type == "windows") - writeLines(paste0(reason, "; building RcppParallel without a tbb backend")) - else - stop("error: RcppParallel requires cmake (>= 3.5); ", reason) + stop("error: RcppParallel requires cmake (>= 3.5); ", reason) } + define(CMAKE = cmake) + } # now, define TBB_LIB and TBB_INC as appropriate @@ -205,11 +198,6 @@ pkgLibs <- if (!is.na(tbbLib)) { "-l$(TBB_MALLOC_NAME)" ) -} else if (!buildBundledTbb) { - - # no TBB to link at all; the tinythread fallback is used instead - NULL - } else if (R.version$os == "emscripten") { c( @@ -245,13 +233,11 @@ if (!is.na(tbbLib)) { } # PKG_CXXFLAGS -if (.Platform$OS.type == "windows" && is.na(tbbLib) && !buildBundledTbb) { - define(TBB_ENABLED = FALSE) - define(PKG_CXXFLAGS = "-DRCPP_PARALLEL_USE_TBB=0") -} else { - define(TBB_ENABLED = TRUE) - define(PKG_CXXFLAGS = "-DRCPP_PARALLEL_USE_TBB=1") -} +# +# TBB is always enabled: either one was supplied via TBB_LIB / TBB_ROOT, or we +# built the bundled copy, and failing to do either is fatal above +define(TBB_ENABLED = TRUE) +define(PKG_CXXFLAGS = "-DRCPP_PARALLEL_USE_TBB=1") # macOS needs some extra flags set if (Sys.info()[["sysname"]] == "Darwin") {