@@ -586,10 +586,74 @@ compileAttributes <- function(pkgdir = ".", verbose = getOption("verbose")) {
586586 list (env = list (PKG_CXXFLAGS = " -std=c++2b" ))
587587}
588588
589+ .openmpPluginDefault <- function () {
590+ list (env = list (PKG_CXXFLAGS = " -fopenmp" , PKG_LIBS = " -fopenmp" ))
591+ }
592+
593+ .openmpPluginDarwin <- function () {
594+
595+ # generate a test script for compilation
596+ script <- tempfile(" openmp-detect-" , fileext = " .cpp" )
597+ writeLines(" " , con = script )
598+ on.exit(unlink(script , force = TRUE ), add = TRUE )
599+
600+ # get the C++ compiler from R
601+ r <- file.path(R.home(" bin" ), " R" )
602+ output <- tryCatch(
603+ system2(r , c(" CMD" , " SHLIB" , " --dry-run" , shQuote(script )), stdout = TRUE ),
604+ condition = identity
605+ )
606+ if (inherits(output , " condition" ))
607+ return (.openmpPluginDefault())
608+
609+ # extract the compiler invocation from the shlib output
610+ # use some heuristics here...
611+ index <- grep(" make would use" , output )
612+ compile <- output [[index + 1L ]]
613+
614+ # use everything up to the first include flag, which is normally
615+ # the R headers from CPPFLAGS
616+ idx <- regexpr(" -I" , compile , fixed = TRUE )
617+ cxx <- substring(compile , 1L , idx - 1L )
618+
619+ # check the compiler version
620+ command <- paste(cxx , " --version" )
621+ version <- tryCatch(
622+ system(command , intern = TRUE ),
623+ condition = identity
624+ )
625+ if (inherits(version , " condition" ))
626+ return (.openmpPluginDefault())
627+
628+ # if we're using Apple clang, use alternate flags
629+ # assume libomp was installed following https://mac.r-project.org/openmp/
630+ if (any(grepl(" Apple clang" , version ))) {
631+ cxxflags <- " -Xclang -fopenmp"
632+ libs <- " -lomp"
633+ }
634+
635+ # if we're using Homebrew clang, add in libomp include paths
636+ else if (any(grepl(" Homebrew clang" , version ))) {
637+ machine <- Sys.info()[[" machine" ]]
638+ prefix <- if (machine == " arm64" ) " /opt/homebrew" else " /usr/local"
639+ cxxflags <- sprintf(" -I%s/opt/libomp/include -fopenmp" , prefix )
640+ libs <- sprintf(" -L%s/opt/libomp/lib -fopenmp" , prefix )
641+
642+ # otherwise, use default -fopenmp flags for other compilers (LLVM clang; gcc)
643+ } else {
644+ cxxflags <- " -fopenmp"
645+ libs <- " -fopenmp"
646+ }
647+
648+ list (env = list (PKG_CXXFLAGS = cxxflags , PKG_LIBS = libs ))
649+
650+ }
651+
589652# # built-in OpenMP plugin
590- .plugins [[" openmp" ]] <- function () {
591- list (env = list (PKG_CXXFLAGS = " -fopenmp" ,
592- PKG_LIBS = " -fopenmp" ))
653+ .plugins [[" openmp" ]] <- if (Sys.info()[[" sysname" ]] == " Darwin" ) {
654+ .openmpPluginDarwin
655+ } else {
656+ .openmpPluginDefault
593657}
594658
595659.plugins [[" unwindProtect" ]] <- function () { # nocov start
0 commit comments