Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configure: test linking with -fopenmp, test the resulting shared object #6642

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 21 additions & 62 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -75,62 +75,34 @@ fi
# necessarily here in configure). Hence use -fopenmp directly for this detection step.
# printf not echo to pass checkbashisms w.r.t. to the \n

cat <<EOF > test-omp.c
#include <omp.h>
int main() {
return omp_get_num_threads();
# Usage: "user-facing string" "CFLAGS" "LDFLAGS"
check_openmp_flags () {
printf "* checking if %s... " "$1"
if "${R_HOME}/bin/Rscript" tools/check-openmp-flags.R "${PKG_CFLAGS} $2" "${PKG_LIBS} $3" >> config.log 2>&1; then
echo "yes"
export R_OPENMP_CFLAGS="$2"
export R_OPENMP_LIBS="$3"
export R_OPENMP_ENABLED=1
return 0
else
echo "no"
return 1
fi
}
EOF

detect_openmp () {
R_OPENMP_CFLAGS=
R_OPENMP_LIBS=

if [ "$(uname)" = "Linux" ]; then

printf "%s" "* checking if R installation supports OpenMP without any extra hints... "
if "${R_HOME}/bin/R" CMD SHLIB test-omp.c >> config.log 2>&1; then
echo "yes"
export R_OPENMP_ENABLED=1
return
else
echo "no"
fi

check_openmp_flags "R installation is configured to use OpenMP" '$(SHLIB_OPENMP_CFLAGS)' '$(SHLIB_OPENMP_CFLAGS)' && return

printf "%s" "* checking if R installation supports openmp with \"-fopenmp\" flag... "
if ${CC} ${CFLAGS} -fopenmp test-omp.c >> config.log 2>&1; then
echo "yes"
export PKG_CFLAGS="${PKG_CFLAGS} -fopenmp"
export R_OPENMP_ENABLED=1
return
else
echo "no"
fi
fi # uname=Linux
# https://github.com/Rdatatable/data.table/issues/6409
check_openmp_flags "R installation supports OpenMP with \"-fopenmp\" flag" -fopenmp -fopenmp && return

if [ "$(uname)" = "Darwin" ]; then

# https://mac.r-project.org/openmp
printf "%s" "* checking if R installation supports OpenMP with \"-Xclang -fopenmp\" ... "
if CPPFLAGS="${CPPFLAGS} -Xclang -fopenmp" PKG_LIBS="-lomp" "${R_HOME}/bin/R" CMD SHLIB test-omp.c >> config.log 2>&1; then
echo "yes"
export PKG_CFLAGS="${PKG_CFLAGS} -Xclang -fopenmp"
export PKG_LIBS="${PKG_LIBS} -lomp"
export R_OPENMP_ENABLED=1
return
else
echo "no"
fi

# https://github.com/Rdatatable/data.table/issues/6409
printf "%s" "* checking if R installation supports OpenMP with \"-fopenmp\" ... "
if CPPFLAGS="${CPPFLAGS} -fopenmp" "${R_HOME}/bin/R" CMD SHLIB test-omp.c >> config.log 2>&1; then
echo "yes"
export PKG_CFLAGS="${PKG_CFLAGS} -fopenmp"
export R_OPENMP_ENABLED=1
return
else
echo "no"
fi
check_openmp_flags "R installation supports OpenMP with \"-Xclang -fopenmp\" " "-Xclang -fopenmp" "-lomp" && return

if [ "$(uname -m)" = "arm64" ]; then
HOMEBREW_PREFIX=/opt/homebrew
Expand All @@ -139,18 +111,9 @@ detect_openmp () {
fi

if [ -e "${HOMEBREW_PREFIX}/opt/libomp" ]; then
printf "%s" "* checking if libomp installation at ${HOMEBREW_PREFIX}/opt/libomp can be used... "
LIBOMP_INCLUDE="-I${HOMEBREW_PREFIX}/opt/libomp/include -Xclang -fopenmp"
LIBOMP_LINK="-L${HOMEBREW_PREFIX}/opt/libomp/lib -lomp"
if ${CC} ${CFLAGS} ${LIBOMP_INCLUDE} ${LIBOMP_LINK} test-omp.c >> config.log 2>&1; then
echo "yes"
export PKG_CFLAGS="${PKG_CFLAGS} ${LIBOMP_INCLUDE}"
export PKG_LIBS="${PKG_LIBS} ${LIBOMP_LINK}"
export R_OPENMP_ENABLED=1
return
else
echo "no"
fi
check_openmp_flags "libomp installation at ${HOMEBREW_PREFIX}/opt/libomp can be used" "${LIBOMP_INCLUDE}" "${LIBOMP_LINK}" && return
fi

fi # uname=Darwin
Expand All @@ -160,8 +123,6 @@ detect_openmp () {
}

detect_openmp
# Clean up.
rm -f test-omp.* a.out

if [ "${R_OPENMP_ENABLED}" = "0" ]; then
echo "***"
Expand All @@ -171,10 +132,8 @@ if [ "${R_OPENMP_ENABLED}" = "0" ]; then
echo "*** https://github.com/Rdatatable/data.table/wiki/Installation"
echo "*** Continuing installation without OpenMP support..."
echo "***"
sed -e "s|@openmp_cflags@||" src/Makevars.in > src/Makevars
else
sed -e "s|@openmp_cflags@|\$(SHLIB_OPENMP_CFLAGS)|" src/Makevars.in > src/Makevars
fi
sed -e "s|@openmp_cflags@|${R_OPENMP_CFLAGS}|" -e "s|@openmp_libs@|${R_OPENMP_LIBS}|" src/Makevars.in > src/Makevars

# retain user supplied PKG_ env variables, #4664. See comments in Makevars.in too.
sed -e "s|@PKG_CFLAGS@|$PKG_CFLAGS|" src/Makevars > src/Makevars.tmp && mv src/Makevars.tmp src/Makevars
Expand Down
2 changes: 1 addition & 1 deletion src/Makevars.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PKG_CFLAGS = @PKG_CFLAGS@ @openmp_cflags@ @zlib_cflags@
PKG_LIBS = @PKG_LIBS@ @openmp_cflags@ @zlib_libs@
PKG_LIBS = @PKG_LIBS@ @openmp_libs@ @zlib_libs@
# See WRE $1.2.1.1. But retain user supplied PKG_* too, #4664.
# WRE states ($1.6) that += isn't portable and that we aren't allowed to use it.
# Otherwise we could use the much simpler PKG_LIBS += @openmp_cflags@ -lz.
Expand Down
40 changes: 40 additions & 0 deletions tools/check-openmp-flags.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
args <- commandArgs(TRUE)
stopifnot(`Usage: Rscript check-openmp-flags.R CFLAGS LIBS` = length(args) == 2)
# We'll need to create Makevars (and object and DLL files too)
setwd(tempdir())
cat(sprintf(
"Testing if OpenMP works with CFLAGS='%s' and LIBS='%s':\n",
args[[1]], args[[2]]
))

# It must be a 'Makevars' for constructs like $(SHLIB_OPENMP_CFLAGS) to work:
writeLines(c(
paste("PKG_CFLAGS =", args[[1]]),
paste("PKG_LIBS =", args[[2]])
), "Makevars")

# Will succeed to compile even without OpenMP but return 0
writeLines("
#ifdef _OPENMP
#include <omp.h>
#endif
void test_openmp(int * result) {
int sum = 0;
#ifdef _OPENMP
// Have to test an actual OpenMP operation: simpler tests may succeed for a broken configuration, #6642
#pragma omp parallel for reduction(+:sum) num_threads(2)
for (int i = 1; i <= 2; ++i) sum += i;
#endif
*result = sum;
}
", "test.c")

# May fail to compile anyway
stopifnot(tools::Rcmd("SHLIB --preclean test.c") == 0)

dyn.load(paste0("test", .Platform$dynlib.ext))
ans <- .C("test_openmp", ans = integer(1))$ans
desired <- 3L
cat(sprintf("Test result: %d (must be %d; should be 0 for disabled OpenMP)\n", ans, desired))
stopifnot(`Test failed` = identical(ans, desired))
cat("Success\n")
Loading