15 Packaging Flow
For better or for worse, there is not a unique recipe to build a package. In other words, there is not a unique sequence of steps that you should always follow in order to take a source package and make it part of the installed packages. In this chapter I will describe an opinionated workflow to pack the source code of our working example.
15.2 Example Structure
The following diagram depicts the filestructure for our working example with the package
Let’s assume that the source package you are developing has the previous structure. If this is not the case for you, at least keep in mind that the mandatory components are
Because a package is made up of various types of files—which can be located in different subdirectories—that play different roles, you can actually break down the overall creation of a package into separate pieces. Interestingly, each of the resulting pieces can be created separately. Consequently, the packaging process that you follow may depend on the piece (or pieces) that need to be built as you add or change components in a package.
The core part of a package is the code in the
R/ directory. Most of the modifications made at this level will very likely have a cascading effect on the rest of elements in the package. From this point of view, a typical packaging workflow involves the following steps:
- Create Documentation
- Check Documentation
- Run Tests
- Knit Vignettes
- Build Bundle
- Install Package
- Check Package
You can use functions from
"devtools" to individually perform each of the actions previously listed. The following table shows such functions.
Note: Assuming that your working directory is the one containing all the files and subdirectories of your package, you can invoke the
devtools functions from the console.
Create Documentation: When you change the roxygen comments of your functions, you will need to (re)generate the corresponding manual documentation. This can be done with the function
devtools::document() which generates the so-called
.Rd (R documentation) files, located in the
Check Documentation: An optional, but strongly recommended, step after new documentation has been generated, is to check that it is correct. This step becomes mandatory if you plan to share your package via CRAN. To check that the
.Rd files are okay, use the function
devtools::check_man(). This function inspects that the content and syntax of the
.Rd files are correct. A typical cause for this check-up to fail is when you have typos or inconsistencies. For example: when the definition of a function contains the argument
x but your roxygen comment
Run Tests: If your package contains unit-tests, included in the directory
tests/, you can use the function
devtools::test() to run such tests.
Build Vignettes: If your package contains vignettes, included in the directory
vignettes/, you can use the function
devtools::build_vignettes() to build them. This function generates the vignettes by knitting the
.Rmd files in the
vignettes/ directory, and it will produce output files in the
Build Bundle: If you just simply want to convert a package source into a single bundled file, you use the function
devtools::build(). This function will create, by default, the
.tar.gz file that in turn can be installed on any platform.
To create a binary package, you have to use the argument
binary = TRUE. Keep in mind that this generated binary will be platform specific, and will only be installable on the current platform. Most of the time, there is no need to create a binary package.
build() does not generate or check any documentation. It also does not run any tests. However,
build() does build vignettes by default.
Install: To install the package you can use
devtools::install(). This function can install a source, bundle or a binary package. After the installation is done, you should be able to load the package with
library() in order to use its functions, inspect its manual documentation, and read the available vignettes.
Check: Optionally, you can carry out an integral check of the package. This checking is a comprehensive one, and it will verify pretty much every single detail.
15.3.1 Optional devtools file
Unless you are constantly creating packages, you will very likely forget what functions to use for a specific purpose. One small hack that I tend to use is to include an auxiliary
.R file in the source package, which I typically name as
devtools-flow.R (or something like that). This file basically contains the list of
"devtools" functions that we’ve discussed so far. The following code shows the typical commands of the auxiliary file:
# ===================================================== # Devtools workflow # ===================================================== devtools::document() # generate documentation devtools::check_man() # check documentation devtools::test() # run tests devtools::build_vignettes() # build vignettes devtools::build() # build bundle devtools::install() # install package devtools::check() # comprehensive check (optional)
You can think of this auxiliary file, e.g.
devtools-flow.R, as a cheat-sheet. But keep in mind that this is an additional file that the building functions are NOT expecting to find. That’s why you should include the name of this file in your
Add a new line with the name of the file to
.Rbuildignore, and remember to anchor it with the caret
^ character. Here’s what your
.Rbuildignore file may look like:
^.*\.Rproj$ ^\.Rproj\.user$ ^devtools-flow.R
I should also say that the inclusion of a
devtools-flow.R file is completely optional, and there are actually more efficient (but also more advanced/complex) ways to add a master script that you execute in a programmatic way everytime something new has to be built.
15.3.2 RStudio Build and Check
When you use an RStudio R.project, you will see that the pane containing the Environment, History, and Connections, will show one additonal tab called Build.
This tab displays three buttons:
- Install and Restart
The Install and Restart button will install and reload your package, starting a fresh session.
The Check button will perform a comprehensive check of your package.
The Build button shows more building options.
15.3.3 Sample Package
You can find the source package of
"cointoss" in the following github repository:
Feel free to download (or clone) the repository and modify its contents to experiment and practice how to create an R package.
Happy packaging and … May the FoRce be with You!
Make a donation
If you find this resource useful, please consider making a one-time donation in any amount. Your support really matters.