Skip to content

Commit

Permalink
Merge pull request #13 from wlandau/12
Browse files Browse the repository at this point in the history
Use install.libs.R instead of configure
  • Loading branch information
wlandau committed Jan 4, 2024
2 parents f910e35 + 482fb36 commit 02d35e8
Show file tree
Hide file tree
Showing 57 changed files with 774 additions and 971 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/install-internal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@ jobs:
install-internal:
runs-on: ubuntu-latest

env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Change the script so CmdStan always installs internally.
run: sed -i '2s/.*/if (TRUE) {/' inst/cmdstan.R
run: sed -i '1s/.*/choice <- "internal"/' src/install.libs.R

- name: Remove GitHub Actions workflow files
run: rm -rf .github/workflws
run: rm -rf .github/workflows

- name: Deploy to install-internal branch
if: github.event_name != 'pull_request'
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ vignettes/*.html
revdep
cmdstan
*.dll
Makevars
Makevars.win
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Description: Similar to 'rstantools' for 'rstan',
and setting environment variables.
Packages 'rstantools', 'cmdstanr', 'stannis', and
'stanapi' are similar Stan clients with different objectives.
Version: 0.0.4.9000
Version: 0.0.4.9001
License: MIT + file LICENSE
URL: https://wlandau.github.io/instantiate/,
https://github.com/wlandau/instantiate
Expand All @@ -36,7 +36,6 @@ Depends:
R (>= 4.0.0)
Imports:
fs,
pkglite,
rlang,
utils
Suggests:
Expand All @@ -49,6 +48,7 @@ Suggests:
Additional_repositories:
https://mc-stan.org/r-packages/
SystemRequirements: CmdStan (https://mc-stan.org/users/interfaces/cmdstan)
StagedInstall: no
Encoding: UTF-8
Language: en-US
Config/testthat/edition: 3
Expand Down
1 change: 0 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export(stan_package_create)
export(stan_package_model)
export(stan_package_model_files)
importFrom(fs,dir_copy)
importFrom(pkglite,unpack)
importFrom(rlang,abort)
importFrom(rlang,check_installed)
importFrom(rlang,inform)
Expand Down
6 changes: 4 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# instantiate 0.0.4.9000 (development)

# instantiate 0.0.4.9001 (development)

* Use `install.libs.R` for both CmdStan in `instantiate` and Stan model compilation in packages (#1, #9, #12).
* Stan models should now be in `src/stan/` instead of `inst/stan/` (#12). `inst/stan/` should still work for the next few versions, but it is now deprecated. When a modeling package is installed, its `install.libs.R` moves `src/stan/` to `bin/stan/` and then compiles models inside `bin/stan/`.
* Disable staged installation for `instantiate` itself to help the hard-coded paths in CmdStan work as expected in "internal" installation.

# instantiate 0.0.4

Expand Down
2 changes: 1 addition & 1 deletion R/stan_cmdstan_exists.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#' @examples
#' stan_cmdstan_exists()
stan_cmdstan_exists <- function(
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL")
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "")
) {
path <- stan_cmdstan_path(cmdstan_install = cmdstan_install)
cmdstan_valid(path)
Expand Down
65 changes: 33 additions & 32 deletions R/stan_cmdstan_path.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,50 @@
#' @return Character of length 1, directory path to CmdStan. The path
#' may or may not exist. Returns the empty string `""` if the path
#' cannot be determined.
#' @param cmdstan_install Character of length 1, how CmdStan was installed. The
#' installation method determines how `instantiate` looks up CmdStan.
#' Set the default value with the `CMDSTAN_INSTALL` environment variable.
#' @param cmdstan_install Character of length 1, how to look for an installed
#' copy of CmdStan. See <https://wlandau.github.io/instantiate/> for details.
#' Choices:
#' 1. `"internal"`: Use the copy of CmdStan installed internally inside the
#' `instantiate` package file system. Before using this option,
#' CmdStan must be installed in the package file system. To do this,
#' set the `CMDSTAN_INSTALL` environment variable to `"internal"` before
#' installing `instantiate`.
#' 2. `"fixed"`: Use the copy of CmdStan that was located at the value
#' contained in `Sys.getenv("CMDSTAN")` at the time `instantiate`
#' was installed. In this case, the path to CmdStan is not inside
#' `instantiate` itself, but it is fixed at installation time
#' and does not depend on the current value of
#' `Sys.getenv("CMDSTAN")` at runtime.
#' 3. `"cmdstanr"`: Let the `cmdstanr::cmdstan_path()` decide where
#' to look for CmdStan. The `cmdstanr` package must be installed. If it
#' is not installed, the function returns the empty string `""`.
#' 4. `""` (default): Try all 3 options in the order above to find a valid
#' installed copy of CmdStan.
#' 1. `""` (default): look at the original value that the `CMDSTAN_INSTALL`
#' environment variable contained when `instantiate` at the time
#' when it was installed.
#' If it was `"implicit"`, `"fixed"`, or `"internal"`, then choose
#' the corresponding option below. Otherwise, default to `"internal"`.
#' 2. `"implicit"`: Let the `cmdstanr::cmdstan_path()` decide where
#' to look for CmdStan. As explained in the `cmdstanr` documentation,
#' the output of `cmdstanr::cmdstan_path()` depends
#' on the current value of the `CMDSTAN` environment variable.
#' The `cmdstanr` package must be installed. If it
#' is not installed, then `stan_cmdstan_path()`
#' returns the empty string `""`.
#' 3. `"fixed"`: Use the path to CmdStan that was originally
#' contained in `Sys.getenv("CMDSTAN")` at the time when `instantiate`
#' was installed.
#' 4. `"internal"`: Use the copy of CmdStan installed internally inside the
#' `instantiate` package file system. To use this option,
#' `instantiate` needs to have been originally installed with the
#' `CMDSTAN_INSTALL` environment variable set to `"internal"`.
#' @examples
#' stan_cmdstan_path()
stan_cmdstan_path <- function(
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL")
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "")
) {
# It is not feasible to test all these cases in a single test coverage run.
# Covered in several GitHub Actions workflows.
# nocov start
install <- stan_cmdstan_install(cmdstan_install)
if (identical(install, "internal") || identical(install, "")) {
parent <- system.file("cmdstan", package = "instantiate", mustWork = FALSE)
out <- file.path(parent, list.files(parent)) %||% ""
}
if (identical(install, "fixed") || path_next(install, out)) {
out <- .Call(c_cmdstan_path)
install <- cmdstan_install
if (identical(install, "")) {
install <- .Call(c_cmdstan_path_install, PACKAGE = "instantiate")
}
if (identical(install, "cmdstanr") || path_next(install, out)) {
stan_assert_install(install)
if (identical(install, "implicit") || identical(install, "")) {
out <- cmdstanr_path()
} else if (identical(install, "fixed")) {
out <- .Call(c_cmdstan_path_fixed, PACKAGE = "instantiate")
} else if (identical(install, "internal")) {
bin <- system.file("bin", package = "instantiate", mustWork = FALSE)
parent <- file.path(bin, "cmdstan")
out <- file.path(parent, list.files(parent)) %||% ""
}
# nocov end
out
}

path_next <- function(install, out) {
identical(install, "") && !any(dir.exists(out))
}
2 changes: 1 addition & 1 deletion R/stan_cmdstan_version.R
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#' message(stan_cmdstan_version())
#' }
stan_cmdstan_version <- function(
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL"),
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""),
error_on_NA = TRUE
) {
stan_assert_cmdstanr()
Expand Down
1 change: 0 additions & 1 deletion R/stan_package.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#' diagnosing compilation errors, and setting environment variables.
#' @useDynLib instantiate, .registration = TRUE
#' @importFrom fs dir_copy
#' @importFrom pkglite unpack
#' @importFrom rlang abort check_installed inform is_installed warn
#' @importFrom utils capture.output globalVariables install.packages
NULL
Expand Down
8 changes: 4 additions & 4 deletions R/stan_package_compile.R
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
#' @family packages
#' @description Compile all Stan models in a directory, usually in a package.
#' @details If building a package using `instantiate`, all Stan model files
#' must live in a folder called `inst/stan/` in the package source
#' must live in a folder called `src/stan/` in the package source
#' directory.
#' @return `NULL` (invisibly). Called for its side effects.
#' @inheritParams stan_cmdstan_path
#' @param models Character vector of file paths to Stan model source code
#' files. Defaults to the Stan files in `./inst/stan/`
#' because all the Stan model files must live in the `inst/stan/` folder
#' files. Defaults to the Stan files in `./src/stan/`
#' because all the Stan model files must live in the `src/stan/` folder
#' for an R package built with `instantiate`.
#' @param verbose Logical of length 1, whether to set the
#' `cmdstanr_verbose` global option to print more compiler messages
Expand Down Expand Up @@ -43,7 +43,7 @@
#' }
stan_package_compile <- function(
models = instantiate::stan_package_model_files(),
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL"),
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = ""),
verbose = TRUE,
quiet = FALSE,
pedantic = FALSE,
Expand Down
37 changes: 19 additions & 18 deletions R/stan_package_configure.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
#' @export
#' @family packages
#' @description Write configuration files in an R package which
#' compile all the Stan models in `inst/stan/` when the package installs.
#' compile all the Stan models in `src/stan/` when the package installs.
#' @details Writes configuration scripts `configure` and `configure.win`
#' in the directory specified by the `path` argument.
#' @return `NULL` (invisibly). Called for its side effects.
#' @param path Character of length 1, file path to the package which will
#' contain Stan models in `inst/stan/` at installation time.
#' contain Stan models in `src/stan/` at installation time.
#' @param overwrite Logical of length 1, whether to overwrite any existing
#' configuration files.
#' @examples
Expand Down Expand Up @@ -38,20 +38,17 @@ stan_package_configure <- function(path = getwd(), overwrite = FALSE) {
package = "instantiate",
mustWork = TRUE
)
in_configure <- system.file(
file.path("configuration", "configure"),
package = "instantiate",
mustWork = TRUE
)
in_configure_win <- system.file(
file.path("configuration", "configure.win"),
in_install <- system.file(
file.path("configuration", "install.libs.R"),
package = "instantiate",
mustWork = TRUE
)
src <- file.path(path, "src")
out_cleanup <- file.path(path, "cleanup")
out_cleanup_win <- file.path(path, "cleanup.win")
out_configure <- file.path(path, "configure")
out_configure_win <- file.path(path, "configure.win")
out_install <- file.path(src, "install.libs.R")
out_makevars <- file.path(src, "Makevars")
out_makevars_win <- file.path(src, "Makevars.win")
file.copy(
from = in_cleanup,
to = out_cleanup,
Expand All @@ -63,16 +60,20 @@ stan_package_configure <- function(path = getwd(), overwrite = FALSE) {
to = out_cleanup_win,
overwrite = overwrite
)
if (!file.exists(src)) {
dir.create(src)
}
file.copy(
from = in_configure,
to = out_configure,
from = in_install,
to = out_install,
overwrite = overwrite,
copy.mode = TRUE
)
file.copy(
from = in_configure_win,
to = out_configure_win,
overwrite = overwrite
)
if (!file.exists(out_makevars)) {
file.create(out_makevars)
}
if (!file.exists(out_makevars_win)) {
file.create(out_makevars_win)
}
invisible()
}
32 changes: 13 additions & 19 deletions R/stan_package_create.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,25 @@ stan_package_create <- function(path = tempfile()) {
!file.exists(path),
message = "path must be a valid file path that does not already exist."
)
packed <- system.file(
"example.txt",
package = "instantiate",
mustWork = TRUE
source <- system.file("example", package = "instantiate", mustWork = TRUE)
fs::dir_copy(path = source, new_path = path, overwrite = TRUE)
file.rename(
from = file.path(path, "gitignore"),
to = file.path(path, ".gitignore")
)
temp <- tempfile()
on.exit(unlink(x = temp, recursive = TRUE))
pkglite::unpack(
input = packed,
output = temp,
install = FALSE,
quiet = TRUE
file.rename(
from = file.path(path, "rbuildignore"),
to = file.path(path, ".Rbuildignore")
)
temp <- file.path(temp, "example")
fs::dir_copy(
path = temp,
new_path = path,
overwrite = TRUE
file.rename(
from = file.path(path, "github"),
to = file.path(path, ".github")
)
unlink(x = temp, recursive = TRUE)
message(
paste0(
"Package with an internal Stan model created at ",
"Package with an internal Stan model created at directory path \"",
path,
". Configure with stan_package_configure() before installing."
"\". Configure with stan_package_configure() before installing."
)
)
invisible()
Expand Down
26 changes: 24 additions & 2 deletions R/stan_package_model.R
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,38 @@ stan_package_model <- function(
name,
package,
library = NULL,
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL")
cmdstan_install = Sys.getenv("CMDSTAN_INSTALL", unset = "")
) {
stan_assert_cmdstanr()
stan_assert(name, is.character(.), !anyNA(.), nzchar(.))
stan_assert(package, is.character(.), !anyNA(.), nzchar(.))
stan_file <- get(x = "system.file", envir = globalenv()) (
file.path("bin", "stan", paste0(name, ".stan")),
package = package,
lib.loc = library,
mustWork = FALSE
)
stan_file_inst <- get(x = "system.file", envir = globalenv()) (
file.path("stan", paste0(name, ".stan")),
package = package,
lib.loc = library,
mustWork = TRUE
mustWork = FALSE
)
if (file.exists(stan_file_inst)) {
stan_deprecate(
name = "Stan files installed to inst/stan/",
date = "2024-01-03",
version = "0.0.4.9001",
alternative = paste(
"Reinstall your Stan modeling package so your",
"compiled models are in bin/stan/ instead."
)
)
stan_file <- if_any(file.exists(stan_file), stan_file, stan_file_inst)
}
stan_assert(
file.exists(stan_file),
message = sprintf("Stan model file \"%s\" not found.", stan_file)
)
exe_file <- file.path(dirname(stan_file), name)
exe_file <- if_any(stan_on_windows(), paste0(exe_file, ".exe"), exe_file)
Expand Down
14 changes: 9 additions & 5 deletions R/stan_package_model_files.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
#' @export
#' @family packages
#' @description List all the paths to the Stan model files in a package.
#' @details All Stan models must live in the `inst/stan/` directory in the
#' @details All Stan models must live in the `src/stan/` directory in the
#' package file system.
#' @return Character vector of paths to Stan model files in the package.
#' @param path Character of length 1, path to the root directory of the
#' R package with the Stan models.
#' @param path Character of length 1, root path to start from when searching
#' for Stan model files.
#' @examples
#' path <- tempfile()
#' stan_package_create(path = path)
Expand All @@ -20,8 +20,12 @@ stan_package_model_files <- function(path = getwd()) {
length(.) == 1L,
message = "invalid package directory path in stan_package_model_files()"
)
path <- file.path(path, "inst", "stan")
out <- list.files(path, full.names = TRUE, pattern = "\\.stan$")
out <- list.files(
path,
full.names = TRUE,
recursive = TRUE,
pattern = "\\.stan$"
)
stan_assert(
length(out) > 0L,
message = paste0(
Expand Down

0 comments on commit 02d35e8

Please sign in to comment.