In the (GNU) make jargon, a rule is a sequence of commands to build a result. In this package, a rule
should be understood similarly: It is a command or a sequence of commands that optionally produces some
files and depends on some other files (such as data files or scripts) or other rules. Moreover, a rule
contains a command for cleanup, i.e., for removal of generated files.
Usage
makefile(
job = list(),
fileName = NULL,
makeScript = "Makefile.R",
vars = NULL,
all = TRUE,
tasks = TRUE,
clean = TRUE,
makefile = TRUE,
depends = NULL
)Arguments
- job
A list of rules (i.e., instances of the S3 class
rmake.rule- seerule())- fileName
A file to write to. If
NULL, the result is returned as a character vector instead of writing to a file.- makeScript
The name of the file that calls this function (used to generate the
makefilerule)- vars
A named character vector of shell variables that will be declared in the resulting Makefile (in addition to
[defaultVars])- all
TRUEif theallrule should be automatically created and added: the createdallrule has dependencies on all the other rules, which causes everything to be built ifmake allis executed in the shell's command line.- tasks
TRUEif "task" rules should be automatically created and added – seerule()for more details.- clean
TRUEif thecleanrule should be automatically created and added- makefile
TRUEif theMakefilerule should be automatically created and added: this rule ensures that any change in the R script that generates theMakefile(i.e., that callsmakefile()) triggers the re-generation of the Makefile at the beginning of any build.- depends
A character vector of file names that the makefile generating script depends on
Value
If fileName is NULL, the function returns a character vector with the contents of the
Makefile. Otherwise, the content is written to the given fileName.
Details
The makefile() function takes a list of rules (see rule()) and generates a Makefile from them.
Additionally, all and clean rules are optionally generated too, which can be executed from the shell
by issuing the make all or make clean command, respectively, to build everything or erase all
generated files.
If there is a need to group some rules together, it can be done either via dependencies or by using
the task mechanism. Each rule may be assigned one or more tasks (see task in rule()). Each
task is then created as a standalone rule depending on the assigned rules. That way, executing make task_name
will build all rules with the assigned task task_name. By default, all rules are assigned to task all,
which allows make all to build everything.
Examples
# create some jobs
job <- list(
rRule('dataset.rds', 'preprocess.R', 'dataset.csv'),
markdownRule('report.pdf', 'report.Rmd', 'dataset.rds'),
markdownRule('details.pdf', 'details.Rmd', 'dataset.rds'))
# generate Makefile (output as a character vector)
makefile(job)
#> [1] "# This file is generated by rmake - do not edit by hand"
#> [2] "ifeq ($(origin .FEATURES),undefined)"
#> [3] "$(error This Makefile requires GNU Make. Please install it and use 'gmake' or 'make' depending on your system)"
#> [4] "endif"
#> [5] "REQUIRED_VERSION := 3.82"
#> [6] "ifeq ($(filter $(REQUIRED_VERSION),$(firstword $(sort $(MAKE_VERSION) $(REQUIRED_VERSION)))),)"
#> [7] "$(error GNU Make $(REQUIRED_VERSION) or higher is required. You are using $(MAKE_VERSION))"
#> [8] "endif"
#> [9] "SHELL=/bin/sh"
#> [10] "R=\"$(R_HOME)/bin$(R_ARCH)/Rscript\""
#> [11] "RM=rm"
#> [12] "CP=cp"
#> [13] ".ONESHELL:"
#> [14] ""
#> [15] ".PHONY: all"
#> [16] "all: Makefile dataset.rds report.pdf details.pdf"
#> [17] "\t"
#> [18] "dataset.rds: preprocess.R dataset.csv"
#> [19] "\t$(R) - <<'EOFrmake'"
#> [20] "\t{"
#> [21] "\t params <- list(.target = \"dataset.rds\", .script = \"preprocess.R\", .depends = \"dataset.csv\", .task = \"all\")"
#> [22] "\t source(\"preprocess.R\")"
#> [23] "\t}"
#> [24] "\tEOFrmake"
#> [25] "report.pdf: report.Rmd dataset.rds"
#> [26] "\t$(R) - <<'EOFrmake'"
#> [27] "\t{"
#> [28] "\t params <- list(.target = \"report.pdf\", .script = \"report.Rmd\", .depends = \"dataset.rds\", .task = \"all\")"
#> [29] "\t targets <- list(report.pdf = \"pdf_document\")"
#> [30] "\t for (tg in names(targets)) {"
#> [31] "\t rmarkdown::render(\"report.Rmd\", output_format = targets[[tg]], output_file = tg)"
#> [32] "\t }"
#> [33] "\t}"
#> [34] "\tEOFrmake"
#> [35] "details.pdf: details.Rmd dataset.rds"
#> [36] "\t$(R) - <<'EOFrmake'"
#> [37] "\t{"
#> [38] "\t params <- list(.target = \"details.pdf\", .script = \"details.Rmd\", .depends = \"dataset.rds\", .task = \"all\")"
#> [39] "\t targets <- list(details.pdf = \"pdf_document\")"
#> [40] "\t for (tg in names(targets)) {"
#> [41] "\t rmarkdown::render(\"details.Rmd\", output_format = targets[[tg]], output_file = tg)"
#> [42] "\t }"
#> [43] "\t}"
#> [44] "\tEOFrmake"
#> [45] ".PHONY: clean"
#> [46] "clean: "
#> [47] "\t$(RM) dataset.rds"
#> [48] "\t$(RM) report.pdf"
#> [49] "\t$(RM) details.pdf"
#> [50] "Makefile: Makefile.R"
#> [51] "\t$(R) - <<'EOFrmake'"
#> [52] "\t{"
#> [53] "\t params <- list(.target = \"Makefile\", .script = \"Makefile.R\", .depends = NULL, .task = \"all\")"
#> [54] "\t source(\"Makefile.R\")"
#> [55] "\t}"
#> [56] "\tEOFrmake"
# generate to file
tmp <- tempdir()
makefile(job, file.path(tmp, "Makefile"))