Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/R-CMD-check-wsl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
WSL-R-CMD-check:
if: "! contains(github.event.head_commit.message, '[ci skip]')"
runs-on: windows-latest
timeout-minutes: 240

name: windows-latest-WSL2

Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ model. (#1258)
loaded with `readRDS()`. Previously it reported them as already compiled and
calling one failed with a null symbol address, the same defect
`$init_model_methods()` had before #1157.
* A build no longer leaves its copy of the Stan program, the C++ generated from
it and a second copy of the executable in the session's temporary directory.
Checking syntax and reading a program's variables no longer leave stanc's
output there either. (#1258)
* `$log_prob()`, `$grad_log_prob()`, and other model methods are now faster
after initialization because they avoid repeated stale-binding checks. (#1274)
* `install_cmdstan()` now offers to copy the `make/local` flags of the
Expand Down
3 changes: 3 additions & 0 deletions R/build.R
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ build_executable <- function(stan_file,
pattern = "model-", fileext = paste0(".", tools::file_ext(stan_file))
)
file.copy(stan_file, source, overwrite = TRUE)
withr::defer(unlink(c(
source, paste0(strip_ext(source), ".hpp"), cmdstan_ext(strip_ext(source))
)))
}
hpp_code <- get_standalone_hpp(
source, c(stanc_inc_paths, stancflags_direct),
Expand Down
7 changes: 4 additions & 3 deletions R/model.R
Original file line number Diff line number Diff line change
Expand Up @@ -773,9 +773,9 @@ check_syntax_stan_file <- function(stan_file,
stan_file <- resolve_path(stan_file)
stanc_options <- assert_valid_stanc_options(stanc_options)
stanc_options[["allow-undefined"]] <- TRUE
stanc_options[["o"]] <- wsl_safe_path(
tempfile(pattern = "model-", fileext = ".hpp")
)
hpp_file <- tempfile(pattern = "model-", fileext = ".hpp")
withr::defer(unlink(hpp_file))
stanc_options[["o"]] <- wsl_safe_path(hpp_file)
if (pedantic) {
stanc_options[["warn-pedantic"]] <- TRUE
}
Expand Down Expand Up @@ -2460,6 +2460,7 @@ run_stanc <- function(stan_file, args, spinner = FALSE) {
#' @noRd
stanc_info <- function(stan_file, include_paths = NULL) {
out_file <- tempfile(fileext = ".json")
withr::defer(unlink(out_file))
run_log <- wsl_compatible_run(
command = stanc_cmd(),
args = c(wsl_safe_path(stan_file),
Expand Down
14 changes: 14 additions & 0 deletions tests/testthat/test-model-rebuild-rules.R
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,20 @@ test_that("a renamed program with a copied executable rebuilds for its name", {
)))
})

test_that("a project moved as a whole still reuses its executable", {
stan_file <- local_bernoulli()
mocked(expect_mock_compile(cmdstan_model(stan_file)))

moved <- paste0(dirname(stan_file), "-moved")
withr::defer(unlink(moved, recursive = TRUE))
file.rename(dirname(stan_file), moved)

mocked(expect_no_mock_compile(expect_interactive_message(
cmdstan_model(file.path(moved, basename(stan_file))),
"Model executable is up to date!"
)))
})

test_that("a record that cannot be used rebuilds and says why", {
stan_file <- local_bernoulli()
mocked(expect_mock_compile(mod <- cmdstan_model(stan_file)))
Expand Down
21 changes: 7 additions & 14 deletions tests/testthat/test-model-rebuild.R
Original file line number Diff line number Diff line change
Expand Up @@ -270,20 +270,6 @@ test_that("include paths reordered to the same resolution do not rebuild", {
)
})

test_that("a project moved as a whole still reuses its executable", {
dir_a <- withr::local_tempdir()
stan_file_a <- seed_from(
canonical_bernoulli_stan, canonical_bernoulli_exe, dir_a
)
dir_b <- paste0(dir_a, "-moved")
withr::defer(unlink(dir_b, recursive = TRUE))
file.rename(dir_a, dir_b)

expect_no_recompilation(
cmdstan_model(file.path(dir_b, basename(stan_file_a)))
)
})

test_that("formatting the program invalidates the executable that built it", {
dir <- withr::local_tempdir()
stan_file <- write_stan_file(c(
Expand Down Expand Up @@ -465,3 +451,10 @@ test_that("a model whose Stan file is gone errors, and its executable can be ado
adopted <- cmdstan_model(exe_file = mod$exe_file())
expect_sample_output(adopted$sample(data = data, chains = 1), 1)
})

test_that("a build leaves only the model's C++ in the temporary directory", {
stan_file <- local_program()
before <- list.files(tempdir())
mod <- cmdstan_model(stan_file)
expect_equal(setdiff(list.files(tempdir()), before), basename(mod$hpp_file()))
})
7 changes: 7 additions & 0 deletions tests/testthat/test-stan-file-functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ test_that("check_syntax_stan_file() checks a program", {
expect_true(check_syntax_stan_file(include_model$stan_file, quiet = TRUE))
})

test_that("check_syntax_stan_file() and variables_stan_file() leave nothing behind", {
before <- list.files(tempdir())
check_syntax_stan_file(testing_stan_file("bernoulli"), quiet = TRUE)
variables_stan_file(testing_stan_file("bernoulli"))
expect_equal(list.files(tempdir()), before)
})

test_that("format_stan_file() formats a program", {
stan_file <- withr::local_tempfile(
lines = "parameters {real y;} model {y ~ std_normal();}", fileext = ".stan"
Expand Down
Loading