---
title: "Creating Makefiles"
author: "Kirill Müller"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Creating Makefiles}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, echo = FALSE}
library(magrittr)
knitr::opts_chunk$set(
  comment = "#>",
  fig.path = "README-"
)
knit_print.MakefileR <- function(x, options) {
  knitr::knit_print(
    c("``` Makefile",
      format(x) %>% gsub("\t", "⇥      ", .),
      "```") %>%
      paste(">", ., collapse = "\n") %>%
      knitr::asis_output(), options)
}
```

[GNU Make](https://www.gnu.org/software/make) is a standard tool to define
transformation rules.
Each rule consists of a (list of) targets which may depend on one or more
source files, and optionally a script that needs to be executed to create
the target.
A `Makefile` is essentially a collection of such rules.

> Make figures out automatically which files it needs to update, based on which source files have changed. ...
As a result, if you change a few source files and then run Make, it does not need to [redo all the work]. It updates only those non-source files that depend directly or indirectly on the source files that you changed.

Make is readily available on all major platforms,
also [on Microsoft Windows](http://gnuwin32.sourceforge.net/packages/make.htm).
The `MakefileR` package helps creating `Makefile` files programmatically
from R.
The following sections show a few examples and the corresponding output.

## Creating rules

```{r}
library(MakefileR)
make_rule("all", c("first_target", "second_target"))

make_rule(".FORCE")

make_rule("first_target", ".FORCE", "echo 'Building first target'")

make_rule("second_target", "first_target",
  c("echo 'Building second target'", "echo 'Done'"))
```

## Creating definitions

```{r}
make_def("R_VERSION", R.version.string)
```

## Creating groups

```{r}
make_group(make_comment("Definitions")) +
  make_def("R_VERSION", R.version.string) +
  make_def("R_PLATFORM", R.version$platform)
```

## Creating Makefile files

```{r}
makefile() +
  make_group(
    make_comment("Definitions"),
    make_def("R_VERSION", R.version.string)
  ) +
  make_group(
    make_comment("Universal rule"),
    make_rule("all", c("first_target", "second_target"))
  ) +
  make_group(
    make_comment("Special rule"),
    make_rule(".FORCE")
  ) +
  make_comment(c("============", "Action rules", "============")) +
  make_rule("first_target", ".FORCE", "echo 'Building first target'") +
  make_rule("second_target", "first_target",
    c("echo 'Building second target'", "echo 'Done'"))
```

