Overview
rdev supports my personal workflow, including creation of both
traditional R packages and R Analysis Packages
(vignette("analysis-package-layout")), enforcing
consistency across packages, and providing Continuous
Integration/Continuous Delivery (CI/CD) automation. I use the tools in
rdev to improve code quality, speed up development of R code, and
publish results of analyses in R and Quarto Notebooks as HTML to make
them accessible to non-R users.
Installation
My current R development environment uses Homebrew, rig, RStudio, GitHub, a collection of R packages including rdev, Visual Studio Code, and Vim.
Homebrew
I use Homebrew Bundle to install all software on my systems; my basic macOS working environment is published on GitHub in macos-env.
Installing R
rig supports installation of multiple versions of official R binaries, which I use for reproducibility. To install R using rig, first install rig:
Then install desired versions of R. The following installs R 4.1 through 4.6 on ARM based macs (as of 2026-07-26):
rig install oldrel/5 --without-pak
rig install oldrel/4 --without-pak
rig install oldrel/3 --without-pak
rig install oldrel/2 --without-pak
rig install oldrel --without-pak
rig install release --without-pak
rig default releaseNote that:
- I don’t use pak, which rig installs by default, as it is not yet fully supported by renv.
- The oldest version of R I install is 4.1 (on ARM) or 4.3 (on Intel),
which are the oldest versions of R that install into
/optinstead of/usr/local(which causes issues for Homebrew)
Also note that RStudio requires R 3.6 or newer (as of version 2024.04.00). Since there was no ARM binary release for R 3.6 or R 4.0, running these versions requires installing the Intel binaries and running them with Rosetta 2.
Development Tools
Well, obviously, I use RStudio. RStudio is the leading IDE for R development and integrates with many R packages, although it sometimes falls short; I use GitHub and the command line for Git, and occasionally Visual Studio Code (which has better support for markdown) and Vim (which is faster for some types of edits).
Posit is developing a next-generation R and Python IDE based on Visual Studio Code, Positron. While I’ve tried using Positron, I’ve found that it has too many missing features to replace RStudio for my development, including:
- Lack of a notebook-style interface for RMarkdown or Quarto documents
- No support for lintr
- No command History or package Build panes
Of these, the first two are showstoppers and the missing panes are nearly so.
RStudio, the GitHub desktop client, and Visual Studio Code are easily installed using Homebrew:
It is recommended to change the default settings for
.RData in RStudio (in Options > General > Basic >
Workspace):
- Uncheck “Restore .Data into workspace at startup”
- Set “Save workspace to .Data on exit” to “Never”
Vim is installed by default on macOS and most Unix-like systems.
Packages
Managing packages and environments are a challenge for most modern languages. Thankfully R doesn’t have the same level of challenge as python, or even ruby, managing packages available within a project is a best practice. I use renv for this purpose, and use renv to install and manage all packages in all of my projects.
The setup-r script from rdev installs a base set of
packages needed to run rdev in the R User Library. A streamlined version
of that script is included below.
# fix rig permissions
sudo chown -R "$(whoami)":admin /Library/Frameworks/R.framework/Versions/*/Resources/library
RVERSION="$(Rscript -e 'cat(as.character(getRversion()[1,1:2]))')"
USERLIB="$HOME/Library/R/$(uname -m)/${RVERSION}/library"
DEVPKG='c("renv", "styler", "lintr", "miniUI", "languageserver", "rmarkdown", "stringr", "devtools", "available", "remotes")'
GITPKG='c("jabenninghoff/rdev")'
if [ ! -d "${USERLIB}" ]
then
mkdir -p "${USERLIB}"
fi
echo "install.packages(${DEVPKG}, repos=\"https://cloud.r-project.org\", lib=\"${USERLIB}\")" | R --no-save
echo "remotes::install_github(${GITPKG}, lib=\"${USERLIB}\")" | R --no-saveThe chown command is needed to allow updating the base
packages using the RStudio Packages “Update” function. I generally
update packages in RStudio with no projects open before starting
development, then update packages in projects using
renv::update().
If you’re installing (development) versions of packages from GitHub,
it is recommended
to set up a personal access token using
usethis::create_github_token() and adding it to your Git
credential store using gitcreds::gitcreds_set(). You can
verify GitHub is set up following usethis recommendations with
usethis::git_sitrep().
Makevars
When building from source, R uses ~/.R/Makevars to
customize how C, C++, or Fortran code is compiled. I’ve developed a
personalized Makevars file for macOS that detects Homebrew installed
libraries, adds OpenMP support via libomp, and includes notes on
officially supported versions of gfortran, along with instructions on
how to use gfortran from Homebrew.
# macOS .R/Makevars
# adapted from https://github.com/Rdatatable/data.table/wiki/Installation
# https://firas.io/posts/data_table_openmp/
# and https://cran.r-project.org/doc/manuals/r-devel/R-exts.html#Using-Makevars
# CPPFLAGS is set in ${R_HOME}/etc/Makeconf and is set to "-I/opt/R/arm64/include" for ARM versions of R (>= 4.1)
# we use this to determine the (default) HOMEBREW_PREFIX for each architecture
ifeq "$(CPPFLAGS)" "-I/opt/R/arm64/include"
HOMEBREW_PREFIX=/opt/homebrew
else
HOMEBREW_PREFIX=/usr/local
endif
# include homebrew installed libraries
# https://stackoverflow.com/questions/79740057/libintl-h-not-found-when-installing-matrix-with-renv
LDFLAGS+=-L$(HOMEBREW_PREFIX)/lib
CPPFLAGS+=-I$(HOMEBREW_PREFIX)/include
# install libomp with `brew install libomp`
# libomp is keg only, set flags per libomp caveats
LDFLAGS+=-L$(HOMEBREW_PREFIX)/opt/libomp/lib
CPPFLAGS+=-I$(HOMEBREW_PREFIX)/opt/libomp/include
LDFLAGS+=-lomp
# Flags for OpenMP support that should allow packages that want to use
# OpenMP to do so (data.table), and other packages that bork with
# -fopenmp flag (stringi) to be left alone
# Support for C++98 was removed in R 4.1.0: https://cran.r-project.org/bin/windows/base/old/4.1.0/NEWS.R-4.1.0.html
# Supported C++ Standards in R 4.6.0: https://github.com/wch/r-source/tree/tags/R-4-6-0/tests/C%2B%2BStandards
SHLIB_OPENMP_CFLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXXFLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX11FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX14FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX17FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX20FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX23FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_CXX26FLAGS=-Xclang -fopenmp
SHLIB_OPENMP_FCFLAGS=-Xclang -fopenmp
SHLIB_OPENMP_FFLAGS=-Xclang -fopenmp
# gfortran is included with `brew install gcc`
# adapted from https://www.cynkra.com/blog/2021-03-16-gfortran-macos/
# with help from https://cran.r-project.org/doc/manuals/r-release/R-admin.html#macOS-packages
# and https://github.com/r-lib/rig/issues/207
# note: ignore linker duplicate libraries warning per https://github.com/orgs/Homebrew/discussions/4794
# -lemutls_w added here: https://github.com/wch/r-source/commit/22fab0d7a9f50afd4960e68d57bea137a004f03e
#
# CRAN uses specific gfortran binaries from https://mac.r-project.org/tools/:
#
# - gfortran 4.2.3 for R 3.6 (https://cran.r-project.org/bin/macosx/tools/)
# - gfortran 8.2 for intel R 4.0 through 4.2 (https://github.com/fxcoudert/gfortran-for-macOS)
# - gfortran 11.0.0 for arm64 R 4.1 (https://mac.r-project.org/libs-arm64/gfortran-f51f1da0-darwin20.0-arm64.tar.gz)
# - gfortran 12.0.1 for arm64 R 4.2 (https://github.com/R-macos/gcc-darwin-arm64)
# - gfortran-12.2-universal.pkg for R 4.3 and 4.4 (https://github.com/R-macos/gcc-12-branch)
# - gfortran-14.2-universal.pkg (r-gfortran) for R 4.5 and newer (https://github.com/R-macos/gcc-14-branch)
#
# uncomment the following lines when using homebrew gfortran
#FC=$(HOMEBREW_PREFIX)/bin/gfortran
#F77=$(HOMEBREW_PREFIX)/bin/gfortran
#FLIBS=-L$(HOMEBREW_PREFIX)/lib/gcc/current -lgfortran -lquadmathThe latest version of R gfortran 14.2 (for R 4.5 and newer) can be installed from jabenninghoff/homebrew-edge:
Further Reading
My workflow has been heavily influenced by the DevOps movement and the research of the DevOps Research and Assessment (DORA) team at Google started by Dr. Nicole Forsgren. Their research shows how technical and non-technical capabilities improve outcomes.
The functions included in rdev support many of the technical capabilities, including:
- Code maintainability
- Continuous delivery
- Continuous integration
- Deployment automation
- Shifting left on security
- Test automation
- Trunk-based development
- Version control
An outline of my SIRAcon 2022 talk, “Making R Work for You (With Automation)” is available on GitHub in siracon2022.
