fix(patches): replace the RcppParallel system-TBB patch with a link-order fix #145

Merged
pat-s merged 1 commit from t3code/fix-uvr-glibc-build-failures into main 2026-07-31 06:41:47 +00:00
Owner

Why

Every build logs:

! Patch for RcppParallel 6.2.0 did not apply cleanly; skipping patched build.

RcppParallel 6.x rewrote its build system. src/Makevars.in no longer contains the USE_TBB=Linux block that system-tbb.patch edited (it is now a short @VAR@ template driven by tools/config/configure.R), so the patch can never apply again.

The workaround it implemented is obsolete too. 6.x bundles oneTBB 2022 and builds it with cmake, which works on musl and with g++ 8-15, so the 5.x reason for linking a system TBB is gone. Linking one is now harmful: install.libs.R symlinks the system libraries into RcppParallel/lib, so the published binary depends on a TBB the consumer does not have — the same failure mode as fs and libuv.

What is still broken upstream is the link order. configure.R names the TBB directory with -Wl,-L, and gcc expands its own search dirs into -L options ahead of anything forwarded verbatim with -Wl,:

$ gcc -v -o t t.c -Wl,-L/usr/local/lib64 -ltbb
-L/usr/lib/gcc/x86_64-redhat-linux/8  -L/lib/../lib64  -L/usr/lib/../lib64  ...  -L/usr/local/lib64

So on any 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 on el8/el9) instead of the bundled libtbb.so.

