Skip to content

Commit 22ee5fc

Browse files
authored
Merge pull request #836 from martinmodrak/835-compile-test-improvements
Improvemements to compile tests
2 parents 2911096 + 121abd0 commit 22ee5fc

File tree

4 files changed

+135
-133
lines changed

4 files changed

+135
-133
lines changed

DESCRIPTION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@ Imports:
4040
posterior (>= 1.4.1),
4141
processx (>= 3.5.0),
4242
R6 (>= 2.4.0),
43-
withr (>= 2.5.0)
43+
withr (>= 2.5.0),
44+
rlang (>= 0.4.7)
4445
Suggests:
4546
bayesplot,
4647
knitr (>= 1.37),
4748
loo (>= 2.0.0),
48-
rlang (>= 0.4.7),
4949
rmarkdown,
5050
testthat (>= 2.1.0),
5151
Rcpp,

R/model.R

Lines changed: 76 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ compile <- function(quiet = TRUE,
570570
}
571571

572572
if (!force_recompile) {
573-
if (interactive()) {
573+
if (rlang::is_interactive()) {
574574
message("Model executable is up to date!")
575575
}
576576
private$cpp_options_ <- cpp_options
@@ -581,7 +581,7 @@ compile <- function(quiet = TRUE,
581581
self$exe_file(exe)
582582
return(invisible(self))
583583
} else {
584-
if (interactive()) {
584+
if (rlang::is_interactive()) {
585585
message("Compiling Stan program...")
586586
}
587587
}
@@ -632,89 +632,92 @@ compile <- function(quiet = TRUE,
632632

633633
stancflags_val <- paste0("STANCFLAGS += ", stancflags_val, paste0(" ", stancflags_combined, collapse = " "))
634634

635-
if (dry_run) {
636-
return(invisible(self))
637-
}
635+
if (!dry_run) {
638636

639-
if (compile_standalone) {
640-
expose_stan_functions(self$functions, !quiet)
641-
}
637+
if (compile_standalone) {
638+
expose_stan_functions(self$functions, !quiet)
639+
}
642640

643-
withr::with_path(
644-
c(
645-
toolchain_PATH_env_var(),
646-
tbb_path()
647-
),
648-
run_log <- wsl_compatible_run(
649-
command = make_cmd(),
650-
args = c(wsl_safe_path(tmp_exe),
651-
cpp_options_to_compile_flags(cpp_options),
652-
stancflags_val),
653-
wd = cmdstan_path(),
654-
echo = !quiet || is_verbose_mode(),
655-
echo_cmd = is_verbose_mode(),
656-
spinner = quiet && interactive() && !identical(Sys.getenv("IN_PKGDOWN"), "true"),
657-
stderr_callback = function(x, p) {
658-
if (!startsWith(x, paste0(make_cmd(), ": *** No rule to make target"))) {
659-
message(x)
660-
}
661-
if (grepl("PCH file", x) || grepl("precompiled header", x) || grepl(".hpp.gch", x) ) {
662-
warning(
663-
"CmdStan's precompiled header (PCH) files may need to be rebuilt.\n",
664-
"If your model failed to compile please run rebuild_cmdstan().\n",
665-
"If the issue persists please open a bug report.",
666-
call. = FALSE
667-
)
668-
}
669-
if (grepl("No space left on device", x) || grepl("error in backend: IO failure on output stream", x)) {
670-
warning(
671-
"The C++ compiler ran out of disk space and was unable to build the executables for your model!\n",
672-
"See the above error for more details.",
673-
call. = FALSE
674-
)
675-
}
676-
if (os_is_macos()) {
677-
if (R.version$arch == "aarch64"
678-
&& grepl("but the current translation unit is being compiled for target", x)) {
641+
withr::with_path(
642+
c(
643+
toolchain_PATH_env_var(),
644+
tbb_path()
645+
),
646+
run_log <- wsl_compatible_run(
647+
command = make_cmd(),
648+
args = c(wsl_safe_path(tmp_exe),
649+
cpp_options_to_compile_flags(cpp_options),
650+
stancflags_val),
651+
wd = cmdstan_path(),
652+
echo = !quiet || is_verbose_mode(),
653+
echo_cmd = is_verbose_mode(),
654+
spinner = quiet && rlang::is_interactive() && !identical(Sys.getenv("IN_PKGDOWN"), "true"),
655+
stderr_callback = function(x, p) {
656+
if (!startsWith(x, paste0(make_cmd(), ": *** No rule to make target"))) {
657+
message(x)
658+
}
659+
if (grepl("PCH file", x) || grepl("precompiled header", x) || grepl(".hpp.gch", x) ) {
679660
warning(
680-
"The C++ compiler has errored due to incompatibility between the x86 and ",
681-
"Apple Silicon architectures.\n",
682-
"If you are running R inside an IDE (RStudio, VSCode, ...), ",
683-
"make sure the IDE is a native Apple Silicon app.\n",
661+
"CmdStan's precompiled header (PCH) files may need to be rebuilt.\n",
662+
"If your model failed to compile please run rebuild_cmdstan().\n",
663+
"If the issue persists please open a bug report.",
684664
call. = FALSE
685665
)
686666
}
687-
}
688-
},
689-
error_on_status = FALSE
690-
)
691-
)
692-
if (is.na(run_log$status) || run_log$status != 0) {
693-
stop("An error occured during compilation! See the message above for more information.",
694-
call. = FALSE)
695-
}
696-
if (file.exists(exe)) {
697-
file.remove(exe)
698-
}
699-
file.copy(tmp_exe, exe, overwrite = TRUE)
700-
if (os_is_wsl()) {
701-
res <- processx::run(
702-
command = "wsl",
703-
args = c("chmod", "+x", wsl_safe_path(exe)),
704-
error_on_status = FALSE
667+
if (grepl("No space left on device", x) || grepl("error in backend: IO failure on output stream", x)) {
668+
warning(
669+
"The C++ compiler ran out of disk space and was unable to build the executables for your model!\n",
670+
"See the above error for more details.",
671+
call. = FALSE
672+
)
673+
}
674+
if (os_is_macos()) {
675+
if (R.version$arch == "aarch64"
676+
&& grepl("but the current translation unit is being compiled for target", x)) {
677+
warning(
678+
"The C++ compiler has errored due to incompatibility between the x86 and ",
679+
"Apple Silicon architectures.\n",
680+
"If you are running R inside an IDE (RStudio, VSCode, ...), ",
681+
"make sure the IDE is a native Apple Silicon app.\n",
682+
call. = FALSE
683+
)
684+
}
685+
}
686+
},
687+
error_on_status = FALSE
688+
)
705689
)
706-
}
690+
if (is.na(run_log$status) || run_log$status != 0) {
691+
stop("An error occured during compilation! See the message above for more information.",
692+
call. = FALSE)
693+
}
694+
if (file.exists(exe)) {
695+
file.remove(exe)
696+
}
697+
file.copy(tmp_exe, exe, overwrite = TRUE)
698+
if (os_is_wsl()) {
699+
res <- processx::run(
700+
command = "wsl",
701+
args = c("chmod", "+x", wsl_safe_path(exe)),
702+
error_on_status = FALSE
703+
)
704+
}
705+
} # End - if(!dry_run)
706+
707707
private$exe_file_ <- exe
708708
private$cpp_options_ <- cpp_options
709709
private$precompile_cpp_options_ <- NULL
710710
private$precompile_stanc_options_ <- NULL
711711
private$precompile_include_paths_ <- NULL
712712
private$model_methods_env_ <- new.env()
713-
suppressWarnings(private$model_methods_env_$hpp_code_ <- readLines(private$hpp_file_, warn = FALSE))
714-
if (compile_model_methods) {
715-
expose_model_methods(env = private$model_methods_env_,
716-
verbose = !quiet,
717-
hessian = compile_hessian_method)
713+
714+
if(!dry_run) {
715+
suppressWarnings(private$model_methods_env_$hpp_code_ <- readLines(private$hpp_file_, warn = FALSE))
716+
if (compile_model_methods) {
717+
expose_model_methods(env = private$model_methods_env_,
718+
verbose = !quiet,
719+
hessian = compile_hessian_method)
720+
}
718721
}
719722
invisible(self)
720723
}
@@ -876,7 +879,7 @@ check_syntax <- function(pedantic = FALSE,
876879
wd = cmdstan_path(),
877880
echo = is_verbose_mode(),
878881
echo_cmd = is_verbose_mode(),
879-
spinner = quiet && interactive(),
882+
spinner = quiet && rlang::is_interactive(),
880883
stderr_callback = function(x, p) {
881884
message(x)
882885
},

tests/testthat/helper-custom-expectations.R

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ expect_compilation <- function(mod, ...) {
1616
invisible(mod)
1717
}
1818

19+
#' Check compilation from a call (expecting a constructor call, but not necessarily).
20+
#' @param constructor_call a call returning a CmdStanModel object that should have been compiled
21+
#' @return the newly created model
22+
expect_call_compilation <- function(constructor_call) {
23+
before_time <- Sys.time()
24+
mod <- expect_interactive_message(constructor_call, "Compiling Stan program...")
25+
if(length(mod$exe_file()) == 0 || !file.exists(mod$exe_file())) {
26+
fail(sprint("Model executable '%s' does not exist after compilation.", mod$exe_file()))
27+
}
28+
after_mtime <- file.mtime(mod$exe_file())
29+
expect(before_time <= after_mtime, sprintf("Exe file '%s' has old timestamp, despite expecting (re)compilation", mod$exe_file()))
30+
invisible(mod)
31+
}
32+
33+
1934
#' @param ... arguments passed to mod$compile()
2035
expect_no_recompilation <- function(mod, ...) {
2136
if(length(mod$exe_file()) == 0 || !file.exists(mod$exe_file())) {
@@ -70,14 +85,11 @@ expect_gq_output <- function(object, num_chains = NULL) {
7085
}
7186

7287
expect_interactive_message <- function(object, regexp = NULL) {
73-
# Non-interactive message suppression failing under Windows CI,
74-
# temporarily skip message check only on Windows
75-
if (os_is_windows() && !os_is_wsl()) {
76-
return(object)
77-
}
78-
if (interactive()) {
79-
expect_message(object = object, regexp = regexp)
80-
} else {
81-
expect_silent(object = object)
82-
}
88+
rlang::with_interactive(value = TRUE,
89+
expect_message(object = object, regexp = regexp))
90+
}
91+
92+
expect_noninteractive_silent <- function(object) {
93+
rlang::with_interactive(value = FALSE,
94+
expect_silent(object))
8395
}

0 commit comments

Comments
 (0)