@@ -259,7 +259,7 @@ CmdStanModel <- R6::R6Class(
259259 if (! is.null(stan_file )) {
260260 assert_file_exists(stan_file , access = " r" , extension = c(" stan" , " stanfunctions" ))
261261 checkmate :: assert_flag(compile )
262- private $ stan_file_ <- absolute_path (stan_file )
262+ private $ stan_file_ <- resolve_path (stan_file )
263263 private $ stan_code_ <- readLines(stan_file )
264264 private $ model_name_ <- gsub(" " , " _" , strip_ext(basename(private $ stan_file_ )))
265265 private $ precompile_cpp_options_ <- args $ cpp_options %|| % list ()
@@ -269,20 +269,20 @@ CmdStanModel <- R6::R6Class(
269269 private $ using_user_header_ <- TRUE
270270 }
271271 if (is.null(args $ include_paths ) && any(grepl(" #include" , private $ stan_code_ ))) {
272- private $ precompile_include_paths_ <- dirname(stan_file )
272+ private $ precompile_include_paths_ <- dirname(private $ stan_file_ )
273273 } else {
274- private $ precompile_include_paths_ <- args $ include_paths
274+ private $ precompile_include_paths_ <- resolve_path( args $ include_paths )
275275 }
276276 }
277277 if (! is.null(exe_file )) {
278278 ext <- if (os_is_windows() && ! os_is_wsl()) " exe" else " "
279- private $ exe_file_ <- repair_path(absolute_path( exe_file ) )
279+ private $ exe_file_ <- resolve_path( exe_file )
280280 if (is.null(stan_file )) {
281281 assert_file_exists(private $ exe_file_ , access = " r" , extension = ext )
282282 private $ model_name_ <- gsub(" " , " _" , strip_ext(basename(private $ exe_file_ )))
283283 }
284284 private $ include_paths_ <-
285- private $ precompile_include_paths_ %|| % args $ include_paths
285+ private $ precompile_include_paths_ %|| % resolve_path( args $ include_paths )
286286 }
287287 if (! is.null(stan_file ) && compile ) {
288288 self $ compile(... )
@@ -422,7 +422,7 @@ CmdStanModel <- R6::R6Class(
422422# ' * `$model_name()` returns the model name as a string.
423423# ' * `$exe_file()` returns a path as a string, or `character(0)` if no
424424# ' executable path is set.
425- # ' * `$include_paths()` returns a character vector of paths or `NULL`.
425+ # ' * `$include_paths()` returns a character vector of absolute paths or `NULL`.
426426# ' * `$cmdstan_version()` returns a CmdStan version as a string.
427427# ' * `$cpp_options()` returns a named list of C++ options.
428428# ' * `$hpp_file()` returns the path to the `.hpp` file as a string when C++ code
@@ -480,7 +480,10 @@ NULL
480480# ' [`$check_syntax()`][model-method-check_syntax] method can be used instead.
481481# ' @param include_paths (character vector) Paths to directories where Stan
482482# ' should look for files specified in `#include` directives in the Stan
483- # ' program.
483+ # ' program. Relative paths are resolved against the working directory when
484+ # ' the model object is created (or when `$compile()` is called) and stored as
485+ # ' absolute paths, so subsequent changes to the working directory do not
486+ # ' affect them.
484487# ' @param user_header (string) The path to a C++ file (with a .hpp extension)
485488# ' to compile with the Stan model.
486489# ' @param cpp_options (list) Any makefile options to be used when compiling the
@@ -594,7 +597,7 @@ compile <- function(quiet = TRUE,
594597 if (is.null(include_paths ) && ! is.null(private $ precompile_include_paths_ )) {
595598 include_paths <- private $ precompile_include_paths_
596599 }
597- private $ include_paths_ <- include_paths
600+ private $ include_paths_ <- resolve_path( include_paths )
598601 if (is.null(dir ) && ! is.null(private $ dir_ )) {
599602 dir <- absolute_path(private $ dir_ )
600603 } else if (! is.null(dir )) {
@@ -724,7 +727,7 @@ compile <- function(quiet = TRUE,
724727 if (length(stancflags_local ) > 0 ) {
725728 stancflags_combined <- c(stancflags_combined , stancflags_local )
726729 }
727- stanc_inc_paths <- include_paths_stanc3_args(include_paths , standalone_call = TRUE )
730+ stanc_inc_paths <- include_paths_stanc3_args(include_paths , direct_call = TRUE )
728731 stancflags_standalone <- c(" --standalone-functions" , stanc_inc_paths , stancflags_combined )
729732 self $ functions $ hpp_code <- get_standalone_hpp(temp_stan_file , stancflags_standalone )
730733 private $ model_methods_env_ <- new.env()
@@ -980,7 +983,10 @@ check_syntax <- function(pedantic = FALSE,
980983 stanc_options [[" warn-pedantic" ]] <- TRUE
981984 }
982985
983- stancflags_val <- include_paths_stanc3_args(include_paths )
986+ stancflags_val <- include_paths_stanc3_args(
987+ include_paths ,
988+ direct_call = TRUE
989+ )
984990
985991 if (is.null(stanc_options [[" name" ]])) {
986992 stanc_options [[" name" ]] <- paste0(self $ model_name(), " _model" )
@@ -1106,7 +1112,10 @@ format <- function(overwrite_file = FALSE,
11061112 lower = 1 , len = 1 , null.ok = TRUE
11071113 )
11081114 stanc_options <- private $ precompile_stanc_options_
1109- stancflags_val <- include_paths_stanc3_args(self $ include_paths())
1115+ stancflags_val <- include_paths_stanc3_args(
1116+ self $ include_paths(),
1117+ direct_call = TRUE
1118+ )
11101119 stanc_options [" auto-format" ] <- TRUE
11111120 if (! is.null(max_line_length )) {
11121121 stanc_options [" max-line-length" ] <- max_line_length
@@ -2462,19 +2471,34 @@ assert_stan_file_exists <- function(stan_file) {
24622471 }
24632472}
24642473
2465- include_paths_stanc3_args <- function (include_paths = NULL , standalone_call = FALSE ) {
2474+ # ' Build stanc include-path arguments
2475+ # '
2476+ # ' Make receives include paths through `STANCFLAGS` and needs paths containing
2477+ # ' spaces to be shell-quoted within a single `--include-paths=` flag. Direct
2478+ # ' calls through processx instead need the flag and comma-separated paths as
2479+ # ' separate, unquoted arguments.
2480+ # '
2481+ # ' @param include_paths A character vector of directories containing files used
2482+ # ' in Stan `#include` directives, or `NULL`.
2483+ # ' @param direct_call A logical indicating whether the arguments will be passed
2484+ # ' directly to stanc through processx instead of through Make.
2485+ # '
2486+ # ' @return `NULL` if `include_paths` is `NULL`; otherwise, a single
2487+ # ' `--include-paths=` argument for Make or two arguments for a direct call.
2488+ # ' @noRd
2489+ include_paths_stanc3_args <- function (include_paths = NULL , direct_call = FALSE ) {
24662490 stancflags <- NULL
24672491 if (! is.null(include_paths )) {
24682492 assert_dir_exists(include_paths , access = " r" )
24692493 include_paths <- sapply(absolute_path(include_paths ), wsl_safe_path )
24702494 # Calling stanc3 directly through processx::run does not need quoting
2471- if (! isTRUE(standalone_call )) {
2495+ if (! isTRUE(direct_call )) {
24722496 paths_w_space <- grep(" " , include_paths )
24732497 include_paths [paths_w_space ] <- paste0(" '" , include_paths [paths_w_space ], " '" )
24742498 }
24752499 include_paths <- paste0(include_paths , collapse = " ," )
24762500 include_paths_flag <- " --include-paths="
2477- if (isTRUE(standalone_call )) {
2501+ if (isTRUE(direct_call )) {
24782502 stancflags <- c(stancflags , " --include-paths" , include_paths )
24792503 } else {
24802504 stancflags <- paste0(stancflags , include_paths_flag , include_paths )
@@ -2494,7 +2518,10 @@ model_variables <- function(stan_file, include_paths = NULL, allow_undefined = F
24942518 command = stanc_cmd(),
24952519 args = c(wsl_safe_path(stan_file ),
24962520 " --info" ,
2497- include_paths_stanc3_args(include_paths ),
2521+ include_paths_stanc3_args(
2522+ include_paths ,
2523+ direct_call = TRUE
2524+ ),
24982525 allow_undefined_arg ),
24992526 wd = cmdstan_path(),
25002527 echo = FALSE ,
0 commit comments