@@ -167,39 +167,73 @@ versionBundledTbbLibraries <- function(tbbDest) {
167167 suffix <- " 2"
168168
169169 libs <- list.files(tbbDest , pattern = " ^libtbb.*\\ .so$" , full.names = TRUE )
170- for (lib in libs ) {
171-
172- # leave symlinks and linker scripts (i.e. an already-versioned layout)
173- # untouched; only real, unversioned libraries need renaming
174- if (nzchar(Sys.readlink(lib )))
175- next
176-
177- versioned <- paste0(lib , " ." , suffix )
178- if (file.exists(versioned ))
179- next
180-
181- fmt <- " ** versioning tbb library '%s' -> '%s'"
182- msg <- sprintf(fmt , basename(lib ), basename(versioned ))
183- writeLines(msg )
184-
185- # 'libtbb.so' -> 'libtbb.so.2', then re-create 'libtbb.so' as a
186- # relative symlink pointing back at the versioned library
187- file.rename(lib , versioned )
188- linked <- tryCatch(
189- file.symlink(basename(versioned ), lib ),
190- warning = function (w ) FALSE
191- )
170+ for (lib in libs )
171+ versionBundledTbbLibrary(lib , paste0(lib , " ." , suffix ))
192172
193- # if the symlink couldn't be created (e.g. a filesystem without symlink
194- # support), fall back to a plain copy so that 'libtbb.so' still exists --
195- # RcppParallel's own shared object records a load-time dependency on it
196- if (! isTRUE(linked )) {
197- writeLines(" ** could not create symlink; copying instead" )
198- file.copy(versioned , lib , overwrite = TRUE )
199- }
173+ }
200174
175+ # Version a single bundled TBB library. Failing to produce the versioned
176+ # layout is an error: a partial or silently-skipped layout would only
177+ # resurface later as load failures in downstream binaries, so fail the
178+ # install loudly instead.
179+ versionBundledTbbLibrary <- function (lib , versioned ) {
180+
181+ # leave symlinks (i.e. an already-versioned layout) untouched; only real,
182+ # unversioned libraries need renaming
183+ if (nzchar(Sys.readlink(lib )))
184+ return (invisible (FALSE ))
185+
186+ # only version actual ELF libraries; this leaves linker scripts alone
187+ # (in old-style layouts, 'libtbb.so' is an INPUT() script and the real
188+ # library already sits at 'libtbb.so.2'), while still replacing a stale
189+ # 'libtbb.so.2' left behind by a previous installation
190+ if (! isElfFile(lib ))
191+ return (invisible (FALSE ))
192+
193+ fmt <- " ** versioning tbb library '%s' -> '%s'"
194+ msg <- sprintf(fmt , basename(lib ), basename(versioned ))
195+ writeLines(msg )
196+
197+ # 'libtbb.so' -> 'libtbb.so.2'
198+ if (! isTRUE(file.rename(lib , versioned ))) {
199+ fmt <- " couldn't rename '%s' to '%s'"
200+ stop(sprintf(fmt , lib , versioned ))
201201 }
202202
203+ # re-create 'libtbb.so' as a relative symlink pointing back at the
204+ # versioned library
205+ linked <- tryCatch(
206+ file.symlink(basename(versioned ), lib ),
207+ warning = function (w ) FALSE
208+ )
209+ if (isTRUE(linked ))
210+ return (invisible (TRUE ))
211+
212+ # if the symlink couldn't be created (e.g. a filesystem without symlink
213+ # support), fall back to a plain copy so that 'libtbb.so' still exists.
214+ # the library has already been renamed at this point, so a failed copy
215+ # would leave no 'libtbb.so' at all; fail loudly rather than complete a
216+ # broken install
217+ writeLines(" ** couldn't create symlink; copying instead" )
218+ copied <- tryCatch(
219+ file.copy(versioned , lib , overwrite = TRUE ),
220+ warning = function (w ) FALSE
221+ )
222+ if (! isTRUE(copied )) {
223+ fmt <- " couldn't copy '%s' to '%s'"
224+ stop(sprintf(fmt , versioned , lib ))
225+ }
226+
227+ invisible (TRUE )
228+
229+ }
230+
231+ isElfFile <- function (path ) {
232+ header <- tryCatch(
233+ readBin(path , " raw" , n = 4L ),
234+ condition = function (cnd ) raw()
235+ )
236+ identical(header , charToRaw(" \x 7fELF" ))
203237}
204238
205239# Report which TBB libraries are about to be installed, and from where.
0 commit comments