---
title: Introduction to make
author: "Colin Rundel"
date: "2018-10-18"
output:
xaringan::moon_reader:
css: "slides.css"
lib_dir: libs
nature:
highlightStyle: github
highlightLines: true
countIncrementalSlides: false
---
exclude: true
```{r, message=FALSE, warning=FALSE, include=FALSE}
options(
htmltools.dir.version = FALSE, # for blogdown
width = 80,
tibble.width = 80
)
knitr::opts_chunk$set(
fig.align = "center"
)
htmltools::tagList(rmarkdown::html_dependency_font_awesome())
```
---
class: middle
count: false
# make
---
## make
* Automatically build software / libraries / documents by specifying dependencies via a `Makefile`
* Originally created by Stuart Feldman in 1976 at Bell Labs
* Almost universally available (all flavors of unix / linux / osx)
---
## Makefile
A `Makefile` provides a list of target files along with their dependencies and the steps necessary to generate each of the targets.
```
target1: depend1 depend2 depend3 ...
step1
step2
step3
...
depend1: depend1.1
step1
step2
```
---
## Makefile (simple example)
```make
paper.html: paper.Rmd Fig1/fig.png Fig2/fig.png
Rscript -e "library(rmarkdown);render('paper.Rmd')"
Fig1/fig.png: Fig1/fig.R
cd Fig1;Rscript fig.R
Fig2/fig.png: Fig2/fig.R
cd Fig2;Rscript fig.R
```
---
## Smart Building
Because the `Makefile` specifies the dependency structure `make` knows when a file has changed (by examining the file's modification timestamp) and only runs the steps that depend on the file(s) that have changed.
* After running `make` the first time, I edit `paper.Rmd`, what steps run if I run `make` again?
* What about editing `Fig1/fig.R`?
---
## Variables
Like R or other language we can define variables
```make
R_OPTS=--no-save --no-restore --no-site-file --no-init-file --no-environ
Fig1/fig.png: Fig1/fig.R
cd Fig1;Rscript $(R_OPTS) fig.R
```
---
## Special Targets
By default is you run `make` without arguments it will attempt to build the *first* target in the `Makefile` (whose name does not start with a `.`). By convention we often include an `all` target which explicitly specifies how to build everything within the project.
`all` is an example of what is called a phony target - because there is no file named `all` in the directory. Other common phony targets:
* clean - remove any files created by the Makefile, restores to the original state
* install - for software packages, installs the compiled programs / libraries / headers
We specify phony targets by including a line with `.PHONY` as the target and the phony targets as dependencies, i.e.:
```make
.PHONY: all clean all
```
---
## Builtin Variables
* `$@` - the file name of the target
* `$<` - the name of the first dependency
* `$^` - the names of all dependencies
* `$(@D)` - the directory part of the target
* `$(@F)` - the file part of the target
* `$(
.center[.large[
Live Demo
]]
---
## Acknowledgments
Above materials are derived in part from the following sources:
* Karl Broman - [minimal make](http://kbroman.org/minimal_make/)