--- title: "Packaging odin models" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Packaging odin models} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} source("helpers.R") ``` You should not use `odin()` 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 `odin_package()` which will generate appropriate code for you. This vignette is based heavily on the packaging vignette in `dust2` (`vignette("packaging", package = "dust")`), as odin uses `dust2`'s machinery for packaging. ```{r} library(odin2) ``` To package odin code, put your odin files in `inst/odin/` within a package and run `odin_package()` on the package's root directory. You can have several odin systems within a single package. ```{r pkg_setup, include = FALSE} path <- odin2:::example_package() ``` 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), `dust2` and `monty` in `LinkingTo`, which allows package compilation to find their respective header files Our `NAMESPACE` file contains: ```{r pkg_ns, echo = FALSE, results = "asis"} plain_output(readLines(file.path(path, "NAMESPACE"))) ``` This `useDynLib` call to your package in the `NAMESPACE` file is required for R to load the compiled code into the package. The file in `inst/odin` is the odin code from `vignette("odin2")`, with `sir.R` containing ```{r pkg_walk, echo = FALSE, results = "asis"} r_output(readLines(file.path(path, "inst/odin/sir.R"))) ``` There can be as many of these files as you want within the directory `inst/odin`. To prepare the package, run `odin_package()`: ```{r pkg_generate} odin_package(path) ``` The directory structure now has more files: ```{r pkg_tree_after, echo = FALSE} withr::with_dir(path, fs::dir_tree()) ``` None of these files should be edited: * `inst/dust/sir.cpp` contains the C++ code generated by odin, used by `dust2` * `src/sir.cpp` is the full code generated in turn by dust * `src/dust.R` contains the R definitions of the dust system * `src/cpp11.cpp` and `R/cpp11.R` are files generated by `cpp11` 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/odin` you should rerun `odin_package()`.