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

Ivan Krylov |kry|ov @end|ng |rom d|@root@org
Thu May 23 19:02:37 CEST 2024


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

-- 
Best regards,
Ivan

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



More information about the R-package-devel mailing list