Posted on :: Tags: ,

TL;DR: include OBJCXX=clang++ -std=gnu++17 in .R/Makevars to help install.pacakges to help Object-C code compilation.

Error messages

I wanted to install tidyverse on a new Mac. Almost everything worked out of the box, except for one thing: R's systemfonts triggered an hour of pain. clang++ stopped parsing when it encountered mac/FontManagerMac.mm while complaining that it was unable to understand c++11 features, e.g., constexpr.

clang++ -I"/opt/homebrew/Cellar/r/4.4.2_2/lib/R/include" -DNDEBUG -I/opt/homebrew/opt/freetype/include/freetype2 -I/opt/homebrew/opt/libpng/include/libpng16 -I'/opt/homebrew/lib/R/4.4/site-library/cpp11/include' -I/opt/homebrew/opt/gettext/include -I/opt/homebrew/opt/readline/include -I/opt/homebrew/opt/xz/include -I/opt/homebrew/include   -fobjc-arc -fPIC   -c mac/FontManagerMac.mm -o mac/FontManagerMac.o
In file included from mac/FontManagerMac.mm:5:
In file included from mac/../FontDescriptor.h:11:
In file included from mac/../utils.h:9:
In file included from /opt/homebrew/lib/R/4.4/site-library/cpp11/include/cpp11/protect.hpp:10:
/opt/homebrew/lib/R/4.4/site-library/cpp11/include/cpp11/R.hpp:52:1: error: unknown type name 'constexpr'
   52 | constexpr R_xlen_t operator"" _xl(unsigned long long int value) { return value; }
      | ^
/opt/homebrew/lib/R/4.4/site-library/cpp11/include/cpp11/R.hpp:52:19: error: expected ';' after top level declarator
   52 | constexpr R_xlen_t operator"" _xl(unsigned long long int value) { return value; }
      |                   ^
      |                   ;

Solution: make your Clang++ understand new features

I believe CRAN packages are generally well prepared to handle C/C++ compiling, except for Object-C! We need to include the following line to .R/Makevars for a silicon Mac:

OBJCXX=clang++ -std=gnu++17

We could additionally tweak so that compilation processes can take place on many files with an additional flag:

MAKEFLAGS = -j10

Here, we run 10 jobs simultaneously.

Another issue on openmp

In order to compile Rcpp codes with <omp.h>, we also need libomp for multi-threading. We can add more lines to .R/Makevars and here is an example:

LDFLAGS += -L/opt/homebrew/opt/llvm/lib
LDFLAGS += -L/opt/homebrew/opt/libomp/lib -lomp

CXXFLAGS += -I/opt/homebrew/opt/llvm/include
CXXFLAGS += -I/opt/homebrew/opt/libomp/include -Xclang -fopenmp

CPPFLAGS += -I/opt/homebrew/opt/llvm/include
CPPFLAGS += -I/opt/homebrew/opt/libomp/include -Xclang -fopenmp

PKG_LDFLAGS += $(LDFLAGS)
PKG_CXXFLAGS += $(CXXFLAGS)
PKG_CPPFLAGS += $(CPPFLAGS)

OBJCXX = clang++ -std=gnu++17

MAKEFLAGS = -j10