Compiler ignoring Makevars.win?

Hello all, lately I’ve been spending a lot of time helping users of my RStan-dependent package troubleshoot toolchain configuration issues when installing the package from GitHub. In the course of that, I discovered something surprising on my own system: based on the flags used in a compiled model, as reported by get_cxxflags(), the compiler seems to be ignoring the contents of my Makevars.win.

This is my Makevars.win:

> writeLines(readLines(Sys.getenv("R_MAKEVARS_USER")))

CXX14FLAGS += -Wno-unused -Wno-ignored-attributes -Wno-sign-compare -Wno-deprecated-declarations
CXX14FLAGS += -Wno-attributes -Wno-parentheses -Wno-unknown-pragmas -Wno-infinite-recursion
CXX14FLAGS += -mfpmath=sse -mstackrealign
PKG_CPPFLAGS += -DUSE_STANC3
CXX14FLAGS += -mtune=native -O3 -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2

The last line is what’s prescribed in the Configuring C++ Toolchain for Windows section of the RStan Getting Started wiki. All the no-warnings stuff is necessary to suppress extremely verbose and problematic compiler warnings, but the results I show below are unchanged if I delete everything before the last line.

Compiling the 8 schools model and querying the flags used, I get:

> mod <- stan_model(file = "8schools.stan")
> get_cxxflags(mod)
[1] "CXXFLAGS = -O2 -Wall $(DEBUGFLAG) -mfpmath=sse -msse2 -mstackrealign $(LTO)"

Same thing if I compile one of the much more complex Stan programs in my package (just compiling a single model, not installing the package). The flags returned by get_cxxflags() are the same as the ones shown above, not the ones in Makevars.win.

Does anyone have an idea why the compiler seems to be ignoring Makevars.win? One thought I had was that perhaps get_cxxflags() literally only reports the CXXFLAGS (of which I have none specified) and ignores the CXX14FLAGS, and/or that the models being compiled don’t require C++14 (caveat: I really have no idea what I’m talking about here). But the fact that the optimization flags, especially -O3, don’t seem to be enforced appears to be a problem.

Thanks in advance for any suggestions.

Session info:

R version 4.1.3 (2022-03-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] rstan_2.26.1       StanHeaders_2.26.1

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.8         compiler_4.1.3     pillar_1.7.0       tools_4.1.3       
 [5] prettyunits_1.1.1  pkgbuild_1.3.1     jsonlite_1.8.0     lifecycle_1.0.1   
 [9] tibble_3.1.6       gtable_0.3.0       pkgconfig_2.0.3    rlang_1.0.2       
[13] rstudioapi_0.13    DBI_1.1.2          cli_3.2.0          parallel_4.1.3    
[17] curl_4.3.2         loo_2.5.0          gridExtra_2.3      withr_2.5.0       
[21] dplyr_1.0.8        generics_0.1.2     vctrs_0.3.8        stats4_4.1.3      
[25] grid_4.1.3         tidyselect_1.1.2   glue_1.6.2         inline_0.3.19     
[29] R6_2.5.1           processx_3.5.2     fansi_1.0.2        ggplot2_3.3.5     
[33] callr_3.7.0        purrr_0.3.4        magrittr_2.0.2     codetools_0.2-18  
[37] matrixStats_0.61.0 scales_1.1.1       ps_1.6.0           ellipsis_0.3.2    
[41] assertthat_0.2.1   colorspace_2.0-3   V8_4.1.0           utf8_1.2.2        
[45] RcppParallel_5.1.5 munsell_0.5.0      crayon_1.5.0      

I believe the get_cxxflags() function only returns flags that you’ve set via CXXFLAGS +=, whereas your flags are set via CXX14FLAGS +=. To verify for certain whether the flags are being respected during compilation, you can use verbose = TRUE in your stan call and look at the compilation flags that are used

Ah OK, thanks for the clarification @andrjohns. I hadn’t noticed verbose did that. I also realized it must be using Makevars.win, because the warnings when compiling my real model are suppressed.

A related question, which has also come up in these user toolchain issues I mentioned as well as my own: is the R_MAKEVARS_USER environment variable supposed to be set to ~/.R/Makevars.win or whatever by default? I don’t think it’s mentioned in the Getting Started, which led me to think it was, but I’m getting the impression it’s not set to anything. For a couple of users who’ve been bogged down with this stuff, that was the (or a) cause.

A related question, which has also come up in these user toolchain issues I mentioned as well as my own: is the R_MAKEVARS_USER environment variable supposed to be set to ~/.R/Makevars.win or whatever by default?

