On 23 May 2024 at 20:02, Ivan Krylov wrote: | On Wed, 22 May 2024 09:18:13 -0500 | Dirk Eddelbuettel <e...@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 | e...@debian.org ______________________________________________ R-package-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-package-devel