@@ -397,6 +397,8 @@ CmdStanModel <- R6::R6Class(
397
397
# ' `functions` field in the compiled model object. This can also be done after
398
398
# ' compilation using the
399
399
# ' [`$expose_functions()`][model-method-expose_functions] method.
400
+ # ' @param dry_run (logical) If `TRUE`, the code will do all checks before compilation,
401
+ # ' but skip the actual C++ compilation. Used to speedup tests.
400
402
# '
401
403
# ' @param threads Deprecated and will be removed in a future release. Please
402
404
# ' turn on threading via `cpp_options = list(stan_threads = TRUE)` instead.
@@ -450,8 +452,10 @@ compile <- function(quiet = TRUE,
450
452
compile_model_methods = FALSE ,
451
453
compile_hessian_method = FALSE ,
452
454
compile_standalone = FALSE ,
455
+ dry_run = FALSE ,
453
456
# deprecated
454
457
threads = FALSE ) {
458
+
455
459
if (length(self $ stan_file()) == 0 ) {
456
460
stop(" '$compile()' cannot be used because the 'CmdStanModel' was not created with a Stan file." , call. = FALSE )
457
461
}
@@ -500,15 +504,63 @@ compile <- function(quiet = TRUE,
500
504
exe <- self $ exe_file()
501
505
}
502
506
507
+ # Resolve stanc and cpp options
508
+ if (pedantic ) {
509
+ stanc_options [[" warn-pedantic" ]] <- TRUE
510
+ }
511
+
512
+ if (isTRUE(cpp_options $ stan_opencl )) {
513
+ stanc_options [[" use-opencl" ]] <- TRUE
514
+ }
515
+
516
+ # Note that unlike cpp_options["USER_HEADER"], the user_header variable is deliberately
517
+ # not transformed with wsl_safe_path() as that breaks the check below on WSLv1
518
+ if (! is.null(user_header )) {
519
+ if (! is.null(cpp_options [[" USER_HEADER" ]]) || ! is.null(cpp_options [[" user_header" ]])) {
520
+ warning(" User header specified both via user_header argument and via cpp_options arguments" )
521
+ }
522
+
523
+ cpp_options [[" USER_HEADER" ]] <- wsl_safe_path(absolute_path(user_header ))
524
+ stanc_options [[" allow-undefined" ]] <- TRUE
525
+ private $ using_user_header_ <- TRUE
526
+ }
527
+ else if (! is.null(cpp_options [[" USER_HEADER" ]])) {
528
+ if (! is.null(cpp_options [[" user_header" ]])) {
529
+ warning(' User header specified both via cpp_options[["USER_HEADER"]] and cpp_options[["user_header"]].' , call. = FALSE )
530
+ }
531
+
532
+ user_header <- cpp_options [[" USER_HEADER" ]]
533
+ cpp_options [[" USER_HEADER" ]] <- wsl_safe_path(absolute_path(cpp_options [[" USER_HEADER" ]]))
534
+ private $ using_user_header_ <- TRUE
535
+ }
536
+ else if (! is.null(cpp_options [[" user_header" ]])) {
537
+ user_header <- cpp_options [[" user_header" ]]
538
+ cpp_options [[" user_header" ]] <- wsl_safe_path(absolute_path(cpp_options [[" user_header" ]]))
539
+ private $ using_user_header_ <- TRUE
540
+ }
541
+
542
+
543
+ if (! is.null(user_header )) {
544
+ user_header <- absolute_path(user_header ) # As mentioned above, just absolute, not wsl_safe_path()
545
+ if (! file.exists(user_header )) {
546
+ stop(paste0(" User header file '" , user_header , " ' does not exist." ), call. = FALSE )
547
+ }
548
+ }
549
+
503
550
# compile if:
504
551
# - the user forced compilation,
505
552
# - the executable does not exist
506
553
# - the stan model was changed since last compilation
554
+ # - a user header is used and the user header changed since last compilation (#813)
507
555
if (! file.exists(exe )) {
508
556
force_recompile <- TRUE
509
557
} else if (file.exists(self $ stan_file())
510
558
&& file.mtime(exe ) < file.mtime(self $ stan_file())) {
511
559
force_recompile <- TRUE
560
+ } else if (! is.null(user_header )
561
+ && file.exists(user_header )
562
+ && file.mtime(exe ) < file.mtime(user_header )) {
563
+ force_recompile <- TRUE
512
564
}
513
565
514
566
if (! force_recompile ) {
@@ -530,7 +582,7 @@ compile <- function(quiet = TRUE,
530
582
531
583
if (os_is_wsl() && (compile_model_methods || compile_standalone )) {
532
584
warning(" Additional model methods and standalone functions are not " ,
533
- " currently available with WSL CmdStan and will not be compiled" ,
585
+ " currently available with WSLv1 CmdStan and will not be compiled. " ,
534
586
call. = FALSE )
535
587
compile_model_methods <- FALSE
536
588
compile_standalone <- FALSE
@@ -548,23 +600,6 @@ compile <- function(quiet = TRUE,
548
600
549
601
stancflags_val <- include_paths_stanc3_args(include_paths )
550
602
551
- if (pedantic ) {
552
- stanc_options [[" warn-pedantic" ]] <- TRUE
553
- }
554
-
555
- if (isTRUE(cpp_options $ stan_opencl )) {
556
- stanc_options [[" use-opencl" ]] <- TRUE
557
- }
558
- if (! is.null(user_header )) {
559
- cpp_options [[" USER_HEADER" ]] <- wsl_safe_path(user_header )
560
- stanc_options [[" allow-undefined" ]] <- TRUE
561
- }
562
- if (! is.null(cpp_options [[" USER_HEADER" ]])) {
563
- cpp_options [[" USER_HEADER" ]] <- wsl_safe_path(absolute_path(cpp_options [[" USER_HEADER" ]]))
564
- }
565
- if (! is.null(cpp_options [[" user_header" ]])) {
566
- cpp_options [[" user_header" ]] <- wsl_safe_path(absolute_path(cpp_options [[" user_header" ]]))
567
- }
568
603
if (is.null(stanc_options [[" name" ]])) {
569
604
stanc_options [[" name" ]] <- paste0(self $ model_name(), " _model" )
570
605
}
@@ -588,10 +623,17 @@ compile <- function(quiet = TRUE,
588
623
self $ functions $ hpp_code <- get_standalone_hpp(temp_stan_file , stancflags_standalone )
589
624
self $ functions $ external <- ! is.null(user_header )
590
625
self $ functions $ existing_exe <- FALSE
626
+
627
+ stancflags_val <- paste0(" STANCFLAGS += " , stancflags_val , paste0(" " , stancflags_combined , collapse = " " ))
628
+
629
+ if (dry_run ) {
630
+ return (invisible (self ))
631
+ }
632
+
591
633
if (compile_standalone ) {
592
634
expose_stan_functions(self $ functions , ! quiet )
593
635
}
594
- stancflags_val <- paste0( " STANCFLAGS += " , stancflags_val , paste0( " " , stancflags_combined , collapse = " " ))
636
+
595
637
withr :: with_path(
596
638
c(
597
639
toolchain_PATH_env_var(),
0 commit comments