Changes

  • Replace RcppParallel/system-tbb.patch with RcppParallel/bundled-tbb-link-order.patch, which changes the three -Wl,-L occurrences in tools/config/configure.R to plain -L.
  • Scope the RcppParallel entry to >=6.0.0 and widen platforms to *.
  • Drop the rstan entry: its -DTBB_INTERFACE_NEW is already emitted by RcppParallel::CxxFlags() once the bundled oneTBB is used, and its -I/usr/local/include was an el8/el9 path applied on every platform.
  • .pre-commit-config.yaml: exclude local/patches/*.patch from trailing-whitespace, end-of-file-fixer and editorconfig-checker. They rewrite blank context lines ( -> ``) in every diff in the registry; git apply happens to tolerate it today, but a patch with meaningful trailing whitespace would be silently corrupted. The excludes are per-hook so validate patch registry still runs.
  • README: the RcppParallel example described the 5.x problem.

Verification

Built in the published images:

image NEEDED RPATH loads with system libtbb removed
build-env-alpine:3.24 libtbb.so $ORIGIN/../lib yes
build-env-redhat:8 libtbb.so, libtbbmalloc.so $ORIGIN/../lib yes
build-env-ubuntu:noble libtbb.so $ORIGIN/../lib yes

Without the patch the same builds record libtbb.so.12 (alpine, ubuntu) or libtbb.so.2 (el8, the classic 2018 TBB) and fall back to the system library at load time.

rstan 2.32.7 compiles and loads against the patched RcppParallel on ubuntu noble with no makevars override and with the system libtbb moved away. On el8 it also compiles; loading it there is blocked by an unrelated image bug (see below).

Behaviour change

Requires the paired build-env-images PR (drops TBB_INC/TBB_LIB) and an image rebuild — with those env vars set, configure still takes the system-TBB branch. After that, RcppParallel binaries ship their own oneTBB and are self-contained.

Also found, fixed in the paired images PR

  • The uvr lock failed ... GLIBC_2.29 not found errors in the same log are the -gnu uvr artifact on el8's glibc 2.28; fixed in build-env-images.
  • build-env-redhat:8 R 4.5.3/4.6.0 could not load stats (libRlapack.so: undefined symbol: dgemmtr_), which is why rstan compiled but would not load there. The el8 R RPM symlinks libRblas.so to openblas 0.3.15, which predates that symbol; the images PR repoints it at the reference BLAS R ships. With all three fixes, rstan 2.32.7 builds and loads on el8.
## Why Every build logs: ``` ! Patch for RcppParallel 6.2.0 did not apply cleanly; skipping patched build. ``` RcppParallel 6.x rewrote its build system. `src/Makevars.in` no longer contains the `USE_TBB=Linux` block that `system-tbb.patch` edited (it is now a short `@VAR@` template driven by `tools/config/configure.R`), so the patch can never apply again. The workaround it implemented is obsolete too. 6.x bundles **oneTBB 2022** and builds it with cmake, which works on musl and with g++ 8-15, so the 5.x reason for linking a system TBB is gone. Linking one is now harmful: `install.libs.R` symlinks the system libraries into `RcppParallel/lib`, so the published binary depends on a TBB the consumer does not have — the same failure mode as `fs` and libuv. What is still broken upstream is the **link order**. `configure.R` names the TBB directory with `-Wl,-L`, and gcc expands its own search dirs into `-L` options ahead of anything forwarded verbatim with `-Wl,`: ``` $ gcc -v -o t t.c -Wl,-L/usr/local/lib64 -ltbb -L/usr/lib/gcc/x86_64-redhat-linux/8 -L/lib/../lib64 -L/usr/lib/../lib64 ... -L/usr/local/lib64 ``` So on any 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 on el8/el9) instead of the bundled `libtbb.so`. ## Changes - Replace `RcppParallel/system-tbb.patch` with `RcppParallel/bundled-tbb-link-order.patch`, which changes the three `-Wl,-L` occurrences in `tools/config/configure.R` to plain `-L`. - Scope the RcppParallel entry to `>=6.0.0` and widen `platforms` to `*`. - Drop the `rstan` entry: its `-DTBB_INTERFACE_NEW` is already emitted by `RcppParallel::CxxFlags()` once the bundled oneTBB is used, and its `-I/usr/local/include` was an el8/el9 path applied on every platform. - `.pre-commit-config.yaml`: exclude `local/patches/*.patch` from `trailing-whitespace`, `end-of-file-fixer` and `editorconfig-checker`. They rewrite blank context lines (` ` -> ``) in every diff in the registry; `git apply` happens to tolerate it today, but a patch with meaningful trailing whitespace would be silently corrupted. The excludes are per-hook so `validate patch registry` still runs. - README: the RcppParallel example described the 5.x problem. ## Verification Built in the published images: | image | NEEDED | RPATH | loads with system libtbb removed | | --- | --- | --- | --- | | `build-env-alpine:3.24` | `libtbb.so` | `$ORIGIN/../lib` | yes | | `build-env-redhat:8` | `libtbb.so`, `libtbbmalloc.so` | `$ORIGIN/../lib` | yes | | `build-env-ubuntu:noble` | `libtbb.so` | `$ORIGIN/../lib` | yes | Without the patch the same builds record `libtbb.so.12` (alpine, ubuntu) or `libtbb.so.2` (el8, the classic 2018 TBB) and fall back to the system library at load time. rstan 2.32.7 compiles and loads against the patched RcppParallel on ubuntu noble with no makevars override and with the system libtbb moved away. On el8 it also compiles; loading it there is blocked by an unrelated image bug (see below). ## Behaviour change Requires the paired build-env-images PR (drops `TBB_INC`/`TBB_LIB`) and an image rebuild — with those env vars set, configure still takes the system-TBB branch. After that, RcppParallel binaries ship their own oneTBB and are self-contained. ## Also found, fixed in the paired images PR - The `uvr lock failed ... GLIBC_2.29 not found` errors in the same log are the `-gnu` uvr artifact on el8's glibc 2.28; fixed in build-env-images. - `build-env-redhat:8` R 4.5.3/4.6.0 could not load `stats` (`libRlapack.so: undefined symbol: dgemmtr_`), which is why rstan compiled but would not load there. The el8 R RPM symlinks `libRblas.so` to openblas 0.3.15, which predates that symbol; the images PR repoints it at the reference BLAS R ships. With all three fixes, rstan 2.32.7 builds and loads on el8.
RcppParallel 6.x rewrote its build: src/Makevars.in no longer has the
`USE_TBB=Linux` block the registry patch edited, so the patch could never
apply and every build logged "Patch for RcppParallel did not apply cleanly".

The workaround it implemented is also obsolete. 6.x bundles oneTBB 2022 and
builds it with cmake, which works on musl and with g++ 8-15, so there is no
longer a reason to link a system TBB -- and linking one publishes a binary
that needs a TBB the consumer does not have.

What is still broken upstream is the link order. configure.R names the TBB
directory with `-Wl,-L`, and gcc expands its own search dirs into `-L` options
ahead of anything forwarded verbatim with `-Wl,`, so on a build host with a
distro TBB installed `-ltbb` resolves to that library and RcppParallel.so
records its SONAME instead of the bundled `libtbb.so`. The new patch passes a
plain `-L` instead.

Verified on alpine 3.24, redhat 8 and ubuntu noble: RcppParallel gets NEEDED
libtbb.so with RPATH $ORIGIN/../lib and loads with every system libtbb moved
away, and rstan 2.32.7 compiles and loads against it with no makevars override
-- RcppParallel::CxxFlags() already emits -DTBB_INTERFACE_NEW -- so the rstan
entry is dropped too.

Summary:

- replace RcppParallel/system-tbb.patch with bundled-tbb-link-order.patch
- scope the RcppParallel entry to >=6.0.0 and widen its platforms to "*"
- drop the rstan entry, made redundant by the bundled oneTBB
- exclude local/patches/*.patch from the whitespace-mutating hooks, which
  rewrote context lines in every diff
pat-s merged commit 98371fb9c5 into main 2026-07-31 06:41:47 +00:00
pat-s deleted branch t3code/fix-uvr-glibc-build-failures 2026-07-31 06:41:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
devxy/build-cran-binaries!145
No description provided.