renv is an excellent choice for maintaining a clean and reproducible R environment on macOS. Here, I will share my experiences and provide a guide on setting up R on macOS. The post is divided into the following sections:
- Installing system dependencies required for R libraries using Homebrew.
- Installing R libraries using
- Saving and restoring R environments using
- Installing R libraries hosted on private repositories.
- Building R libraries from source using
Let’s get started!
1# install xcode CLI 2xcode-select --install 3# install homebrew 4/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Installing system dependencies
Brewfile for batch installation of R, RStudio and the required system libraries
1brew "ccache" # Object-file caching compiler wrapper 2brew "coreutils" # GNU File, Shell, and Text utilities 3brew "gdal" # Geospatial Data Abstraction Library 4brew "geos" # Geometry Engine 5brew "gfortran" # GNU compiler collection 6brew "graphviz" # Graph visualization software from AT&T and Bell Labs 7brew "libgit2" # C library of Git core methods that is re-entrant and linkable 8brew "libjpeg" # Image manipulation library 9brew "libomp" # LLVM's OpenMP runtime library 10brew "libxml2" # GNOME XML library 11brew "llvm" # Next-gen compiler infrastructure 12brew "openblas" # Optimized BLAS library 13brew "openssl" # OpenSSL GIO module for glib 14brew "poppler" # PDF rendering library (based on the xpdf-3.0 code base) 15brew "proj" # Cartographic Projections Library 16brew "readline" # Library for command-line editing 17brew "unixodbc" # ODBC 3 connectivity for UNIX 18brew "xz" # General-purpose data compression with high compression ratio 19brew "zlib" # General-purpose lossless data-compression library 20brew "r" 21cask "rstudio"
Then run the installation using the following
1brew bundle install --force --file Brewfile -v
Installing R libraries
To set up a reproducible R environment, I recommend using
renv. Here’s an example of how to create a new environment and install the
- Set the current project folder as the working directory:
- Install the
renvlibrary if you haven’t already:
- Initialize and activate the
1library(renv) 2renv::init() 3renv::activate()
renv, only the
renv library itself will be installed in the system-wide location, such as
/usr/local/Cellar/r/ (Intel macOS) or
/opt/homebrew/Cellar/r/ (Apple Silicon).
Project-specific libraries, on the other hand, will be installed into the
renv base located at
~/Library/Caches/org.R-project.R. When creating a new environment,
renv links the libraries from its base into the
renv folder within the project directory. This approach maintains a clean system base and allows for sharing the
renv space across different R environments.
To install project-specific R libraries, you can utilize the
renv::install() function. For instance, if you want to install
signature.tools.lib, it has the following dependencies:
1renv::install("bioc::VariantAnnotation") 2renv::install("bioc::BSgenome.Hsapiens.UCSC.hg38") 3renv::install("bioc::BSgenome.Hsapiens.1000genomes.hs37d5") 4renv::install("bioc::BSgenome.Mmusculus.UCSC.mm10") 5renv::install("bioc::BSgenome.Cfamiliaris.UCSC.canFam3") 6renv::install("bioc::SummarizedExperiment") 7renv::install("bioc::BiocGenerics") 8renv::install("bioc::GenomeInfoDb") 9renv::install("NMF") 10renv::install("foreach") 11renv::install("doParallel") 12renv::install("lpSolve") 13renv::install("ggplot2") 14renv::install("cluster") 15renv::install("methods") 16renv::install("stats") 17renv::install("linxihui/NNLM") 18renv::install("nnls") 19renv::install("GenSA") 20renv::install("gmp") 21renv::install("plyr") 22renv::install("RCircos") 23renv::install("scales") 24renv::install("bioc::GenomicRanges") 25renv::install("bioc::IRanges") 26renv::install("bioc::BSgenome") 27renv::install("readr") 28renv::install("doRNG") 29renv::install("combinat") 30renv::install("Nik-Zainal-Group/signature.tools.lib.dev") 31renv::install("Nik-Zainal-Group/teachingmutationalsignatures")
Saving and restoring R environments
renv to save the environment you described, you can use the
renv::snapshot() function. However, please note that
renv only saves libraries that are explicitly called in your code. If a library is not referenced anywhere in your code,
renv will not include it in the snapshot.
To ensure all the required libraries are saved, you can create a separate file, let’s call it
libraries.R, where you call and load all the necessary libraries. This way,
renv will detect these library calls and include them in the snapshot.
Here’s an example of how you can structure the
1# libraries.R 2library(signature.tools.lib) 3# Call and load any other required libraries here
renv::snapshot() after sourcing the
renv will recognize the library calls and include the required libraries in the snapshot.
1# save renv.lock file 2renv::snapshot()
Saving the environment will generate a
To restore the environment on a new location or machine, you can follow these steps after copying the
renv.lock files into a new project folder, then run the following commands:
1# if `renv` is not installed on the new system 2install.packages('renv') 3 4renv::init() 5# or 6renv::restore()
Installation from private repositories
When dealing with R libraries hosted on a private repository, additional authentication is required. One common method is to generate a Personal Access Token (PAT) to authenticate with the hosting service like Github.
To authenticate using the generated PAT.
1Sys.setenv(GITHUB_PAT = "PASTE_TOKEN_HERE") 2renv::install("private_repo/R_package")
Installation from source
To install R libraries from source, we need to instruct R where to find the required system dependencies. This is done by using a
which is placed
~/.R/Makevars and looks like this.
1# -------- 2# Makevars 3# -------- 4 5# General note 6 7# Homebrew bin / opt / lib locations 8 9### uncomment on Apple Silicon 10#HB=/opt/homebrew/bin 11#HO=/opt/homebrew/opt 12#HL=/opt/homebrew/lib 13#HI=/opt/homebrew/include 14 15### uncomment on Intel 16#HB=/usr/local/bin 17#HO=/usr/local/opt 18#HL=/usr/local/lib 19#HI=/usr/local/include 20 21# MacOS Xcode header location 22# (do "xcrun -show-sdk-path" in terminal to get path) 23XH=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk 24 25# ccache 26CCACHE=$(HB)/ccache 27 28# Make using all cores (set # to # of cores on your machine) 29MAKE=make -j4 30 31# GNU version 32GNU_VER=12 33 34# LLVM (Clang) compiler options 35CC=$(CCACHE) $(HO)/llvm/bin/clang 36CXX=$(CC)++ 37CXX98=$(CC)++ 38CXX11=$(CC)++ 39CXX14=$(CC)++ 40CXX17=$(CC)++ 41 42# FORTRAN 43FC=$(CCACHE) $(HB)/gfortran-$(GNU_VER) 44F77=$(FC) 45FLIBS=-L$(HL)/gcc/$(GNU_VER) -lgfortran -lquadmath -lm 46 47# STD libraries 48CXX1XSTD=-std=c++0x 49CXX11STD=-std=c++11 50CXX14STD=-std=c++14 51CXX17STD=-std=c++17 52 53# FLAGS 54STD_FLAGS=-g -O3 -Wall -pedantic -mtune=native -pipe 55CFLAGS=$(STD_FLAGS) 56CXXFLAGS=$(STD_FLAGS) 57CXX98FLAGS=$(STD_FLAGS) 58CXX11FLAGS=$(STD_FLAGS) 59CXX14FLAGS=$(STD_FLAGS) 60CXX17FLAGS=$(STD_FLAGS) 61 62# Preprocessor FLAGS 63# NB: -isysroot refigures the include path to the Xcode SDK we set above 64CPPFLAGS=-isysroot $(XH) -I$(HI) \ 65 -I$(HO)/llvm/include -I$(HO)/openssl/include \ 66 -I$(HO)/gettext/include -I$(HO)/tcl-tk/include 67 68# Linker flags (suggested by homebrew) 69LDFLAGS+=-L$(HO)/llvm/lib -Wl,-rpath,$(HO)/llvm/lib 70 71# Flags for OpenMP support that should allow packages that want to use 72# OpenMP to do so (data.table), and other packages that bork with 73# -fopenmp flag (stringi) to be left alone 74SHLIB_OPENMP_CFLAGS=-fopenmp 75SHLIB_OPENMP_CXXFLAGS=-fopenmp 76SHLIB_OPENMP_CXX98FLAGS=-fopenmp 77SHLIB_OPENMP_CXX11FLAGS=-fopenmp 78SHLIB_OPENMP_CXX14FLAGS=-fopenmp 79SHLIB_OPENMP_CXX17FLAGS=-fopenmp 80SHLIB_OPENMP_FCFLAGS=-fopenmp 81SHLIB_OPENMP_FFLAGS=-fopenmp
There are three things we need to pay attention to in the file above (highlighted lines):
- Depending on the architecture of the macOS machine, Intel vs Apple Silicon (M1/2), we need to uncomment the corresponding lines.
xcrun -show-sdk-pathto make sure they are located at
- To find the installed version of GCC, change directory into /usr/local/lib/gcc/ on an Intel macOS, or /opt/homebrew/lib/ on an Apple Silicon.
The mentioned method is useful for installing libraries like the
data.table library that require OpenMP support to leverage multiprocessing capabilities. For more details on this approach, you can refer to the article located here.