Monday, 1 April 2019

Build R project using Make

My default for building projects is to use make. I find it helps organise a projects workflow, even if there are other build tools available. It is succinct, and descriptive. A previous post showed how you can use make to build Haskell projects using GHC, Cabal and Stack. This blog show how to do the same for R projects.
Below is an R script that can be used to render R markdown to PDF. It is invoked from a parent Makefile which is what is read when you call make.
make.R
#!/usr/bin/env R
 
# Render R markdown to PDF.
# Invoke with:
# > R -q -f make.R --args my_report.Rmd
 
# load packages
require(rmarkdown)
 
# require a parameter naming file to render
if (length(args) == 0) {
    stop("Error: missing file operand", call. = TRUE)
} else {
    # read report to render from command line
    for (rmd in commandArgs(trailingOnly = TRUE)) {
        # render Rmd to PDF
        if ( grepl("\\.Rmd$", rmd) && file.exists(rmd)) {
            render(rmd, pdf_document())
        } else {
            print(paste("Ignoring: ", rmd))
        }
    }
}
The above will process Rmd files listed after the –args parameter. This script is invoked from the Makefile below. It declares an rule that describes how to build a PDF from RmdThe rule calls R with the above R script (make.R).
Makefile
#!/usr/bin/env make
 
.PHONY: all clean
.SUFFIXES: .Rmd .pdf
 
DOCS = my-report
RMDS = $(patsubst %, %.Rmd, $(DOCS))
R = /usr/bin/R
 
Rmd: $(patsubst %.Rmd, %.pdf, $(RMDS))
 
.Rmd.pdf:
    @$(R) --quiet --file=make.R --args $<
 
all: clean Rmd
 
clean:
    @rm -f $(patsubst %.Rmd, %.pdf, $(RMDS))
Note Makefiles must use tabs for indentation, not spaces. My default tab setting is 8 spaces.

Example

Here is a quick example document we will render to PDF:
example.Rmd
---
title: "Example"
author: "Frank Jung"
date: "12 August 2016"
output: pdf_document
---
 
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
 
## R Markdown
 
This is an R Markdown document. Markdown is a simple formatting syntax for
authoring HTML, PDF, and MS Word documents. For more details on using R Markdown
see <http://rmarkdown.rstudio.com>.
 
When you click the **Knit** button a document will be generated that includes
both content as well as the output of any embedded R code chunks within the
document. You can embed an R code chunk like this:
 
```{r cars}
summary(cars)
```
 
## Including Plots
 
You can also embed plots, for example:
 
```{r pressure, echo=FALSE}
plot(pressure)
```
 
Note that the `echo = FALSE` parameter was added to the code chunk to prevent
printing of the R code that generated the plot.
Render using above make file with:
make clean all
Renders the PDF as example.pdf.

If you have not used a build tool for you project, I suggest having a look at make. The variant available on most systems is GNU Make. You'll find that there are many languages already supported. When I first started using make, they were primitive and I tended to ignore the implicit rules. Now, I write my own with confidence. I hope you too will experience the benefits of make in your projects ...