diff --git a/ChangeLog b/ChangeLog index b08ef1f73..bcb1addf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,10 @@ or related R headers were installed first * inst/include/RcppCommon.h: Call new header as first thing +2025-11-18 James J Balamuta + + * R/Attributes.R: Updated OpenMP Plugin's flags on macOS + 2025-11-04 Dirk Eddelbuettel * .github/workflows/macos.yaml (jobs): Roll macos-13 to macos-14 diff --git a/R/Attributes.R b/R/Attributes.R index 53e9f0a61..16088396f 100644 --- a/R/Attributes.R +++ b/R/Attributes.R @@ -588,8 +588,52 @@ compileAttributes <- function(pkgdir = ".", verbose = getOption("verbose")) { ## built-in OpenMP plugin .plugins[["openmp"]] <- function() { - list(env = list(PKG_CXXFLAGS="-fopenmp", - PKG_LIBS="-fopenmp")) + + # Default flags for non-macOS systems + cxxflags <- "-fopenmp" + libs <- "-fopenmp" + + # Check if we're on macOS + if (Sys.info()[["sysname"]] == "Darwin") { + # Get the C++ compiler from R CMD config CXX + r_cmd <- file.path(R.home("bin"), "R") + cxx <- tryCatch({ + system2(r_cmd, c("CMD", "config", "CXX"), stdout = TRUE, stderr = FALSE) + }, error = function(e) "") + + if (length(cxx) > 0 && nzchar(cxx[1])) { + # Check compiler version using full command (this includes any flags) + compiler_version <- tryCatch({ + system(paste(cxx[1], "--version"), intern = TRUE, ignore.stderr = TRUE) + }, error = function(e) character(0)) + + if (length(compiler_version) > 0) { + # Check for Apple clang + is_apple_clang <- any(grepl("Apple", compiler_version, ignore.case = TRUE)) + # Check for Homebrew clang + is_homebrew_clang <- any(grepl("Homebrew", compiler_version, ignore.case = TRUE)) + + if (is_apple_clang) { + # Apple clang requires -Xclang -fopenmp + cxxflags <- "-Xclang -fopenmp" + libs <- "-lomp" + } else if (is_homebrew_clang) { + # Homebrew clang needs include/lib paths for the added libomp formula + # Determine prefix based on architecture (arm64 vs x86_64) + arch <- Sys.info()[["machine"]] + brew_prefix <- if (arch == "arm64") "/opt/homebrew" else "/usr/local" + + cxxflags <- paste("-Xclang -fopenmp", + paste0("-I", brew_prefix, "/opt/libomp/include")) + libs <- paste(paste0("-L", brew_prefix, "/opt/libomp/lib"), "-lomp") + } + # Otherwise it's gcc and regular -fopenmp works (defaults are fine) + } + } + } + + list(env = list(PKG_CXXFLAGS = cxxflags, + PKG_LIBS = libs)) } .plugins[["unwindProtect"]] <- function() { # nocov start