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

improve OpenMP detection on macOS #6034

Merged
merged 13 commits into from
Apr 3, 2024
92 changes: 74 additions & 18 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ esac

msg=0
NOZLIB=1 # if pkg-config is not available then zlib will be disabled for higher chance of compilation success
pkg-config --version >/dev/null 2>&1
pkg-config --version >> config.log 2>&1
if [ $? -ne 0 ]; then
echo "*** pkg-config is not installed."
msg=1
Expand All @@ -33,9 +33,9 @@ else
else
NOZLIB=0
lib=`pkg-config --libs zlib`
expr -- "$lib" : ".*-lz$" >/dev/null # -- for FreeBSD, #4652
expr -- "$lib" : ".*-lz$" >> config.log # -- for FreeBSD, #4652
if [ $? -ne 0 ]; then
expr -- "$lib" : ".*-lz " >/dev/null
expr -- "$lib" : ".*-lz " >> config.log
# would use \b in one expr but MacOS does not support \b
if [ $? -ne 0 ]; then
echo "*** pkg-config is installed and 'pkg-config --exists zlib' succeeds but"
Expand Down Expand Up @@ -81,36 +81,92 @@ int main() {
}
EOF

# First, try R CMD SHLIB to see if R can already compile
# things using OpenMP without any extra help from data.table
"${R_HOME}/bin/R" CMD SHLIB test-omp.c >/dev/null 2>&1 || R_NO_OPENMP=1
detect_openmp () {

if [ "$R_NO_OPENMP" = "1" ]; then
# Compilation failed -- try forcing -fopenmp instead.
R_NO_OPENMP=0
"${CC}" "${CFLAGS}" -fopenmp test-omp.c || R_NO_OPENMP=1
# TODO: and then nothing seems to be done with this outcome
else
echo "R CMD SHLIB supports OpenMP without any extra hint"
fi
if [ "$(uname)" = "Linux" ]; then
MichaelChirico marked this conversation as resolved.
Show resolved Hide resolved

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


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

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" LDFLAGS="${LDFLAGS} -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

# Clean up.
rm -f test-omp.* a.out
if [ "$(uname -m)" = "arm64" ]; then
HOMEBREW_PREFIX=/opt/homebrew
else
HOMEBREW_PREFIX=/usr/local
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
fi

fi

# Write to Makevars
if [ "$R_NO_OPENMP" = "1" ]; then
# No support for OpenMP available
export R_OPENMP_ENABLED=0
}

detect_openmp
rm -f a.out test-omp.c

if [ "${R_OPENMP_ENABLED}" = "0" ]; then
echo "***"
echo "*** OpenMP not supported! data.table uses OpenMP to automatically"
echo "*** parallelize operations like sorting, grouping, file reading, etc."
echo "*** For details on how to install the necessary toolchains on your OS see:"
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

# 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
sed -e "s|@PKG_LIBS@|$PKG_LIBS|" src/Makevars > src/Makevars.tmp && mv src/Makevars.tmp src/Makevars

# optional dependency on zlib
if [ "$NOZLIB" = "1" ]; then
echo "*** Compilation without compression support in fwrite"
Expand Down
19 changes: 11 additions & 8 deletions src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,18 @@ int GetVerbose(void) {

// # nocov start
SEXP hasOpenMP(void) {
// Just for use by onAttach (hence nocov) to avoid an RPRINTF from C level which isn't suppressable by CRAN
// There is now a 'grep' in CRAN_Release.cmd to detect any use of RPRINTF in init.c, which is
// why RPRINTF is capitalized in this comment to avoid that grep.
// .Platform or .Machine in R itself does not contain whether OpenMP is available because compiler and flags are per-package.
#ifdef _OPENMP

#if defined(_OPENMP)
// gcc build of libomp
return ScalarInteger(_OPENMP); // return the version; e.g. 201511 (i.e. 4.5)
#else
return ScalarInteger(0); // 0 rather than NA so that if() can be used on the result
#endif
#elif defined(KMP_VERSION_BUILD)
// LLVM builds of libomp
return ScalarInteger(KMP_VERSION_BUILD);
#else
// no OpenMP support detected
return ScalarInteger(0);
#endif

}
// # nocov end

Expand Down
8 changes: 8 additions & 0 deletions src/myomp.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@

// Compatibility define for LLVM builds of libomp.
#ifdef KMP_VERSION_BUILD
# ifndef _OPENMP
# define _OPENMP KMP_VERSION_BUILD
# endif
#endif

#ifdef _OPENMP
#include <omp.h>
#if _OPENMP >= 201511
Expand Down
Loading