This bug description was generated with the help of Claude
Describe the bug
get_cmdstan_flags("STANCFLAGS") splits the flag string on whitespace (R/utils.R):
flags_vec <- strsplit(x = trimws(flags), split = "\s+", perl = TRUE)[[1]]
That splits inside a quoted value. A make/local containing
STANCFLAGS += --include-paths='/my dir'
becomes:
#> [1] "--include-paths='/my" "dir'"
compile() appends this vector to the stanc options and then uses it two ways:
- for make, the elements are rejoined with spaces into STANCFLAGS += ..., which round-trips fine — the shell re-strips the quotes;
- for the direct stanc calls in get_standalone_hpp() (which relements are passed to processx as separate arguments, so stanc receives --include-paths='/my and dir' as two distinct argv e
stanc then treats dir' as a positional argument:
stanc: too many arguments, don't know what to do with model.s
Only compile() is affected — $check_syntax() and $format() don't read local STANCFLAGS.
To Reproduce
Put a quoted, space-containing value in make/local:
STANCFLAGS += --include-paths='/my dir'
then compile any model. The equivalent failure can be seen directly:
stanc <- file.path(cmdstan_path(), "bin", "stanc")
processx::run(stanc, c("--include-paths='/my", "dir'", "model.stan"),
error_on_status = FALSE)$stderr
#> stanc: too many arguments, don't know what to do with model.stan
Expected behavior
Flags read from make/local should reach direct stanc calls asould produce — i.e. --include-paths=/my dir as one argument, with the shell quoting removed rather than treated as part of
Additional context
Pre-existing, not a regression. This is the same class of bug as #820 and #1227 (shell quoting leaking into processx arguments), but for flags coming from make/local rather than from include_paths or stanc_options. #1231 splits the direct and make-quoted option vectors but keeps passing the split local flags to both, so it doesn't cover this case.
Not a duplicate of #1230, which is the mirror image: #1230 is about the quoting cmdstanr writes for Make in include_paths_stanc3_args() and explicitly does not affect direct stanc calls. This one is about the quoting cmdstanr reads from make/local in get_cmdstan_flags(), and affects only the direct calls. Neither fix resolves the other — flags from make/local never pass through include_paths_stanc3_args().
This bug description was generated with the help of Claude
Describe the bug
get_cmdstan_flags("STANCFLAGS") splits the flag string on whitespace (R/utils.R):
flags_vec <- strsplit(x = trimws(flags), split = "\s+", perl = TRUE)[[1]]
That splits inside a quoted value. A make/local containing
STANCFLAGS += --include-paths='/my dir'
becomes:
#> [1] "--include-paths='/my" "dir'"
compile() appends this vector to the stanc options and then uses it two ways:
stanc then treats dir' as a positional argument:
stanc: too many arguments, don't know what to do with model.s
Only compile() is affected — $check_syntax() and $format() don't read local STANCFLAGS.
To Reproduce
Put a quoted, space-containing value in make/local:
STANCFLAGS += --include-paths='/my dir'
then compile any model. The equivalent failure can be seen directly:
Expected behavior
Flags read from make/local should reach direct stanc calls asould produce — i.e. --include-paths=/my dir as one argument, with the shell quoting removed rather than treated as part of
Additional context
Pre-existing, not a regression. This is the same class of bug as #820 and #1227 (shell quoting leaking into processx arguments), but for flags coming from make/local rather than from include_paths or stanc_options. #1231 splits the direct and make-quoted option vectors but keeps passing the split local flags to both, so it doesn't cover this case.
Not a duplicate of #1230, which is the mirror image: #1230 is about the quoting cmdstanr writes for Make in include_paths_stanc3_args() and explicitly does not affect direct stanc calls. This one is about the quoting cmdstanr reads from make/local in get_cmdstan_flags(), and affects only the direct calls. Neither fix resolves the other — flags from make/local never pass through include_paths_stanc3_args().