[R-pkg-devel] Compile issues on r-devel-linux-x86_64-debian-clang with OpenMP

Dirk Eddelbuettel edd @end|ng |rom deb|@n@org
Thu May 23 21:47:44 CEST 2024


On 23 May 2024 at 20:02, Ivan Krylov wrote:
| On Wed, 22 May 2024 09:18:13 -0500
| Dirk Eddelbuettel <edd using debian.org> wrote:
| 
| > Testing via 'nm' as you show is possible but not exactly 'portable'.
| > So any suggestions as to what to condition on here?
| 
| (My apologies if you already got an answer from Kurt. I think we're not
| seeing his mails to the list.)
| 
| Perhaps take the configure test a bit further and try to dyn.load() the
| resulting shared object? To be extra sure, call the function that uses
| the OpenMP features? (Some weird systems may have lazy binding enabled,
| making dyn.load() succeed but crashing the process on invocation of a
| missing function.)
| 
| On GNU/Linux, the linker will happily leave undefined symbols in when
| creating a shared library (unlike on, say, Windows, where extern void
| foo(void); foo(); is a link-time error unless an object file or an
| import library providing foo() is also present). When loading such a
| library, the operation fails unless the missing symbols are already
| present in the address space of the process (e.g. from a different
| shared library).
| 
| A fresh process of R built without OpenMP support will neither link in
| the OpenMP runtime while running SHLIB nor have the OpenMP runtime
| loaded and so should successfully fail the test.
| 
| I also wouldn't call the entry point "main" just in case some future
| compiler considers this a violation of the rules™ [*] and breaks the
| code. extern "C" void configtest(int*) would be compatible with .C()
| without having to talk to R's memory manager:
| 
| # The configure script:
| cat > test-omp.cpp <<EOF
| #include <omp.h>
| extern "C" void configtest(int * arg) {
|   *arg = omp_get_num_threads();
| }
| EOF
| # Without the following you're relying on the GNU/Linux-like behaviour
| # w.r.t. undefined symbols (see WRE 1.2.1.1):
| cat > Makevars <<EOF
| PKG_CXXFLAGS = \$(SHLIB_OPENMP_CXXFLAGS)
| PKG_LIBS = \$(SHLIB_OPENMP_CXXFLAGS)
| EOF
| R CMD SHLIB test-omp.cpp
| 
| # And then in R:
| dyn.load(paste0("test-omp", .Platform$dynlib.ext))
| # There's probably no need to test the return value, right?
| .C("configtest", arg = integer(1))$arg

Given that comes from RcppArmadillo we can rely on Rcpp::cppFunction() or
Rcpp::sourceCpp() which should make that dance a little simpler.

I had forgotten this was in fact a home-grown shell snippet (per `git blame`
last polished by Kevin, now CC'ed, in 2020).  That should make an explicit
load -- and noticing when we fail to load -- feasible.

Maybe someone has time and appetite for contributing a PR?

Cheers, Dirk

| -- 
| Best regards,
| Ivan
| 
| [*]
| In C++, main() is the function-that-must-not-be-named:
| https://en.cppreference.com/w/cpp/language/main_function

-- 
dirk.eddelbuettel.com | @eddelbuettel | edd using debian.org



More information about the R-package-devel mailing list