Skip to content

ship versioned tbb libraries on linux again#260

Merged
kevinushey merged 5 commits into
masterfrom
fix/linux-versioned-tbb-libs
Jul 24, 2026
Merged

ship versioned tbb libraries on linux again#260
kevinushey merged 5 commits into
masterfrom
fix/linux-versioned-tbb-libs

Conversation

@kevinushey

Copy link
Copy Markdown
Contributor

Problem

On Linux, RcppParallel 6.0.x installs unversioned TBB libraries — libtbb.so with SONAME libtbb.so, and no libtbb.so.2. This is a regression from 5.1.11 and earlier, which shipped a real libtbb.so.2 plus a libtbb.so redirect.

The cause is the oneTBB cmake build: it only versions its output under if (WIN32) (OUTPUT_NAME "tbb${TBB_BINARY_VERSION}") and sets no SOVERSION, so Linux/macOS get the bare target name. 5.1.11's versioned layout was never something RcppParallel did explicitly — it came from Intel TBB's make-based build (build/linux.inc set the SONAME suffix from TBB_COMPATIBLE_INTERFACE_VERSION, i.e. 2, and Makefile.tbb emitted libtbb.so as an INPUT(libtbb.so.2) linker script).

Binaries compiled against RcppParallel ≤ 5.1.11 recorded a load-time dependency on libtbb.so.2. After an upgrade to 6.0.x that file no longer exists, so they fail to load:

unable to load shared object '.../foo.so':
  libtbb.so.2: cannot open shared object file: No such file or directory

This was reported by the CRAN maintainer during revdep checking on Fedora.

Fix

For the bundled TBB on Linux only, after copying the libraries, rename each real unversioned libtbb*.so to libtbb*.so.2 and re-create libtbb*.so as a relative symlink pointing back at it. This restores the historical layout so legacy NEEDED libtbb.so.2 dependencies resolve again.

  • Scoped to the bundled build; the external/system-TBB path is untouched (that library keeps its own SONAME and lives on a stable system path).
  • Idempotent: skips symlinks/linker scripts and any already-versioned file.
  • A symlink, not a linker script: a linker script (INPUT(...)) works at link time but the dynamic loader can't parse it, so it would fail at runtime — and 6.0.x's RcppParallel.so itself has NEEDED libtbb.so.

Verification

Rebuilt into a temporary library on Linux:

  • Resulting layout is libtbb.so.2 (real) + libtbb.so -> libtbb.so.2 for tbb, tbbmalloc, and tbbmalloc_proxy.
  • Package loads; setThreadOptions() works; tbbLibraryPath("tbb") returns the .so.2.
  • RcppParallel.so's own NEEDED libtbb.so resolves via the new symlink.
  • A synthesized binary with a genuine NEEDED libtbb.so.2 (mimicking a 5.1.11-built revdep) now resolves the file against the new install — the load error is gone.

Note

Giving the new-ABI oneTBB the legacy .so.2 name means an old binary now loads it and could fault on a removed symbol rather than getting a clean file-not-found; that is what the existing compatibility headers/symbols are for, and a rebuild remains the real fix. This change restores pre-6.0 behavior and stops the file-level breakage.

The oneTBB cmake build only versions its output on Windows, so on Linux
RcppParallel 6.0.x installed unversioned libraries (e.g. 'libtbb.so' with
SONAME 'libtbb.so'). RcppParallel 5.1.11 and earlier shipped a real
'libtbb.so.2' plus a 'libtbb.so' redirect, inherited from Intel TBB's
make-based build (which set the SONAME from TBB_COMPATIBLE_INTERFACE_VERSION).

Binaries compiled against those releases recorded a load-time dependency on
'libtbb.so.2', and so fail to load after an upgrade with "libtbb.so.2: cannot
open shared object file". Restore the versioned layout for the bundled TBB on
Linux by renaming 'libtbb*.so' to 'libtbb*.so.2' and re-creating 'libtbb*.so'
as a symlink. A symlink (rather than a linker script) is used so the name
resolves at runtime as well as at link time.
@kevinushey
kevinushey merged commit 77684de into master Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant