---
title: "Packaging dust systems"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Packaging dust systems}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
source("support.R")
set.seed(1)
```

You should not use `dust_compile()` within a package, because that would cause the model to compile each time you use it, rather than when the package builds.  It may also cause issues when trying to use the model in parallel (e.g., with the `parallel` package), and will require all users of your code to have a full C++ toolchain.  Instead you should use `dust_package()` which will generate appropriate code for you.

```{r}
library(dust2)
```

To use dust in a package, put your dust source files in `inst/dust` and run `dust_package()` on the package's root directory.  You can have several dust systems within a single package.

```{r pkg_setup, include = FALSE}
desc <- c(
  "Package: example",
  "Title: Example Dust in a Package",
  "Version: 0.0.1",
  "Imports: dust2",
  "LinkingTo: cpp11, dust2, monty",
  "Authors@R: c(person('A', 'Person', role = c('aut', 'cre')",
  "                     email = 'person@example.com'))",
  "License: CC0")
ns <- "useDynLib('example', .registration = TRUE)"

path <- tempfile()
dir.create(path)
dir.create(file.path(path, "inst/dust"), FALSE, TRUE)
writeLines(desc, file.path(path, "DESCRIPTION"))
writeLines(ns, file.path(path, "NAMESPACE"))
stopifnot(file.copy("examples/walk.cpp", file.path(path, "inst/dust")))
```

A skeleton package might contain:

```{r pkg_tree, echo = FALSE}
withr::with_dir(path, fs::dir_tree())
```

This is the normal R package skeleton, though missing `R/` and `src/` directories (for now).  The `DESCRIPTION` file contains

```{r pkg_desc, echo = FALSE, results = "asis"}
plain_output(readLines(file.path(path, "DESCRIPTION")))
```

The important things here are:

* the package name (`Package`). We're using `example`, and names with a dot may not work as expected
* including [`cpp11`](https://github.com/r-lib/cpp11) and `dust` in `LinkingTo`, which allows package compilation to find their respective header files
* a `useDynLib` call to your package in the `NAMESPACE` file

Our `NAMESPACE` file contains:

```{r pkg_ns, echo = FALSE, results = "asis"}
plain_output(readLines(file.path(path, "NAMESPACE")))
```

The files in `inst/dust` are the same files as seen above, with `walk.cpp` containing

```{r pkg_walk, echo = FALSE, results = "asis"}
cc_output(readLines(file.path(path, "inst/dust/walk.cpp")))
```

There can be as many of these files as you want within the directory `inst/dust`.

To prepare the package, run `dust_package()`:

```{r pkg_generate}
dust_package(path)
```

The directory structure now has more files:

```{r pkg_tree_after, echo = FALSE}
withr::with_dir(path, fs::dir_tree())
```

The file `src/walk.cpp` is generated by dust and should not be edited. They include your model, but also a bit of helper code:

```{r pkg_walk_c, echo = FALSE, results = "asis"}
cc_output(readLines(file.path(path, "src/walk.cpp")))
```

The file `R/dust.R` contains the R interface generated by dust with the constructor objects (all models' constructors will be collected into this file, which also should not be edited).

```{r pkg_dust_r, echo = FALSE, results = "asis"}
r_output(readLines(file.path(path, "R/dust.R")))
```

Finally, `R/cpp11.R` and `src/cpp11.cpp` are files created by cpp11 that should not be edited.

Your package can include as much R code as you want, and can be developed like any other R package. But any time you change the code in `inst/dust` you should rerun `dust_package()`.
