#' Compile Rust code and generate package documentation.
#'
#' The function `rextendr::document()` updates the package documentation for an
#' R package that uses `extendr` code, taking into account any changes that were
#' made in the Rust code. It is a wrapper for [devtools::document()], and it
#' executes `extendr`-specific routines before calling [devtools::document()].
#' Specifically, it ensures that Rust code is recompiled (when necessary) and that
#' up-to-date R wrappers are generated before regenerating the package documentation.
#' @inheritParams devtools::document
#' @return No return value, called for side effects.
#' @export
document <- function(pkg = ".", quiet = FALSE, roclets = NULL) {
try_save_all(quiet = quiet)
withr::local_envvar(devtools::r_env_vars())
register_extendr(path = pkg, quiet = quiet)
rlang::check_installed("devtools")
devtools::document(pkg = pkg, roclets = roclets, quiet = quiet)
if (!isTRUE(quiet)) {
check_namespace_file(pkg)
}
}
check_if_roxygen_used <- function(namespace_content) {
any(stringi::stri_startswith_fixed(namespace_content, "# Generated by roxygen2:"))
}
check_if_dyn_lib_used <- function(namespace_content, pkg_name) {
expected_pattern <- glue::glue("useDynLib\\({pkg_name},\\s*\\.registration = TRUE\\)")
any(stringi::stri_detect_regex(namespace_content, expected_pattern))
}
check_namespace_file <- function(path = ".") {
namespace_file_path <- rprojroot::find_package_root_file("NAMESPACE", path = path)
description_file_path <- rprojroot::find_package_root_file("DESCRIPTION", path = path)
package_name <- desc::desc_get_field("Package", file = description_file_path)
namespace_content <- brio::read_lines(namespace_file_path)
namespace_content <- stringi::stri_trim_both(namespace_content[nzchar(namespace_content)])
is_roxygen_used <- check_if_roxygen_used(namespace_content)
is_dyn_lib_used <- check_if_dyn_lib_used(namespace_content, package_name)
if (!is_dyn_lib_used) {
roxygen_message <- ifelse(is_roxygen_used, NULL,
paste(
"Alternatively, allow {.pkg roxygen2} to generate {.file NAMESPACE} exports for you.",
"Annotate exported functions with {.code # @export} directive,",
"delete the {.file NAMESPACE} file and run {.code rextendr::document()} again to regenerate exports."
)
)
use_dyn_lib_ref <- glue::glue("useDynLib({package_name}, .registration = TRUE)") # nolint: object_usage_linter.
cli::cli_warn(
c(
"The {.file NAMESPACE} file does not contain the expected {.code useDynLib} directive.",
"x" = "This prevents your package from loading Rust code.",
"*" = "Add the following line to the {.file NAMESPACE} file: {.code {use_dyn_lib_ref}}",
"*" = roxygen_message
)
)
}
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.