R looks for the makevars files (for any compilation from source as well) in the $HOME/.R directory, rather than the R_MAKEVARS_USER variable. If you have users whose Makevars settings aren’t being detected by R, the most likely cause is the .R folder not being in the $HOME directory

Oh, interesting. So R_MAKEVARS_USER may have been a red herring, except there’s at least one case (I’m pretty sure; will double-check) where the Makevars file in $HOME/.R didn’t take effect until the environment variable was set.

Anyway, thanks for taking the time to explain this stuff. Based on various threads on here, I know I’m not alone in finding these toolchain issues confusing.

Bumping this thread because I’ve once again encountered a situation where the compiler seems to be ignoring my user Makevars.win. I just upgraded from R 4.2.2 / Rtools42 to R 4.3.0 / Rtools43, and I’m still able to compile and sample models but my compiler flags, which used to work as intended, suddenly do not.

My user Makevars.win looks like

CXX14FLAGS += -Wno-unused -Wno-ignored-attributes -Wno-sign-compare -Wno-deprecated-declarations
CXX14FLAGS += -Wno-attributes -Wno-parentheses -Wno-unknown-pragmas -Wno-infinite-recursion
CXX14FLAGS += -mfpmath=sse -mstackrealign  # https://github.com/kaskr/adcomp/issues/321#issuecomment-780945941
CXX14FLAGS += -mtune=native -O3 -mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2

But the compiler output states, as an example:

using C++ compiler: 'G__~1.EXE (GCC) 12.2.0'
using C++17

g++  -std=gnu++17 -I"C:/R/R-4.3.0/include" -DNDEBUG -I"../inst/include" -I"C:/R/R-4.3.0/library/StanHeaders/include/src" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 -DUSE_STANC3 -D_HAS_AUTO_PTR_ETC=0 -I'C:/R/R-4.3.0/library/BH/include' -I'C:/R/R-4.3.0/library/Rcpp/include' -I'C:/R/R-4.3.0/library/RcppEigen/include' -I'C:/R/R-4.3.0/library/RcppParallel/include' -I'C:/R/R-4.3.0/library/rstan/include' -I'C:/R/R-4.3.0/library/StanHeaders/include'   -I"C:/rtools43/x86_64-w64-mingw32.static.posix/include"  -DRCPP_PARALLEL_USE_TBB=1 -I"C:/R/R-4.3.0/library/RcppParallel/include" -D_REENTRANT -DSTAN_THREADS   -Wa,-mbig-obj   -O2 -Wall  -mfpmath=sse -msse2 -mstackrealign  -c RcppExports.cpp -o RcppExports.o
g++  -std=gnu++17 -I"C:/R/R-4.3.0/include" -DNDEBUG -I"../inst/include" -I"C:/R/R-4.3.0/library/StanHeaders/include/src" -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DRCPP_PARALLEL_USE_TBB=1 -DUSE_STANC3 -D_HAS_AUTO_PTR_ETC=0 -I'C:/R/R-4.3.0/library/BH/include' -I'C:/R/R-4.3.0/library/Rcpp/include' -I'C:/R/R-4.3.0/library/RcppEigen/include' -I'C:/R/R-4.3.0/library/RcppParallel/include' -I'C:/R/R-4.3.0/library/rstan/include' -I'C:/R/R-4.3.0/library/StanHeaders/include'   -I"C:/rtools43/x86_64-w64-mingw32.static.posix/include"  -DRCPP_PARALLEL_USE_TBB=1 -I"C:/R/R-4.3.0/library/RcppParallel/include" -D_REENTRANT -DSTAN_THREADS   -Wa,-mbig-obj   -O2 -Wall  -mfpmath=sse -msse2 -mstackrealign  -c stanExports_IPM_ICchinook_pp.cc -o stanExports_IPM_ICchinook_pp.o

If you scroll far enough, you’ll see that it’s using -O2 instead of -O3 and my flags to suppress various warnings have been replaced with -Wall. This was not the case before upgrading; nothing else has changed.

I see that the compiler is now using C++17. This surprised me, since the rstantools-generated src/Makevars.win in my package includes the line CXX_STD = CXX14, but I tried changing all the CXX14FLAGS in my user Makevars.win to CXX17FLAGS. This made no difference. Also, my Makevars are ignored as well when compiling a standalone model where there is no package CXX_STD.

Any advice on what’s going on here and how to fix it would be greatly appreciated.