Skip to content

Commit 7afa849

Browse files
committed
emit an -rpath for tbb in LdFlags() on macos
The TBB libraries RcppParallel ships on macOS record an '@rpath'-relative install name, but LdFlags() emitted only a '-L' search path. That satisfies the linker, so downstream packages built fine, but the resulting binary carried no LC_RPATH at all: dyld could resolve '@rpath/libtbb.dylib' only when RcppParallel -- and hence TBB -- had already been loaded into the process. Loading such a binary on its own failed with "Library not loaded: @rpath/libtbb.dylib". Pair the '-L' with a matching '-rpath', as the TBB_LIB branch just above already does. A stale rpath (e.g. in a binary package built where RcppParallel lived at a different path) is harmless: dyld skips a path that does not resolve and falls back to matching the already-loaded image, which is the current behaviour. Fixes #209.
1 parent 39afcb3 commit 7afa849

3 files changed

Lines changed: 49 additions & 1 deletion

File tree

NEWS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# RcppParallel (development version)
22

3+
* On macOS, `RcppParallel::LdFlags()` now also emits an `-rpath` entry for the
4+
directory containing the TBB libraries. The libraries record an
5+
`@rpath`-relative install name, so packages linking against them previously
6+
produced binaries with no runtime search path for TBB; those binaries could
7+
only be loaded when RcppParallel (and hence TBB) already happened to be
8+
loaded into the process, and failed with "Library not loaded:
9+
@rpath/libtbb.dylib" otherwise. (#209)
10+
311
* Fixed an issue where compiling code including `tbb/parallel_for_each.h`
412
could fail with toolchains that accept `-std=c++20` but provide a
513
pre-C++20 standard library, with errors of the form "no member named

R/tbb.R

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,15 @@ tbbLdFlags <- function() {
108108

109109
# explicitly link on macOS
110110
# https://github.com/RcppCore/RcppParallel/issues/206
111+
#
112+
# the bundled libraries record an '@rpath'-relative install name (e.g.
113+
# '@rpath/libtbb.dylib'), so '-L' alone is not enough: the client library
114+
# ends up with no runtime search path for TBB at all, and only loads
115+
# because RcppParallel -- and hence TBB -- normally happens to be loaded
116+
# into the process first. Emit a matching '-rpath' so the client can
117+
# resolve TBB on its own. (#209)
111118
if (is_mac()) {
112-
fmt <- "-L%s -l%s -l%s"
119+
fmt <- "-L%1$s -Wl,-rpath,%1$s -l%2$s -l%3$s"
113120
return(sprintf(fmt, asBuildPath(tbbLibraryPath()), TBB_NAME, TBB_MALLOC_NAME))
114121
}
115122

tests/test-ld-flags.R

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Unit tests for tbbLdFlags(), the linker flags handed to downstream packages
2+
# via RcppParallel::LdFlags().
3+
#
4+
# On macOS, the TBB libraries RcppParallel ships record an '@rpath'-relative
5+
# install name (e.g. '@rpath/libtbb.dylib'), so a '-L' search path alone only
6+
# satisfies the linker: the resulting binary carries no runtime search path for
7+
# TBB, and dyld can resolve it only when RcppParallel has already pulled TBB
8+
# into the process. Every '-L' we emit must therefore be paired with a matching
9+
# '-rpath'. (#209)
10+
11+
RcppParallel:::test_init()
12+
13+
flags <- tbbLdFlags()
14+
15+
assert(is.character(flags))
16+
assert(length(flags) == 1L)
17+
assert(!is.na(flags))
18+
19+
if (is_mac()) {
20+
21+
parts <- strsplit(flags, "\\s+")[[1L]]
22+
23+
libPaths <- sub("^-L", "", grep("^-L", parts, value = TRUE))
24+
rpaths <- sub("^-Wl,-rpath,", "", grep("^-Wl,-rpath,", parts, value = TRUE))
25+
26+
# we always link TBB explicitly on macOS, so there is a search path to check
27+
assert(length(libPaths) > 0L)
28+
assert(all(nzchar(libPaths)))
29+
30+
# and each one must also be searched at load time
31+
assert(all(libPaths %in% rpaths))
32+
33+
}

0 commit comments

Comments
 (0)