OpenMP on macOS with Xcode tools

Warning! Everything described on this page is strictly experimental and not officially supported by CRAN, R-core or R Foundation. In may break at any time. The information is provided in the hope of being useful to some tech-savvy people. It is not intended for the regular R user.

For those impatient, skip to how to enable OpenMP in packages.

OpenMP support in Xcode

Apple has explicitly disabled OpenMP support in compilers that they ship in Xcode:

   $ clang -c omp.c -fopenmp
   clang: error: unsupported option '-fopenmp'
even though clang had OpenMP support for quite a long time now (great thanks to the folks at Intel providing their library as open source!). In fact, the clang compiler in Xcode can generate all the necessary code for OpenMP. It can be tricked into performing its designed function by using -Xclang -fopenmp flags.

The unfortunate part about this is that Apple is not shipping the necesssary libomp.dylib run-time library needed for OpenMP support. Fortunately, some clever folks were able to match the versions so we can build the binaries that correspond to the clang version used. It is sometimes possible to use a more recent version of the runtime than the version of Apple clang, so picking the latest is often sufficient.

OpenMP run-time downloads

The follwing are links to libomp OpenMP run-time built from official LLVM release sources using Xcode compilers. They are signed and support macOS 10.13 (High Sierra) and higher. All tar-balls contain the system tree usr/local/lib and usr/local/include so the recommended installation is to type in Terminal:
    curl -O
    sudo tar fvxz openmp-14.0.6-darwin20-Release.tar.gz -C /

NOTE: Do NOT use a browser to download the tar balls, because it will quarantine the downloaded file and its contents. Modern macOS security doesn't allow the use of quarantined libraries so you'd have to remove the quarantine first with xattr -c if you do so.

The contained set of files is the same in all tar balls:

so you can simply remove those to uninstall. Note that any package you compile against libomp.dylib will need that run-time so you have to ship it with your package or have users install it. You can verify the signature in the library via codetool (see below).

BuildDownloadSHA1 checksum
LLVM 16.0.4
Xcode 15.0+ (Apple clang 1500.x)
openmp-16.0.4-darwin20-Release.tar.gz (Release)
openmp-16.0.4-darwin20-Debug.tar.gz (Debug)
LLVM 15.0.7
Xcode 14.3.x (Apple clang 1403.x)
openmp-15.0.7-darwin20-Release.tar.gz (Release)
openmp-15.0.7-darwin20-Debug.tar.gz (Debug)
LLVM 14.0.6
Xcode 14.0-14.2 (Apple clang 1400.x)
openmp-14.0.6-darwin20-Release.tar.gz (Release)
openmp-14.0.6-darwin20-Debug.tar.gz (Debug)
LLVM 13.0.0
Xcode 13.3-13.4.1 (Apple clang 1316.x)
openmp-13.0.0-darwin21-Release.tar.gz (Release)
openmp-13.0.0-darwin21-Debug.tar.gz (Debug)
LLVM 12.0.1
Xcode 13.0-13.2.1 (Apple clang 1300.x)
openmp-12.0.1-darwin20-Release.tar.gz (Release)
openmp-12.0.1-darwin20-Debug.tar.gz (Debug)
LLVM 11.0.1 (+M1 patch)
Xcode 12.5 (Apple clang 1205.x)
openmp-11.0.1-darwin20-Release.tar.gz (Release)
openmp-11.0.1-darwin20-Debug.tar.gz (Debug)
(All binaries above include both arm64 and x86_64 and require macOS 11 or higher. Binaries below require macOS 10.13 or higher and are Intel-only)
LLVM 10.0.0
Xcode 12.0-12.4 (Apple clang 1200.x)
openmp-10.0.0-darwin17-Release.tar.gz (Release)
openmp-10.0.0-darwin17-Debug.tar.gz (Debug)
LLVM 9.0.1
Xcode 11.4-11.7 (Apple clang 1103.x)
openmp-9.0.1-darwin17-Release.tar.gz (Release)
openmp-9.0.1-darwin17-Debug.tar.gz (Debug)
LLVM 8.0.1
Xcode 11.0-11.3.1 (Apple clang 1100.x)
openmp-8.0.1-darwin17-Release.tar.gz (Release)
openmp-8.0.1-darwin17-Debug.tar.gz (Debug)
LLVM 7.1.0
Xcode 10.2-10.3 (Apple clang 1001.x)
openmp-7.1.0-darwin17-Release.tar.gz (Release)
openmp-7.1.0-darwin17-Debug.tar.gz (Debug)

How to enable OpenMP in packages

How you do the latter depends on the package, but if the package does not set these environment variables itself, you can try
    PKG_CPPFLAGS='-Xclang -fopenmp' PKG_LIBS=-lomp R CMD INSTALL myPackage
If that doesn't work, please consult the package's documentation, and liaise with its maintainer. It is also possible to add those flags globally by adding the following to ~/.R/Makevars:
    CPPFLAGS += -Xclang -fopenmp
    LDFLAGS += -lomp
but be very careful when doing this, always check your ~/.R/Makevars whenever you upgrade R, macOS or Xcode!

Side notes

It may be possible in principle to build static version of the run-time. That can be done via -DLIBOMP_ENABLE_SHARED=OFF, but has not been tested. There is a potential for chaos when more OMP run-times get loaded into one process. Another interesting test would be to try -DLIBOMP_FORTRAN_MODULES=ON and see which versions are compatible with the GNU Fortran used in R. We are intentionally removing the gomp symlink from the binary so that iomp and gomp don't conflict.

License and sources

All sources were obtained directly from the LLVM releases and copies are also available in the src directory (including the build script). See LICENSE.txt in the sources for the corresponding license and for details on the OpenMP run-time.

Verifying code signatures

You can use codetools to verify the signature, for example you should see:
$ codesign -d -vv /usr/local/lib/libomp.dylib 
Format=Mach-O universal (x86_64 arm64)
CodeDirectory v=20400 size=5514 flags=0x0(none) hashes=167+2 location=embedded
Signature size=8927
Authority=Developer ID Application: Simon Urbanek (VZLD955F6P)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=11/11/2021 at 1:29:04 PM
Info.plist=not bound
Sealed Resources=none
Internal requirements count=1 size=168


Thanks to John Clayden, Kevin Ushey and others who contributed to the discussion and testing.

Trademark notices

Last modified on 2024/04/09 by Simon Urbanek