Why does Build & Reload recompile all C++ files even when these are unchanged?

820 views Asked by At

I am using RStudio on two machines, with identical configurations, and even the same .Rproj file (from Dropbox).

From the RStudio webpage:

Incremental Rebuilds

By default RStudio performs incremental rebuilds of packages. C++ files are only recompiled when they change or any header files change. This provides fast turnaround for incremental development.

On one machine, if I modify a simple .R file, or even if I modify no files at all, and choose Build & Reload, then the C++ does not recompile.

On the other, however, I get:

With no files changed:

==> devtools::document(roclets=c('rd', 'collate', 'namespace', 'vignette'))

Updating quanteda documentation
Loading quanteda
'/Library/Frameworks/R.framework/Resources/bin/R' CMD INSTALL '/Users/kbenoit/Dropbox (Personal)/GitHub/quanteda' --library='/var/folders/46/zfn6gwj15d3_n6dhyy1cvwc00000gp/T//RtmpowXjeu/devtools_install_cd475c156859' --no-R --no-data --no-help --no-demo --no-inst --no-docs --no-exec --no-multiarch --no-test-load --preclean
Re-compiling quanteda
clang++ -std=c++11 -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG -I. -I/usr/local/include -I/usr/local/include/freetype2 -I/opt/X11/include -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/Rcpp/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/RcppParallel/include" -I"/Library/Frameworks/R.framework/Versions/3.3/Resources/library/RcppArmadillo/include"   -fPIC  -Wall -mtune=core2 -g -O2 -c RcppExports.cpp -o RcppExports.o

etc

With one .R file changed:
(which is a data documentation R file with no actual functions)

==> Rcpp::compileAttributes()

* Updated src/RcppExports.cpp
* Updated R/RcppExports.R

==> devtools::document(roclets=c('rd', 'collate', 'namespace', 'vignette'))

Updating quanteda documentation
Loading quanteda
'/Library/Frameworks/R.framework/Resources/bin/R' CMD INSTALL '/Users/kbenoit/Dropbox (Personal)/GitHub/quanteda' --library='/var/folders/46/zfn6gwj15d3_n6dhyy1cvwc00000gp/T//RtmpLaNxr4/devtools_install_cdef692abc82' --no-R --no-data --no-help --no-demo --no-inst --no-docs --no-exec --no-multiarch --no-test-load --preclean
Re-compiling quanteda

The question: How can I get the second machine to do only incremental builds when necessary, which is the supposed default behaviour?

UPDATE:

  1. I have verified that this is not due to Dropbox, after cloning to a non-Dropbox local repository and building on both machines.

  2. The problem does not go away even after using ccache in Makevars as @DirkEddelbuettel suggests (although this is a great idea for other reasons so I am now using it).

  3. The problem does go away if I uncheck Build and Reload from the Roxygen Options box from the Build Tools pane of the Project Options:

Roxygen options

1

There are 1 answers

2
Dirk is no longer here On BEST ANSWER

Fair question. Quick and somewhat related take, with some caveat:

  • I prefer to ignore / avoid devtools as I find that it obfuscates.

  • But what follows below would apply to it too.

  • The key command(s) here are R CMD INSTALL and its friends (ie R CMD SHLIB etc)

  • AFAIK these simply do NOT have the logic of make to not rebuild unless required

  • plus we are encouraged to run cleanup and remove existing artifacts

  • and having been bitten in the past, I prefer rebuilds after cleaning

all of which leads to full(er) rebuilds.

But don't despair: The single best trick is to ... avoid this by using

 CC=ccache gcc
 CXX=ccache g++

and so on, idem for clang under OS X. Just trust the awesome ccache frontend and your rebuilds (of unchanged code) will be lightning fast. I have been doing this for many, many years on my work and home machines.

Now there is a related subquestion here: when/how does RStudio run compileAttributes() for us? I am not sure. I probably relies (like make) on time stamps, and there can be issues with networked drives and shares. If in doubt I do this locally on the command-line via a littler helper script.

Edit: As a convenience, below is what I have in a local dotfile repo. I allows to set a version for gcc et al which is sometimes needed during compiler transitions. When empty (as right now) it does not harm and we just get g++ etc.

#VER=-4.9
VER=
CCACHE=ccache
CC=$(CCACHE) gcc$(VER)
CXX=$(CCACHE) g++$(VER)
CXX1X=$(CCACHE) g++$(VER)

SHLIB_CXXLD=g++$(VER)

FC=ccache gfortran
F77=ccache gfortran