From 40a0a6e02d8c49ea98e0c27068591d44eeb279e0 Mon Sep 17 00:00:00 2001 From: pat-s Date: Sun, 4 Oct 2026 07:35:01 +0000 Subject: [PATCH 1/4] fix(patches): cover every RcppParallel 6.x release with the bundled-TBB patch (#228) --- .../force-bundled-tbb-6.0.0.patch | 152 +++++++++++++++++ .../force-bundled-tbb-6.1.x.patch | 157 ++++++++++++++++++ ...bb.patch => force-bundled-tbb-6.2.x.patch} | 68 ++++---- local/patches/registry.json | 44 ++++- 4 files changed, 381 insertions(+), 40 deletions(-) create mode 100644 local/patches/RcppParallel/force-bundled-tbb-6.0.0.patch create mode 100644 local/patches/RcppParallel/force-bundled-tbb-6.1.x.patch rename local/patches/RcppParallel/{force-bundled-tbb.patch => force-bundled-tbb-6.2.x.patch} (67%) diff --git a/local/patches/RcppParallel/force-bundled-tbb-6.0.0.patch b/local/patches/RcppParallel/force-bundled-tbb-6.0.0.patch new file mode 100644 index 0000000..a7f91dc --- /dev/null +++ b/local/patches/RcppParallel/force-bundled-tbb-6.0.0.patch @@ -0,0 +1,152 @@ +diff --git a/R/aaa.R b/R/aaa.R +index 568a2aa..2744059 100644 +--- a/R/aaa.R ++++ b/R/aaa.R +@@ -5,4 +5,21 @@ TBB_LIB <- "" + TBB_INC <- "" + + TBB_NAME <- "tbb" +-TBB_MALLOC_NAME <- "tbbmalloc" +\ No newline at end of file ++TBB_MALLOC_NAME <- "tbbmalloc" ++ ++# bincraft patch: build images (ours did until build-env-images c51ed09) and ++# plenty of user environments export TBB_ROOT / TBB_LIB / TBB_INC. A binary we ++# publish always carries its own oneTBB in RcppParallel/lib -- see the ++# companion changes in tools/config/configure.R and src/install.libs.R -- so ++# honouring those variables at run time is actively harmful: .onLoad() would ++# dyn.load() a second, unrelated TBB into the process next to the bundled one ++# (two copies of the same symbols in the global scope, which segfaults R on ++# load), and RcppParallelLibs() / CxxFlags() would hand that system TBB to ++# dependents such as rstan, putting NEEDED libtbb.so.12 back into their ++# binaries. Read the variables only when explicitly opted back in. ++bincraftGetenv <- function(name, unset = "") { ++ if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") == "TRUE") ++ Sys.getenv(name, unset = unset) ++ else ++ unset ++} +\ No newline at end of file +diff --git a/R/tbb.R b/R/tbb.R +index 3d8fbb3..9560165 100644 +--- a/R/tbb.R ++++ b/R/tbb.R +@@ -17,7 +17,7 @@ tbbLibraryPath <- function(name = NULL) { + sysname <- Sys.info()[["sysname"]] + + # find root for TBB install +- tbbRoot <- Sys.getenv("TBB_LIB", unset = tbbRoot()) ++ tbbRoot <- bincraftGetenv("TBB_LIB", unset = tbbRoot()) + if (is.null(name)) + return(tbbRoot) + +@@ -60,7 +60,7 @@ tbbCxxFlags <- function() { + flags <- c("-DRCPP_PARALLEL_USE_TBB=1") + + # if TBB_INC is set, apply those library paths +- tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC) ++ tbbInc <- bincraftGetenv("TBB_INC", unset = TBB_INC) + if (!file.exists(tbbInc)) { + tbbInc <- system.file("include", package = "RcppParallel") + } +@@ -100,7 +100,7 @@ tbbLdFlags <- function() { + } + + # shortcut if TBB_LIB defined +- tbbLib <- Sys.getenv("TBB_LINK_LIB", Sys.getenv("TBB_LIB", unset = TBB_LIB)) ++ tbbLib <- bincraftGetenv("TBB_LINK_LIB", bincraftGetenv("TBB_LIB", unset = TBB_LIB)) + if (nzchar(tbbLib)) { + if (R.version$os == "emscripten") { + fmt <- "-L%1$s -l%2$s" +diff --git a/src/install.libs.R b/src/install.libs.R +index 4dcbac2..57dbc74 100644 +--- a/src/install.libs.R ++++ b/src/install.libs.R +@@ -258,6 +258,18 @@ prependFlags <- function(prependFlags, toFlags) { + tbbLib <- Sys.getenv("TBB_LIB") + tbbInc <- Sys.getenv("TBB_INC") + ++# bincraft patch: the companion change in tools/config/configure.R stops an ++# ambient TBB_LIB / TBB_INC from selecting a system TBB, but this script is ++# also run directly by `R CMD INSTALL` (not only through the `tbb` rule in ++# src/Makevars, which passes the configured values), so at install time it ++# still sees the image's environment and would symlink the system libraries ++# into RcppParallel/lib. Drop them here for the same reason, under the same ++# opt-out. ++if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") != "TRUE") { ++ tbbLib <- "" ++ tbbInc <- "" ++} ++ + args <- commandArgs(trailingOnly = TRUE) + if (identical(args, "build")) { + if (nzchar(tbbLib) && nzchar(tbbInc)) { +diff --git a/tools/config/configure.R b/tools/config/configure.R +index a001e63..bfe8c8e 100644 +--- a/tools/config/configure.R ++++ b/tools/config/configure.R +@@ -144,6 +144,24 @@ tbbRoot <- Sys.getenv("TBB_ROOT", unset = NA) + tbbLib <- Sys.getenv("TBB_LIB", unset = NA) + tbbInc <- Sys.getenv("TBB_INC", unset = NA) + ++# bincraft patch: ignore an ambient TBB_ROOT / TBB_LIB / TBB_INC. Our build ++# images exported these until build-env-images c51ed09 (a leftover from ++# RcppParallel 5.x, whose bundled Intel TBB would not build on musl or with ++# modern g++), and any of them switches the branches below to a system TBB. ++# The published binary then records NEEDED libtbb.so.12 (or libtbb.so.2 for ++# the classic Intel TBB) and gets a RcppParallel/lib full of absolute symlinks ++# into the image's library dir, so it cannot dyn.load on a consumer machine ++# without that exact TBB. 6.x bundles oneTBB 2022 and builds it with cmake on ++# every platform we ship, so the bundled copy is always the right choice here; ++# forcing it in the package rather than relying on the image environment keeps ++# the binary correct whichever image version CI happens to pull. Set ++# BINCRAFT_ALLOW_SYSTEM_TBB=TRUE to restore the upstream behaviour. ++if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") != "TRUE") { ++ tbbRoot <- NA ++ tbbLib <- NA ++ tbbInc <- NA ++} ++ + tbbName <- Sys.getenv("TBB_NAME", unset = "tbb") + tbbMallocName <- Sys.getenv("TBB_MALLOC_NAME", unset = "tbbmalloc") + +@@ -224,10 +242,21 @@ define( + ) + + # set PKG_LIBS ++# ++# bincraft patch: the library directories below are passed as plain '-L', not ++# '-Wl,-L'. gcc expands its own search dirs (/usr/lib64, /usr/lib/) ++# into explicit '-L' options ahead of anything forwarded verbatim with '-Wl,', ++# so with '-Wl,-L' a system libtbb.so wins over the one named here: on a build ++# host with a distro TBB installed, '-ltbb' resolves to that library and ++# RcppParallel.so records its SONAME (libtbb.so.12, or libtbb.so.2 for the ++# classic Intel TBB) instead of the bundled 'libtbb.so'. The binary then loads ++# the system TBB rather than the copy shipped in RcppParallel/lib, and fails ++# outright on a machine that has no system TBB. gcc places a plain '-L' before ++# its built-in dirs, so the intended library is found first. + pkgLibs <- if (!is.na(tbbLib)) { + + c( +- "-Wl,-L\"$(TBB_LIB)\"", ++ "-L\"$(TBB_LIB)\"", + sprintf("-Wl,-rpath,%s", shQuote(tbbLib)), + "-l$(TBB_NAME)", + "-l$(TBB_MALLOC_NAME)" +@@ -240,14 +269,14 @@ pkgLibs <- if (!is.na(tbbLib)) { + } else if (R.version$os == "emscripten") { + + c( +- "-Wl,-Ltbb/build/lib_release", ++ "-Ltbb/build/lib_release", + "-l$(TBB_NAME)" + ) + + } else { + + c( +- "-Wl,-Ltbb/build/lib_release", ++ "-Ltbb/build/lib_release", + "-l$(TBB_NAME)", + "-l$(TBB_MALLOC_NAME)" + ) diff --git a/local/patches/RcppParallel/force-bundled-tbb-6.1.x.patch b/local/patches/RcppParallel/force-bundled-tbb-6.1.x.patch new file mode 100644 index 0000000..948643c --- /dev/null +++ b/local/patches/RcppParallel/force-bundled-tbb-6.1.x.patch @@ -0,0 +1,157 @@ +diff --git a/R/aaa.R b/R/aaa.R +index 568a2aa..2744059 100644 +--- a/R/aaa.R ++++ b/R/aaa.R +@@ -5,4 +5,21 @@ TBB_LIB <- "" + TBB_INC <- "" + + TBB_NAME <- "tbb" +-TBB_MALLOC_NAME <- "tbbmalloc" +\ No newline at end of file ++TBB_MALLOC_NAME <- "tbbmalloc" ++ ++# bincraft patch: build images (ours did until build-env-images c51ed09) and ++# plenty of user environments export TBB_ROOT / TBB_LIB / TBB_INC. A binary we ++# publish always carries its own oneTBB in RcppParallel/lib -- see the ++# companion changes in tools/config/configure.R and src/install.libs.R -- so ++# honouring those variables at run time is actively harmful: .onLoad() would ++# dyn.load() a second, unrelated TBB into the process next to the bundled one ++# (two copies of the same symbols in the global scope, which segfaults R on ++# load), and RcppParallelLibs() / CxxFlags() would hand that system TBB to ++# dependents such as rstan, putting NEEDED libtbb.so.12 back into their ++# binaries. Read the variables only when explicitly opted back in. ++bincraftGetenv <- function(name, unset = "") { ++ if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") == "TRUE") ++ Sys.getenv(name, unset = unset) ++ else ++ unset ++} +\ No newline at end of file +diff --git a/R/tbb.R b/R/tbb.R +index 152fd16..4b06aa5 100644 +--- a/R/tbb.R ++++ b/R/tbb.R +@@ -17,7 +17,7 @@ tbbLibraryPath <- function(name = NULL) { + sysname <- Sys.info()[["sysname"]] + + # find root for TBB install +- tbbRoot <- Sys.getenv("TBB_LIB", unset = tbbRoot()) ++ tbbRoot <- bincraftGetenv("TBB_LIB", unset = tbbRoot()) + if (is.null(name)) + return(tbbRoot) + +@@ -58,7 +58,7 @@ tbbCxxFlags <- function() { + flags <- c("-DRCPP_PARALLEL_USE_TBB=1") + + # if TBB_INC is set, apply those library paths +- tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC) ++ tbbInc <- bincraftGetenv("TBB_INC", unset = TBB_INC) + if (!file.exists(tbbInc)) { + tbbInc <- system.file("include", package = "RcppParallel") + } +@@ -96,7 +96,7 @@ tbbLdFlags <- function() { + } + + # shortcut if TBB_LIB defined +- tbbLib <- Sys.getenv("TBB_LINK_LIB", Sys.getenv("TBB_LIB", unset = TBB_LIB)) ++ tbbLib <- bincraftGetenv("TBB_LINK_LIB", bincraftGetenv("TBB_LIB", unset = TBB_LIB)) + if (nzchar(tbbLib)) { + if (R.version$os == "emscripten") { + fmt <- "-L%1$s -l%2$s" +diff --git a/src/install.libs.R b/src/install.libs.R +index e770838..1dd2fc7 100644 +--- a/src/install.libs.R ++++ b/src/install.libs.R +@@ -492,6 +492,18 @@ prependFlags <- function(prependFlags, toFlags) { + tbbLib <- Sys.getenv("TBB_LIB") + tbbInc <- Sys.getenv("TBB_INC") + ++# bincraft patch: the companion change in tools/config/configure.R stops an ++# ambient TBB_LIB / TBB_INC from selecting a system TBB, but this script is ++# also run directly by `R CMD INSTALL` (not only through the `tbb` rule in ++# src/Makevars, which passes the configured values), so at install time it ++# still sees the image's environment and would symlink the system libraries ++# into RcppParallel/lib. Drop them here for the same reason, under the same ++# opt-out. ++if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") != "TRUE") { ++ tbbLib <- "" ++ tbbInc <- "" ++} ++ + args <- commandArgs(trailingOnly = TRUE) + if (identical(args, "build")) { + if (nzchar(tbbLib) && nzchar(tbbInc)) { +diff --git a/tools/config/configure.R b/tools/config/configure.R +index c3842f9..adf7876 100644 +--- a/tools/config/configure.R ++++ b/tools/config/configure.R +@@ -66,6 +66,24 @@ tbbRoot <- Sys.getenv("TBB_ROOT", unset = NA) + tbbLib <- Sys.getenv("TBB_LIB", unset = NA) + tbbInc <- Sys.getenv("TBB_INC", unset = NA) + ++# bincraft patch: ignore an ambient TBB_ROOT / TBB_LIB / TBB_INC. Our build ++# images exported these until build-env-images c51ed09 (a leftover from ++# RcppParallel 5.x, whose bundled Intel TBB would not build on musl or with ++# modern g++), and any of them switches the branches below to a system TBB. ++# The published binary then records NEEDED libtbb.so.12 (or libtbb.so.2 for ++# the classic Intel TBB) and gets a RcppParallel/lib full of absolute symlinks ++# into the image's library dir, so it cannot dyn.load on a consumer machine ++# without that exact TBB. 6.x bundles oneTBB 2022 and builds it with cmake on ++# every platform we ship, so the bundled copy is always the right choice here; ++# forcing it in the package rather than relying on the image environment keeps ++# the binary correct whichever image version CI happens to pull. Set ++# BINCRAFT_ALLOW_SYSTEM_TBB=TRUE to restore the upstream behaviour. ++if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") != "TRUE") { ++ tbbRoot <- NA ++ tbbLib <- NA ++ tbbInc <- NA ++} ++ + tbbName <- Sys.getenv("TBB_NAME", unset = "tbb") + tbbMallocName <- Sys.getenv("TBB_MALLOC_NAME", unset = "tbbmalloc") + +@@ -146,6 +164,18 @@ define( + ) + + # set PKG_LIBS ++# ++# bincraft patch: the non-Windows library directories below are passed as ++# plain '-L', not '-Wl,-L'. gcc expands its own search dirs (/usr/lib64, ++# /usr/lib/) into explicit '-L' options ahead of anything forwarded ++# verbatim with '-Wl,', so with '-Wl,-L' a system libtbb.so wins over the one ++# named here: on a build host with a distro TBB installed, '-ltbb' resolves to ++# that library and RcppParallel.so records its SONAME (libtbb.so.12, or ++# libtbb.so.2 for the classic Intel TBB) instead of the bundled 'libtbb.so'. ++# The binary then loads the system TBB rather than the copy shipped in ++# RcppParallel/lib, and fails outright on a machine that has no system TBB. ++# gcc places a plain '-L' before its built-in dirs, so the intended library is ++# found first. + pkgLibs <- if (.Platform$OS.type == "windows") { + + if (!is.na(tbbLib) && file.exists(file.path(tbbInc, "oneapi"))) { +@@ -183,7 +213,7 @@ pkgLibs <- if (.Platform$OS.type == "windows") { + } else if (!is.na(tbbLib)) { + + c( +- "-Wl,-L\"$(TBB_LIB)\"", ++ "-L\"$(TBB_LIB)\"", + sprintf("-Wl,-rpath,%s", shQuote(tbbLib)), + "-l$(TBB_NAME)", + "-l$(TBB_MALLOC_NAME)" +@@ -192,14 +222,14 @@ pkgLibs <- if (.Platform$OS.type == "windows") { + } else if (R.version$os == "emscripten") { + + c( +- "-Wl,-Ltbb/build/lib_release", ++ "-Ltbb/build/lib_release", + "-l$(TBB_NAME)" + ) + + } else { + + c( +- "-Wl,-Ltbb/build/lib_release", ++ "-Ltbb/build/lib_release", + "-l$(TBB_NAME)", + "-l$(TBB_MALLOC_NAME)" + ) diff --git a/local/patches/RcppParallel/force-bundled-tbb.patch b/local/patches/RcppParallel/force-bundled-tbb-6.2.x.patch similarity index 67% rename from local/patches/RcppParallel/force-bundled-tbb.patch rename to local/patches/RcppParallel/force-bundled-tbb-6.2.x.patch index 5c37fa6..d88cfc5 100644 --- a/local/patches/RcppParallel/force-bundled-tbb.patch +++ b/local/patches/RcppParallel/force-bundled-tbb-6.2.x.patch @@ -1,5 +1,5 @@ diff --git a/R/aaa.R b/R/aaa.R -index 568a2aa..bfdab4c 100644 +index 568a2aa..2744059 100644 --- a/R/aaa.R +++ b/R/aaa.R @@ -5,4 +5,21 @@ TBB_LIB <- "" @@ -10,16 +10,16 @@ index 568a2aa..bfdab4c 100644 \ No newline at end of file +TBB_MALLOC_NAME <- "tbbmalloc" + -+# bincraft patch: our build images (and plenty of user environments) export -+# TBB_ROOT / TBB_LIB / TBB_INC. A binary we publish always carries its own -+# oneTBB in RcppParallel/lib -- see the companion changes in -+# tools/config/configure.R and src/install.libs.R -- so honouring those -+# variables at run time is actively harmful: .onLoad() would dyn.load() a -+# second, unrelated TBB into the process next to the bundled one (two copies -+# of the same symbols in the global scope, which segfaults R on load), and -+# RcppParallelLibs() / CxxFlags() would hand that system TBB to dependents -+# such as rstan, putting NEEDED libtbb.so.12 back into their binaries. Read -+# the variables only when explicitly opted back in. ++# bincraft patch: build images (ours did until build-env-images c51ed09) and ++# plenty of user environments export TBB_ROOT / TBB_LIB / TBB_INC. A binary we ++# publish always carries its own oneTBB in RcppParallel/lib -- see the ++# companion changes in tools/config/configure.R and src/install.libs.R -- so ++# honouring those variables at run time is actively harmful: .onLoad() would ++# dyn.load() a second, unrelated TBB into the process next to the bundled one ++# (two copies of the same symbols in the global scope, which segfaults R on ++# load), and RcppParallelLibs() / CxxFlags() would hand that system TBB to ++# dependents such as rstan, putting NEEDED libtbb.so.12 back into their ++# binaries. Read the variables only when explicitly opted back in. +bincraftGetenv <- function(name, unset = "") { + if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") == "TRUE") + Sys.getenv(name, unset = unset) @@ -28,32 +28,24 @@ index 568a2aa..bfdab4c 100644 +} \ No newline at end of file diff --git a/R/tbb.R b/R/tbb.R -index 6f6a745..e407986 100644 +index b071833..e3bf7a5 100644 --- a/R/tbb.R +++ b/R/tbb.R -@@ -17,7 +17,7 @@ tbbLibraryPath <- function(name = NULL) { - sysname <- Sys.info()[["sysname"]] - +@@ -19,3 +19,3 @@ tbbLibraryPath <- function(name = NULL) { # find root for TBB install - tbbRoot <- Sys.getenv("TBB_LIB", unset = tbbRoot()) + tbbRoot <- bincraftGetenv("TBB_LIB", unset = tbbRoot()) if (is.null(name)) - return(tbbRoot) - -@@ -58,3 +58,3 @@ tbbCxxFlags <- function() { +@@ -63,3 +63,3 @@ tbbCxxFlags <- function() { # if TBB_INC is set, apply those library paths - tbbInc <- Sys.getenv("TBB_INC", unset = TBB_INC) + tbbInc <- bincraftGetenv("TBB_INC", unset = TBB_INC) if (!file.exists(tbbInc)) { -@@ -117,7 +117,7 @@ tbbLdFlags <- function() { - } - +@@ -122,3 +122,3 @@ tbbLdFlags <- function() { # shortcut if TBB_LIB defined - tbbLib <- Sys.getenv("TBB_LINK_LIB", Sys.getenv("TBB_LIB", unset = TBB_LIB)) + tbbLib <- bincraftGetenv("TBB_LINK_LIB", bincraftGetenv("TBB_LIB", unset = TBB_LIB)) if (nzchar(tbbLib)) { - if (R.version$os == "emscripten") { - fmt <- "-L%1$s -l%2$s" diff --git a/src/install.libs.R b/src/install.libs.R index 3b3cfda..c0e6f3e 100644 --- a/src/install.libs.R @@ -78,24 +70,24 @@ index 3b3cfda..c0e6f3e 100644 if (identical(args, "build")) { if (nzchar(tbbLib) && nzchar(tbbInc)) { diff --git a/tools/config/configure.R b/tools/config/configure.R -index 6293fe1..eae4aaa 100644 +index c203a1f..0050b5c 100644 --- a/tools/config/configure.R +++ b/tools/config/configure.R -@@ -40,6 +40,24 @@ tbbRoot <- Sys.getenv("TBB_ROOT", unset = NA) +@@ -79,6 +79,24 @@ tbbRoot <- Sys.getenv("TBB_ROOT", unset = NA) tbbLib <- Sys.getenv("TBB_LIB", unset = NA) tbbInc <- Sys.getenv("TBB_INC", unset = NA) -+# bincraft patch: ignore an ambient TBB_ROOT / TBB_LIB / TBB_INC. Several of -+# our build images export these (a leftover from RcppParallel 5.x, whose -+# bundled Intel TBB would not build on musl or with modern g++), and any of -+# them switches the branches below to a system TBB. The published binary then -+# records NEEDED libtbb.so.12 (or libtbb.so.2 for the classic Intel TBB) and -+# gets a RcppParallel/lib full of absolute symlinks into the image's library -+# dir, so it cannot dyn.load on a consumer machine without that exact TBB. -+# 6.x bundles oneTBB 2022 and builds it with cmake on every platform we ship, -+# so the bundled copy is always the right choice here; forcing it in the -+# package rather than relying on the image environment keeps the binary -+# correct whichever image version CI happens to pull. Set ++# bincraft patch: ignore an ambient TBB_ROOT / TBB_LIB / TBB_INC. Our build ++# images exported these until build-env-images c51ed09 (a leftover from ++# RcppParallel 5.x, whose bundled Intel TBB would not build on musl or with ++# modern g++), and any of them switches the branches below to a system TBB. ++# The published binary then records NEEDED libtbb.so.12 (or libtbb.so.2 for ++# the classic Intel TBB) and gets a RcppParallel/lib full of absolute symlinks ++# into the image's library dir, so it cannot dyn.load on a consumer machine ++# without that exact TBB. 6.x bundles oneTBB 2022 and builds it with cmake on ++# every platform we ship, so the bundled copy is always the right choice here; ++# forcing it in the package rather than relying on the image environment keeps ++# the binary correct whichever image version CI happens to pull. Set +# BINCRAFT_ALLOW_SYSTEM_TBB=TRUE to restore the upstream behaviour. +if (Sys.getenv("BINCRAFT_ALLOW_SYSTEM_TBB", unset = "FALSE") != "TRUE") { + tbbRoot <- NA @@ -106,7 +98,7 @@ index 6293fe1..eae4aaa 100644 tbbName <- Sys.getenv("TBB_NAME", unset = "tbb") tbbMallocName <- Sys.getenv("TBB_MALLOC_NAME", unset = "tbbmalloc") -@@ -186,12 +204,23 @@ define( +@@ -225,12 +243,23 @@ define( ) # set PKG_LIBS @@ -131,7 +123,7 @@ index 6293fe1..eae4aaa 100644 if (.Platform$OS.type != "windows") sprintf("-Wl,-rpath,%s", shQuote(tbbLib)), "-l$(TBB_NAME)", -@@ -201,14 +230,14 @@ pkgLibs <- if (!is.na(tbbLib)) { +@@ -240,14 +269,14 @@ pkgLibs <- if (!is.na(tbbLib)) { } else if (R.version$os == "emscripten") { c( diff --git a/local/patches/registry.json b/local/patches/registry.json index 2457304..1f341b7 100644 --- a/local/patches/registry.json +++ b/local/patches/registry.json @@ -6,8 +6,48 @@ "env": {}, "configure_args": [], "makevars": {}, - "patch": "RcppParallel/force-bundled-tbb.patch", - "reason": "RcppParallel 6.x bundles oneTBB 2022 and builds it with cmake on every platform we ship, so the system-TBB workaround needed for 5.x is gone, but two things still steer the build back to a system TBB. (1) Ambient TBB_ROOT/TBB_LIB/TBB_INC: several build images still export these (build-env-images dropped them, but the images are rebuilt only by cron/manual runs, so a stale image keeps them), and R reads ~/.Renviron *after* the process environment, so no pipeline-side env override can undo it. configure.R then takes the system-TBB branch, install.libs.R symlinks the image's libraries into RcppParallel/lib as absolute paths, and the binary records NEEDED libtbb.so.12 (libtbb.so.2 for the classic Intel TBB on el8/el9) -- it cannot dyn.load on a consumer machine without that exact TBB. Both files are patched to ignore those variables (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE); install.libs.R needs it separately because R CMD INSTALL runs it outside the src/Makevars rule that passes the configured values. (2) Link order: the bundled branch passes its build dir as '-Wl,-Ltbb/build/lib_release', and gcc expands its own search dirs (/usr/lib64, /usr/lib/) into '-L' options ahead of anything forwarded with '-Wl,', so '-ltbb' would still resolve to a distro TBB when one is installed; a plain '-L' puts the bundled dir first. Verified on the current build-env-ubuntu:jammy image (which still exports TBB_INC/TBB_LIB): NEEDED libtbb.so, RUNPATH $ORIGIN/../lib, real libtbb.so.2 in RcppParallel/lib, and the package loads with every system libtbb moved away." + "patch": "RcppParallel/force-bundled-tbb-6.2.x.patch", + "reason": "RcppParallel 6.x builds its bundled oneTBB 2022 with cmake, but tools/config/configure.R passes the library dir as '-Wl,-L...', and gcc places its own search dirs (/usr/lib64, /usr/lib/) ahead of anything forwarded with '-Wl,'. Every build image installs a distro libtbb, so '-ltbb' resolves to it: the binary records NEEDED libtbb.so.12 (libtbb.so.2 on el8/el9) instead of the bundled libtbb.so and cannot load on a machine without that exact system TBB. The patch passes a plain '-L' so the bundled build dir wins. As a safeguard it also makes configure.R, src/install.libs.R and R/tbb.R ignore an ambient TBB_ROOT/TBB_LIB/TBB_INC (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE): the build images stopped exporting them in build-env-images c51ed09, but a stale image or ~/.Renviron would otherwise switch the build back to the system TBB, and R reads ~/.Renviron after the process environment, so no pipeline env can override it. The read sites move between releases, so each entry pins a patch generated against that version. Upstream still uses '-Wl,-L' in 6.2.1; drop these entries once a release passes a plain '-L'." + }, + { + "package": "RcppParallel", + "versions": "6.2.0", + "platforms": ["*"], + "env": {}, + "configure_args": [], + "makevars": {}, + "patch": "RcppParallel/force-bundled-tbb-6.2.x.patch", + "reason": "RcppParallel 6.x builds its bundled oneTBB 2022 with cmake, but tools/config/configure.R passes the library dir as '-Wl,-L...', and gcc places its own search dirs (/usr/lib64, /usr/lib/) ahead of anything forwarded with '-Wl,'. Every build image installs a distro libtbb, so '-ltbb' resolves to it: the binary records NEEDED libtbb.so.12 (libtbb.so.2 on el8/el9) instead of the bundled libtbb.so and cannot load on a machine without that exact system TBB. The patch passes a plain '-L' so the bundled build dir wins. As a safeguard it also makes configure.R, src/install.libs.R and R/tbb.R ignore an ambient TBB_ROOT/TBB_LIB/TBB_INC (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE): the build images stopped exporting them in build-env-images c51ed09, but a stale image or ~/.Renviron would otherwise switch the build back to the system TBB, and R reads ~/.Renviron after the process environment, so no pipeline env can override it. The read sites move between releases, so each entry pins a patch generated against that version. Upstream still uses '-Wl,-L' in 6.2.1; drop these entries once a release passes a plain '-L'." + }, + { + "package": "RcppParallel", + "versions": "6.1.1", + "platforms": ["*"], + "env": {}, + "configure_args": [], + "makevars": {}, + "patch": "RcppParallel/force-bundled-tbb-6.1.x.patch", + "reason": "RcppParallel 6.x builds its bundled oneTBB 2022 with cmake, but tools/config/configure.R passes the library dir as '-Wl,-L...', and gcc places its own search dirs (/usr/lib64, /usr/lib/) ahead of anything forwarded with '-Wl,'. Every build image installs a distro libtbb, so '-ltbb' resolves to it: the binary records NEEDED libtbb.so.12 (libtbb.so.2 on el8/el9) instead of the bundled libtbb.so and cannot load on a machine without that exact system TBB. The patch passes a plain '-L' so the bundled build dir wins. As a safeguard it also makes configure.R, src/install.libs.R and R/tbb.R ignore an ambient TBB_ROOT/TBB_LIB/TBB_INC (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE): the build images stopped exporting them in build-env-images c51ed09, but a stale image or ~/.Renviron would otherwise switch the build back to the system TBB, and R reads ~/.Renviron after the process environment, so no pipeline env can override it. The read sites move between releases, so each entry pins a patch generated against that version. Upstream still uses '-Wl,-L' in 6.2.1; drop these entries once a release passes a plain '-L'." + }, + { + "package": "RcppParallel", + "versions": "6.1.0", + "platforms": ["*"], + "env": {}, + "configure_args": [], + "makevars": {}, + "patch": "RcppParallel/force-bundled-tbb-6.1.x.patch", + "reason": "RcppParallel 6.x builds its bundled oneTBB 2022 with cmake, but tools/config/configure.R passes the library dir as '-Wl,-L...', and gcc places its own search dirs (/usr/lib64, /usr/lib/) ahead of anything forwarded with '-Wl,'. Every build image installs a distro libtbb, so '-ltbb' resolves to it: the binary records NEEDED libtbb.so.12 (libtbb.so.2 on el8/el9) instead of the bundled libtbb.so and cannot load on a machine without that exact system TBB. The patch passes a plain '-L' so the bundled build dir wins. As a safeguard it also makes configure.R, src/install.libs.R and R/tbb.R ignore an ambient TBB_ROOT/TBB_LIB/TBB_INC (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE): the build images stopped exporting them in build-env-images c51ed09, but a stale image or ~/.Renviron would otherwise switch the build back to the system TBB, and R reads ~/.Renviron after the process environment, so no pipeline env can override it. The read sites move between releases, so each entry pins a patch generated against that version. Upstream still uses '-Wl,-L' in 6.2.1; drop these entries once a release passes a plain '-L'." + }, + { + "package": "RcppParallel", + "versions": "6.0.0", + "platforms": ["*"], + "env": {}, + "configure_args": [], + "makevars": {}, + "patch": "RcppParallel/force-bundled-tbb-6.0.0.patch", + "reason": "RcppParallel 6.x builds its bundled oneTBB 2022 with cmake, but tools/config/configure.R passes the library dir as '-Wl,-L...', and gcc places its own search dirs (/usr/lib64, /usr/lib/) ahead of anything forwarded with '-Wl,'. Every build image installs a distro libtbb, so '-ltbb' resolves to it: the binary records NEEDED libtbb.so.12 (libtbb.so.2 on el8/el9) instead of the bundled libtbb.so and cannot load on a machine without that exact system TBB. The patch passes a plain '-L' so the bundled build dir wins. As a safeguard it also makes configure.R, src/install.libs.R and R/tbb.R ignore an ambient TBB_ROOT/TBB_LIB/TBB_INC (opt out with BINCRAFT_ALLOW_SYSTEM_TBB=TRUE): the build images stopped exporting them in build-env-images c51ed09, but a stale image or ~/.Renviron would otherwise switch the build back to the system TBB, and R reads ~/.Renviron after the process environment, so no pipeline env can override it. The read sites move between releases, so each entry pins a patch generated against that version. Upstream still uses '-Wl,-L' in 6.2.1; drop these entries once a release passes a plain '-L'." }, { "package": "fs", From 3426d5f59f28d1a91ef18115284f0eaa5c4de6e7 Mon Sep 17 00:00:00 2001 From: automation-bot Date: Sun, 11 Oct 2026 00:32:41 +0000 Subject: [PATCH 2/4] chore(deps): update dependency nbafrank/uvr to v0.4.7 --- local/uvr-install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/local/uvr-install.sh b/local/uvr-install.sh index ed6b1ce..e103e13 100755 --- a/local/uvr-install.sh +++ b/local/uvr-install.sh @@ -30,7 +30,7 @@ set -eu # renovate: datasource=github-releases depName=nbafrank/uvr -UVR_PIN="v0.4.6" +UVR_PIN="v0.4.7" if [ "$#" -eq 0 ]; then echo "usage: $0 ..." >&2 From d992a2b6361439966ffbc70088bacec7b664c78b Mon Sep 17 00:00:00 2001 From: pat-s Date: Sun, 11 Oct 2026 12:12:28 +0000 Subject: [PATCH 3/4] fix(ci): give each xvfb-run its own display (#230) Every `process-cran-updates-ubuntu-2204-arm64` cron run since pipeline 13744 has failed with `xvfb-run: error: Xvfb failed to start` (e.g. 13829). ## Cause The newer-R loop added in #216 runs two `xvfb-run` calls back to back: the R-minor-sensitive `process_cran_updates` pass, then `local/build-newer-r.R`. Without `-a`, `xvfb-run` always uses display `:99`, and on exit it kills its Xvfb without waiting for it. The second call can therefore start while the old server still holds the `:99` lock, so the new Xvfb refuses to start. Only ubuntu-2204-arm64 hits this because it is the only image with a second R minor installed, so the loop body only runs there. ## Change - Default `XVFB_ARGS` to `-a` (`--auto-servernum`) in `process-updates.yaml`, `build-all-versions.yaml` and `weekly-rebuild-missing.yaml`, so each call picks a free display. - The RHEL 10 `xwfb-run` branch still overrides `XVFB_ARGS` with `-c weston`, so it is unchanged. ## Verification `crow lint .crow/` passes. A local repro was not possible (`docker run` hangs on the dev host), so the next ubuntu-2204-arm64 cron run is the real check. Reviewed-on: https://git.devxy.io/devxy/build-cran-binaries/pulls/230 --- .crow/build-all-versions.yaml | 2 +- .crow/process-updates.yaml | 2 +- .crow/weekly-rebuild-missing.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.crow/build-all-versions.yaml b/.crow/build-all-versions.yaml index 7451988..ce3bc09 100644 --- a/.crow/build-all-versions.yaml +++ b/.crow/build-all-versions.yaml @@ -153,7 +153,7 @@ steps: # not visible here. Install the packages needed to recompute the snapshot # and query build metadata in every build job. - UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres s3fs data.table future jsonlite - - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS=""; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi + - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS="-a"; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi - $XVFB $XVFB_ARGS -n $SPLIT_INDEX -- /opt/R/$R_VERSION/bin/Rscript local/build-all.R $SPLIT_INTO $SPLIT_INDEX $NCPUS 2>&1 - | PRIMARY_MINOR=$(echo "$R_VERSION" | cut -d. -f1-2) diff --git a/.crow/process-updates.yaml b/.crow/process-updates.yaml index a1b9698..531a47f 100644 --- a/.crow/process-updates.yaml +++ b/.crow/process-updates.yaml @@ -192,7 +192,7 @@ steps: - UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh RPostgres - /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")' # rhel-10 ships xwfb-run (Xwayland) instead of xvfb-run; prefer it and start weston, else fall back to xvfb-run - - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS=""; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi + - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS="-a"; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi # options(future.globals.onReference = NULL): for some reason s3fs::file_delete() throws 'Error: Detected a non-exportable reference ('externalptr') in one of the globals ('FUN' of class 'function') used in the future expression' otherwise - $XVFB $XVFB_ARGS -- /opt/R/$R_VERSION/bin/R -q -e "options(crayon.enabled = TRUE, Ncpus = 4, future.globals.onReference = 'error', repos = structure(c(getOption('repos'),INLA='https://inla.r-inla-download.org/R/stable'))); progressr::handlers('cli'); progressr::handlers(global = TRUE); options(future.globals.onReference = NULL); bincraft::process_cran_updates(interval = $INTERVAL, platform = '${OS}', process_updated = TRUE, process_new = ${PROCESS_NEW}, process_removed = TRUE, patches = 'local/patches', r_minor_detection = 'classifier',s3_endpoint = 'https://s3.eu-central-003.backblazeb2.com', s3_region = 'eu-central-003', s3_bucket = 'devxy-rpkgs-binaries', s3_access_key_id = Sys.getenv('B2_S3_ACCESS_KEY'), s3_secret_access_key = Sys.getenv('B2_S3_SECRET_KEY'), metadata_db_host = 'r-binaries.devxy.io', metadata_db_name = 'build_metadata', metadata_db_table = 'single_builds', metadata_db_user = 'rpkgs', metadata_db_password = Sys.getenv('PGPASS'), metadata_db_sslmode = 'require', metadata_db_port = 15432, archive = TRUE, upload = TRUE, store_build_metadata = TRUE)" - | diff --git a/.crow/weekly-rebuild-missing.yaml b/.crow/weekly-rebuild-missing.yaml index 955476e..a93a7bd 100644 --- a/.crow/weekly-rebuild-missing.yaml +++ b/.crow/weekly-rebuild-missing.yaml @@ -388,7 +388,7 @@ steps: - rm -rf /mnt/cache/R-pkgs/00LOCK-* - /opt/R/$R_VERSION/bin/Rscript local/install-bincraft.R - /opt/R/$R_VERSION/bin/R -q -e 'packageVersion("bincraft")' - - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS=""; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi + - XVFB=$(command -v xwfb-run 2>/dev/null || command -v xvfb-run); XVFB_ARGS="-a"; if command -v xwfb-run >/dev/null 2>&1; then dnf install -y -q weston 2>/dev/null; XVFB_ARGS="-c weston"; fi - UVR_R_BIN=/opt/R/$R_VERSION/bin/R local/uvr-install.sh httr2 - /opt/R/$R_VERSION/bin/R -q -e 'source("local/fetch-rebuild-packages-from-issue.R")' - $XVFB $XVFB_ARGS -n $SPLIT_INDEX -- /opt/R/$R_VERSION/bin/Rscript local/rebuild-missing.R $SPLIT_INTO $SPLIT_INDEX $REBUILD_BUDGET_HOURS 2>&1 From 5dad51c76a1136c003853bb6c84fbef9dc798e4d Mon Sep 17 00:00:00 2001 From: automation-bot Date: Mon, 12 Oct 2026 00:32:11 +0000 Subject: [PATCH 4/4] chore(deps): update pre-commit hook rbubley/mirrors-prettier to v3.9.10 --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dec6844..e0ba9a9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -28,7 +28,7 @@ repos: hooks: - id: markdownlint-cli2 - repo: https://github.com/rbubley/mirrors-prettier - rev: v3.9.9 + rev: v3.9.10 hooks: - id: prettier - repo: https://github.com/posit-dev/air-pre-commit