├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ └── bookdown.yaml ├── .gitignore ├── README.md ├── _bookdown.yml ├── _output.yml ├── book.bib ├── header-only.Rmd ├── index.Rmd ├── introduction.Rmd ├── packages.bib ├── preamble.tex ├── r-extensions.Rproj ├── renv.lock ├── renv └── activate.R ├── standalone.Rmd ├── style.css └── top-level.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^renv$ 2 | ^renv\.lock$ 3 | ^\.github$ 4 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/bookdown.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: master 4 | 5 | name: bookdown 6 | 7 | jobs: 8 | build: 9 | runs-on: macOS-latest 10 | steps: 11 | - name: Checkout repo 12 | uses: actions/checkout@v2 13 | 14 | - name: Setup R 15 | uses: r-lib/actions/setup-r@master 16 | 17 | - name: Install pandoc and pandoc citeproc 18 | run: | 19 | brew install pandoc 20 | brew install pandoc-citeproc 21 | 22 | - name: Cache Renv packages 23 | uses: actions/cache@v1 24 | with: 25 | path: ~/Library/Application Support/renv 26 | key: r-3-${{ hashFiles('renv.lock') }} 27 | restore-keys: r-3- 28 | 29 | - name: Cache bookdown results 30 | uses: actions/cache@v1 31 | with: 32 | path: _bookdown_files 33 | key: bookdown-${{ hashFiles('**/*Rmd') }} 34 | restore-keys: bookdown- 35 | 36 | - name: Install packages 37 | run: | 38 | R -e 'install.packages("renv")' 39 | R -e 'renv::consent(provided = TRUE)' 40 | R -e 'renv::restore()' 41 | 42 | - name: Build site 43 | run: Rscript -e 'bookdown::render_book("index.Rmd", quiet = TRUE)' 44 | 45 | - name: Install npm 46 | uses: actions/setup-node@v1 47 | 48 | - name: Deploy to Netlify 49 | # NETLIFY_AUTH_TOKEN and NETLIFY_SITE_ID added in the repo's secrets 50 | env: 51 | NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }} 52 | NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }} 53 | run: | 54 | npm install netlify-cli -g 55 | netlify deploy --prod --dir _book 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rhistory 2 | .RData 3 | .Rproj.user 4 | _book 5 | _bookdown_files 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This will hopefully become a small book of examples on how to embed different types of C++ third party libraries into an R package. -------------------------------------------------------------------------------- /_bookdown.yml: -------------------------------------------------------------------------------- 1 | book_filename: "r-extensions" 2 | delete_merged_file: true 3 | language: 4 | ui: 5 | chapter_name: "Chapter " 6 | 7 | rmd_files: 8 | [ 9 | "index.Rmd", 10 | 11 | "introduction.Rmd", 12 | 13 | "header-only.Rmd", 14 | "top-level.Rmd", 15 | "standalone.Rmd" 16 | ] -------------------------------------------------------------------------------- /_output.yml: -------------------------------------------------------------------------------- 1 | bookdown::gitbook: 2 | css: style.css 3 | config: 4 | toc: 5 | before: | 6 |
  • R Extensions
  • 7 | after: | 8 |
  • Published with bookdown
  • 9 | download: ["pdf", "epub"] 10 | bookdown::pdf_book: 11 | includes: 12 | in_header: preamble.tex 13 | latex_engine: xelatex 14 | citation_package: natbib 15 | keep_tex: yes 16 | bookdown::epub_book: default 17 | -------------------------------------------------------------------------------- /book.bib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavisVaughan/r-extensions/9e8e611337ea2d5fbabff3d92685bbccd24305e2/book.bib -------------------------------------------------------------------------------- /header-only.Rmd: -------------------------------------------------------------------------------- 1 | # Header Only {#header-only} 2 | -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "R Extensions" 3 | author: "Davis Vaughan" 4 | date: "`r Sys.Date()`" 5 | site: bookdown::bookdown_site 6 | documentclass: book 7 | bibliography: [book.bib, packages.bib] 8 | biblio-style: apalike 9 | link-citations: yes 10 | description: "This is a book of examples for embedding different types of third party C++ libraries into R packages." 11 | --- 12 | 13 | # Welcome {-#welcome} 14 | 15 | Some intro stuff here.... -------------------------------------------------------------------------------- /introduction.Rmd: -------------------------------------------------------------------------------- 1 | # Introduction {#intro} 2 | 3 | Some introduction material here... -------------------------------------------------------------------------------- /packages.bib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DavisVaughan/r-extensions/9e8e611337ea2d5fbabff3d92685bbccd24305e2/packages.bib -------------------------------------------------------------------------------- /preamble.tex: -------------------------------------------------------------------------------- 1 | \usepackage{booktabs} 2 | -------------------------------------------------------------------------------- /r-extensions.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | StripTrailingWhitespace: Yes 16 | 17 | BuildType: Website 18 | -------------------------------------------------------------------------------- /renv.lock: -------------------------------------------------------------------------------- 1 | { 2 | "R": { 3 | "Version": "3.6.0", 4 | "Repositories": [ 5 | { 6 | "Name": "CRAN", 7 | "URL": "https://cran.rstudio.com" 8 | } 9 | ] 10 | }, 11 | "Packages": { 12 | "Rcpp": { 13 | "Package": "Rcpp", 14 | "Version": "1.0.4.6", 15 | "Source": "Repository", 16 | "Repository": "CRAN", 17 | "Hash": "e652f23d8b1807cc975c51410d05b72f" 18 | }, 19 | "base64enc": { 20 | "Package": "base64enc", 21 | "Version": "0.1-3", 22 | "Source": "Repository", 23 | "Repository": "CRAN", 24 | "Hash": "543776ae6848fde2f48ff3816d0628bc" 25 | }, 26 | "bookdown": { 27 | "Package": "bookdown", 28 | "Version": "0.18", 29 | "Source": "Repository", 30 | "Repository": "CRAN", 31 | "Hash": "72e9c52caf3f7aacb4e368b75f6ec72a" 32 | }, 33 | "digest": { 34 | "Package": "digest", 35 | "Version": "0.6.25", 36 | "Source": "Repository", 37 | "Repository": "CRAN", 38 | "Hash": "f697db7d92b7028c4b3436e9603fb636" 39 | }, 40 | "evaluate": { 41 | "Package": "evaluate", 42 | "Version": "0.14", 43 | "Source": "Repository", 44 | "Repository": "CRAN", 45 | "Hash": "ec8ca05cffcc70569eaaad8469d2a3a7" 46 | }, 47 | "glue": { 48 | "Package": "glue", 49 | "Version": "1.4.0", 50 | "Source": "Repository", 51 | "Repository": "CRAN", 52 | "Hash": "2aefa994e8df5da17dc09afd80f924d5" 53 | }, 54 | "highr": { 55 | "Package": "highr", 56 | "Version": "0.8", 57 | "Source": "Repository", 58 | "Repository": "CRAN", 59 | "Hash": "4dc5bb88961e347a0f4d8aad597cbfac" 60 | }, 61 | "htmltools": { 62 | "Package": "htmltools", 63 | "Version": "0.4.0", 64 | "Source": "Repository", 65 | "Repository": "CRAN", 66 | "Hash": "2d7691222f82f41e93f6d30f169bd5e1" 67 | }, 68 | "jsonlite": { 69 | "Package": "jsonlite", 70 | "Version": "1.6.1", 71 | "Source": "Repository", 72 | "Repository": "CRAN", 73 | "Hash": "84b0ee361e2f78d6b7d670db9471c0c5" 74 | }, 75 | "knitr": { 76 | "Package": "knitr", 77 | "Version": "1.28", 78 | "Source": "Repository", 79 | "Repository": "CRAN", 80 | "Hash": "915a6f0134cdbdf016d7778bc80b2eda" 81 | }, 82 | "magrittr": { 83 | "Package": "magrittr", 84 | "Version": "1.5", 85 | "Source": "Repository", 86 | "Repository": "CRAN", 87 | "Hash": "1bb58822a20301cee84a41678e25d9b7" 88 | }, 89 | "markdown": { 90 | "Package": "markdown", 91 | "Version": "1.1", 92 | "Source": "Repository", 93 | "Repository": "CRAN", 94 | "Hash": "61e4a10781dd00d7d81dd06ca9b94e95" 95 | }, 96 | "mime": { 97 | "Package": "mime", 98 | "Version": "0.9", 99 | "Source": "Repository", 100 | "Repository": "CRAN", 101 | "Hash": "e87a35ec73b157552814869f45a63aa3" 102 | }, 103 | "renv": { 104 | "Package": "renv", 105 | "Version": "0.9.3", 106 | "Source": "Repository", 107 | "Repository": "CRAN", 108 | "Hash": "c1a367437d8a8a44bec4b9d4974cb20c" 109 | }, 110 | "rlang": { 111 | "Package": "rlang", 112 | "Version": "0.4.5", 113 | "Source": "Repository", 114 | "Repository": "CRAN", 115 | "Hash": "1cc1b38e4db40ea6eb19ab8080bbed3b" 116 | }, 117 | "rmarkdown": { 118 | "Package": "rmarkdown", 119 | "Version": "2.1", 120 | "Source": "Repository", 121 | "Repository": "CRAN", 122 | "Hash": "9d1c61d476c448350c482d6664e1b28b" 123 | }, 124 | "stringi": { 125 | "Package": "stringi", 126 | "Version": "1.4.6", 127 | "Source": "Repository", 128 | "Repository": "CRAN", 129 | "Hash": "e99d8d656980d2dd416a962ae55aec90" 130 | }, 131 | "stringr": { 132 | "Package": "stringr", 133 | "Version": "1.4.0", 134 | "Source": "Repository", 135 | "Repository": "CRAN", 136 | "Hash": "0759e6b6c0957edb1311028a49a35e76" 137 | }, 138 | "tinytex": { 139 | "Package": "tinytex", 140 | "Version": "0.21", 141 | "Source": "Repository", 142 | "Repository": "CRAN", 143 | "Hash": "02e11a2e5d05f1d5ab19394f19ab2999" 144 | }, 145 | "xfun": { 146 | "Package": "xfun", 147 | "Version": "0.12", 148 | "Source": "Repository", 149 | "Repository": "CRAN", 150 | "Hash": "ccd8453a7b9e380628f6cd2862e46cad" 151 | }, 152 | "yaml": { 153 | "Package": "yaml", 154 | "Version": "2.2.1", 155 | "Source": "Repository", 156 | "Repository": "CRAN", 157 | "Hash": "2826c5d9efb0a88f657c7a679c7106db" 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /renv/activate.R: -------------------------------------------------------------------------------- 1 | 2 | local({ 3 | 4 | # the requested version of renv 5 | version <- "0.9.3" 6 | 7 | # avoid recursion 8 | if (!is.na(Sys.getenv("RENV_R_INITIALIZING", unset = NA))) 9 | return(invisible(TRUE)) 10 | 11 | # signal that we're loading renv during R startup 12 | Sys.setenv("RENV_R_INITIALIZING" = "true") 13 | on.exit(Sys.unsetenv("RENV_R_INITIALIZING"), add = TRUE) 14 | 15 | # signal that we've consented to use renv 16 | options(renv.consent = TRUE) 17 | 18 | # load the 'utils' package eagerly -- this ensures that renv shims, which 19 | # mask 'utils' packages, will come first on the search path 20 | library(utils, lib.loc = .Library) 21 | 22 | # check to see if renv has already been loaded 23 | if ("renv" %in% loadedNamespaces()) { 24 | 25 | # if renv has already been loaded, and it's the requested version of renv, 26 | # nothing to do 27 | spec <- .getNamespaceInfo(.getNamespace("renv"), "spec") 28 | if (identical(spec[["version"]], version)) 29 | return(invisible(TRUE)) 30 | 31 | # otherwise, unload and attempt to load the correct version of renv 32 | unloadNamespace("renv") 33 | 34 | } 35 | 36 | # construct path to renv in library 37 | libpath <- local({ 38 | 39 | root <- Sys.getenv("RENV_PATHS_LIBRARY", unset = "renv/library") 40 | prefix <- paste("R", getRversion()[1, 1:2], sep = "-") 41 | 42 | # include SVN revision for development versions of R 43 | # (to avoid sharing platform-specific artefacts with released versions of R) 44 | devel <- 45 | identical(R.version[["status"]], "Under development (unstable)") || 46 | identical(R.version[["nickname"]], "Unsuffered Consequences") 47 | 48 | if (devel) 49 | prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") 50 | 51 | file.path(root, prefix, R.version$platform) 52 | 53 | }) 54 | 55 | # try to load renv from the project library 56 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { 57 | 58 | # warn if the version of renv loaded does not match 59 | loadedversion <- utils::packageDescription("renv", fields = "Version") 60 | if (version != loadedversion) { 61 | 62 | # assume four-component versions are from GitHub; three-component 63 | # versions are from CRAN 64 | components <- strsplit(loadedversion, "[.-]")[[1]] 65 | remote <- if (length(components) == 4L) 66 | paste("rstudio/renv", loadedversion, sep = "@") 67 | else 68 | paste("renv", loadedversion, sep = "@") 69 | 70 | fmt <- paste( 71 | "renv %1$s was loaded from project library, but renv %2$s is recorded in lockfile.", 72 | "Use `renv::record(\"%3$s\")` to record this version in the lockfile.", 73 | "Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.", 74 | sep = "\n" 75 | ) 76 | 77 | msg <- sprintf(fmt, loadedversion, version, remote) 78 | warning(msg, call. = FALSE) 79 | 80 | } 81 | 82 | # load the project 83 | return(renv::load()) 84 | 85 | } 86 | 87 | # failed to find renv locally; we'll try to install from GitHub. 88 | # first, set up download options as appropriate (try to use GITHUB_PAT) 89 | install_renv <- function() { 90 | 91 | message("Failed to find installation of renv -- attempting to bootstrap...") 92 | 93 | # ensure .Rprofile doesn't get executed 94 | rpu <- Sys.getenv("R_PROFILE_USER", unset = NA) 95 | Sys.setenv(R_PROFILE_USER = "") 96 | on.exit({ 97 | if (is.na(rpu)) 98 | Sys.unsetenv("R_PROFILE_USER") 99 | else 100 | Sys.setenv(R_PROFILE_USER = rpu) 101 | }, add = TRUE) 102 | 103 | # prepare download options 104 | pat <- Sys.getenv("GITHUB_PAT") 105 | if (nzchar(Sys.which("curl")) && nzchar(pat)) { 106 | fmt <- "--location --fail --header \"Authorization: token %s\"" 107 | extra <- sprintf(fmt, pat) 108 | saved <- options("download.file.method", "download.file.extra") 109 | options(download.file.method = "curl", download.file.extra = extra) 110 | on.exit(do.call(base::options, saved), add = TRUE) 111 | } else if (nzchar(Sys.which("wget")) && nzchar(pat)) { 112 | fmt <- "--header=\"Authorization: token %s\"" 113 | extra <- sprintf(fmt, pat) 114 | saved <- options("download.file.method", "download.file.extra") 115 | options(download.file.method = "wget", download.file.extra = extra) 116 | on.exit(do.call(base::options, saved), add = TRUE) 117 | } 118 | 119 | # fix up repos 120 | repos <- getOption("repos") 121 | on.exit(options(repos = repos), add = TRUE) 122 | repos[repos == "@CRAN@"] <- "https://cloud.r-project.org" 123 | options(repos = repos) 124 | 125 | # check for renv on CRAN matching this version 126 | db <- as.data.frame(available.packages(), stringsAsFactors = FALSE) 127 | if ("renv" %in% rownames(db)) { 128 | entry <- db["renv", ] 129 | if (identical(entry$Version, version)) { 130 | message("* Installing renv ", version, " ... ", appendLF = FALSE) 131 | dir.create(libpath, showWarnings = FALSE, recursive = TRUE) 132 | utils::install.packages("renv", lib = libpath, quiet = TRUE) 133 | message("Done!") 134 | return(TRUE) 135 | } 136 | } 137 | 138 | # try to download renv 139 | message("* Downloading renv ", version, " ... ", appendLF = FALSE) 140 | prefix <- "https://api.github.com" 141 | url <- file.path(prefix, "repos/rstudio/renv/tarball", version) 142 | destfile <- tempfile("renv-", fileext = ".tar.gz") 143 | on.exit(unlink(destfile), add = TRUE) 144 | utils::download.file(url, destfile = destfile, mode = "wb", quiet = TRUE) 145 | message("Done!") 146 | 147 | # attempt to install it into project library 148 | message("* Installing renv ", version, " ... ", appendLF = FALSE) 149 | dir.create(libpath, showWarnings = FALSE, recursive = TRUE) 150 | 151 | # invoke using system2 so we can capture and report output 152 | bin <- R.home("bin") 153 | exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" 154 | r <- file.path(bin, exe) 155 | args <- c("--vanilla", "CMD", "INSTALL", "-l", shQuote(libpath), shQuote(destfile)) 156 | output <- system2(r, args, stdout = TRUE, stderr = TRUE) 157 | message("Done!") 158 | 159 | # check for successful install 160 | status <- attr(output, "status") 161 | if (is.numeric(status) && !identical(status, 0L)) { 162 | text <- c("Error installing renv", "=====================", output) 163 | writeLines(text, con = stderr()) 164 | } 165 | 166 | 167 | } 168 | 169 | try(install_renv()) 170 | 171 | # try again to load 172 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { 173 | message("Successfully installed and loaded renv ", version, ".") 174 | return(renv::load()) 175 | } 176 | 177 | # failed to download or load renv; warn the user 178 | msg <- c( 179 | "Failed to find an renv installation: the project will not be loaded.", 180 | "Use `renv::activate()` to re-initialize the project." 181 | ) 182 | 183 | warning(paste(msg, collapse = "\n"), call. = FALSE) 184 | 185 | }) 186 | -------------------------------------------------------------------------------- /standalone.Rmd: -------------------------------------------------------------------------------- 1 | # Standalone Libraries {#standalone} 2 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | p.caption { 2 | color: #777; 3 | margin-top: 10px; 4 | } 5 | p code { 6 | white-space: inherit; 7 | } 8 | pre { 9 | word-break: normal; 10 | word-wrap: normal; 11 | } 12 | pre code { 13 | white-space: inherit; 14 | } 15 | -------------------------------------------------------------------------------- /top-level.Rmd: -------------------------------------------------------------------------------- 1 | # Top Level Embedding {#top-level} 2 | --------------------------------------------------------------------------------