Skip to content

Commit 9df8885

Browse files
committed
re-export tbbmalloc from RcppParallel.dll on windows
downstream packages on windows link with '-lRcppParallel' alone, and so can only use tbb symbols that RcppParallel.dll exports. the tbb runtime symbols come along implicitly -- RcppParallel references them, so those archive members are linked in and re-exported via their '-export:' directives -- but nothing references the tbbmalloc entry points, so packages using the scalable allocator (e.g. via RcppArmadillo's ARMA_USE_TBB_ALLOC) fail to link with undefined references to scalable_malloc and scalable_free. link tbbmalloc with --whole-archive so its objects are always included and re-exported. tbbmalloc must precede tbb on the link line: both archives bundle an itt_notify object defining the same symbols, and with tbbmalloc's copy already linked, tbb's is never pulled in. older (non-oneTBB) toolchains like rtools42 keep the plain link: there, tbb and tbbmalloc both define DllMain and so cannot be linked wholesale, and their objects carry no '-export:' directives to re-export anyhow.
1 parent d637cbe commit 9df8885

2 files changed

Lines changed: 43 additions & 7 deletions

File tree

NEWS.md

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

3+
* Fixed linking of downstream packages using the TBB scalable allocator
4+
on Windows, e.g. via RcppArmadillo's `ARMA_USE_TBB_ALLOC`. RcppParallel
5+
now links the whole Rtools `tbbmalloc` archive into `RcppParallel.dll`
6+
and re-exports its API, so that `scalable_malloc`, `scalable_free`, and
7+
friends can be resolved by packages linking with `-lRcppParallel`.
8+
39
* Fixed installation on Windows toolchains providing an older (non-oneTBB)
410
copy of TBB, e.g. Rtools42: the tbb stub library is now built by
511
re-exporting the static TBB library, rather than wrapping the oneTBB

tools/config/configure.R

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,49 @@ define(
224224
)
225225

226226
# set PKG_LIBS
227-
pkgLibs <- if (!is.na(tbbLib)) {
228-
227+
pkgLibs <- if (.Platform$OS.type == "windows") {
228+
229+
if (!is.na(tbbLib) && file.exists(file.path(tbbInc, "oneapi"))) {
230+
231+
# downstream packages link with '-lRcppParallel' alone, so
232+
# RcppParallel.dll must provide the tbbmalloc API (scalable_malloc
233+
# and friends) even though RcppParallel itself never calls it; use
234+
# --whole-archive so those objects are linked in, and re-exported
235+
# via their '-export:' directives. tbbmalloc must precede tbb here:
236+
# both archives bundle an itt_notify object defining the same
237+
# symbols, and with tbbmalloc's copy already linked, tbb's is never
238+
# pulled in, avoiding duplicate definition errors
239+
c(
240+
"-Wl,-L\"$(TBB_LIB)\"",
241+
"-Wl,--whole-archive",
242+
"-l$(TBB_MALLOC_NAME)",
243+
"-Wl,--no-whole-archive",
244+
"-l$(TBB_NAME)"
245+
)
246+
247+
} else if (!is.na(tbbLib)) {
248+
249+
# with an older (non-oneTBB) toolchain like Rtools42, tbb and
250+
# tbbmalloc both define DllMain, so tbbmalloc cannot be linked
251+
# wholesale; its objects also carry no '-export:' directives, so
252+
# nothing would be re-exported anyhow -- just link as needed
253+
c(
254+
"-Wl,-L\"$(TBB_LIB)\"",
255+
"-l$(TBB_NAME)",
256+
"-l$(TBB_MALLOC_NAME)"
257+
)
258+
259+
}
260+
261+
} else if (!is.na(tbbLib)) {
262+
229263
c(
230264
"-Wl,-L\"$(TBB_LIB)\"",
231265
sprintf("-Wl,-rpath,%s", shQuote(tbbLib)),
232266
"-l$(TBB_NAME)",
233267
"-l$(TBB_MALLOC_NAME)"
234268
)
235-
236-
} else if (.Platform$OS.type == "windows") {
237-
238-
NULL
239-
269+
240270
} else if (R.version$os == "emscripten") {
241271

242272
c(

0 commit comments

Comments
 (0)