15 Packaging Flow
15.1 Introduction
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 cointoss
.

Figure 15.1: Assumed filestructure
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 DESCRIPTION
, NAMESPACE
, R/
and man/
.
15.3 Workflow
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.
Action | Function |
---|---|
Create Documentation | devtools::document() |
Check Documentation | devtools::check_man() |
Run Tests | devtools::test() |
Knit Vignettes | devtools::build_vignettes() |
Build Bundle | devtools::build() |
Install binary | devtools::install() |
Check | devtools::check() |
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 man/
directory.
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 @param
uses y
.
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 inst/
folder.
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 .Rbuildignore
file.
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.

Figure 15.2: Build tab
This tab displays three buttons:
- Install and Restart
- Check
- More
The Install and Restart button will install and reload your package, starting a fresh session.

Figure 15.3: Install icon
The Check button will perform a comprehensive check of your package.

Figure 15.4: Check icon
The Build button shows more building options.

Figure 15.5: Build icon
15.3.3 Sample Package cointoss
You can find the source package of "cointoss"
in the following github repository:
https://github.com/gastonstat/cointoss
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.