[R-SIG-Mac] Rebuild binaries when a LinkingTo dependency changes

Simon Urbanek @|mon@urb@nek @end|ng |rom R-project@org
Tue Sep 26 04:36:31 CEST 2023



> On 26/09/2023, at 12:28 PM, Kirill Müller <kirill using cynkra.com> wrote:
> 
> Thanks, Simon and Uwe, for your inputs.
> 
> It's not that TMB requires a particular version of Matrix, it just suggests using the same version of Matrix as it was built with. We may have seen this problem before, with innocuous changes in Rcpp breaking downstream packages.
> 
> A different example, running in two separate sessions for comparison, is shown below.
> 

That looks like an issue in TMB - is there really a problem between the two versions or is TMB just making it up? I strongly suspect the latter.


> Windows may be rebuilding more often than strictly necessary, but it seems the right thing to do to me. We could assess the overhead using historic data to see how big of an impact that would be.
> 
> I hear you're proposing that the TMB maintainers release an updated version whenever Matrix is updated?
> 

Short answer is no for most people, except TMB's own current behavior requires it (by its own design) so it depends on what the TMB maintainers really want - if they really want to insist on very specific Matrix version (for whatever reason), then yes.

The version generally doesn't matter in vast majority of cases, because packages typically don't make changes that break their reverse dependencies - which is why the check like that TMB does is generally not very helpful since it is way too conservative to the point of being uninformative. Even if you use LinkingTo, you should not be relying on internal behavior of a very specific version of a package - that's the whole point of defined API like what packages present through the LinkingTo-API - you only request a version of the API regardless of its implementation. If you use a new feature then you obviously have to bump your version and specify the the new version of your dependency so that problem doesn't arise. So there is an issue only if your dependency makes a change which breaks your own package (which is extremely rare - in the case of Matrix it is unfortunate, mostly due to issues in the S4 implementation) and then the only reliable solution is to bump your version since the two binaries are undistinguishable. The problem is that there is no automated way to do that - pretty much the dependency has to tell you or you have to find out yourself.

As I was explaining this is not about re-building - it doesn't help because it's not generally available to users as they have no way to know that they need to re-install exactly the same version of a package like TMB - unless the package bumps the version. Essentially the users would have to remove and re-install all packages every time they update a single one which is not realistic.

Cheers,
Simon


> 
> Best regards
> 
> Kirill
> 
> 
> 
> # Example 1: happy path
> 
> dir.create("templib")
> .libPaths(normalizePath("templib"))
> Sys.setenv(R_LIBS_USER = .libPaths()[[1]])
> 
> # Sanity check
> rownames(installed.packages())
> #>  [1] "base"       "boot"       "class"      "cluster"    "codetools" 
> #>  [6] "compiler"   "datasets"   "foreign"    "graphics"   "grDevices" 
> #> [11] "grid"       "KernSmooth" "lattice"    "MASS"       "Matrix"    
> #> [16] "methods"    "mgcv"       "nlme"       "nnet"       "parallel"  
> #> [21] "rpart"      "spatial"    "splines"    "stats"      "stats4"    
> #> [26] "survival"   "tcltk"      "tools"      "utils"
> packageVersion("Matrix")
> #> [1] '1.5.4.1'
> 
> # Install TMB from source, now matching the Matrix version
> install.packages(c("Rcpp", "RcppEigen"))
> #> Installing packages into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpSL7Etm/reprex-bc8b35150024-vague-bull/templib'
> #> (as 'lib' is unspecified)
> #> 
> #> The downloaded binary packages are in
> #>  /var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T//RtmpOpHc0P/downloaded_packages
> install.packages("TMB", type = "source", repos = "https://cloud.r-project.org/")
> #> Installing package into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpSL7Etm/reprex-bc8b35150024-vague-bull/templib'
> #> (as 'lib' is unspecified)
> 
> # Perform implicit consistency check
> packageVersion("Matrix")
> #> [1] '1.5.4.1'
> requireNamespace("TMB")
> #> Loading required namespace: TMB
> 
> 
> 
> # Example 2: upgrading Matrix after installing TMB
> 
> dir.create("templib")
> .libPaths(normalizePath("templib"))
> Sys.setenv(R_LIBS_USER = .libPaths()[[1]])
> 
> # Sanity check
> rownames(installed.packages())
> #>  [1] "base"       "boot"       "class"      "cluster"    "codetools" 
> #>  [6] "compiler"   "datasets"   "foreign"    "graphics"   "grDevices" 
> #> [11] "grid"       "KernSmooth" "lattice"    "MASS"       "Matrix"    
> #> [16] "methods"    "mgcv"       "nlme"       "nnet"       "parallel"  
> #> [21] "rpart"      "spatial"    "splines"    "stats"      "stats4"    
> #> [26] "survival"   "tcltk"      "tools"      "utils"
> packageVersion("Matrix")
> #> [1] '1.5.4.1'
> 
> # Install TMB from source, now matching the Matrix version
> install.packages(c("Rcpp", "RcppEigen"))
> #> Installing packages into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpSL7Etm/reprex-bc8b4fff25a6-next-esok/templib'
> #> (as 'lib' is unspecified)
> #> 
> #> The downloaded binary packages are in
> #>  /var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T//RtmpyN9yHv/downloaded_packages
> install.packages("TMB", type = "source", repos = "https://cloud.r-project.org/")
> #> Installing package into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpSL7Etm/reprex-bc8b4fff25a6-next-esok/templib'
> #> (as 'lib' is unspecified)
> 
> # Upgrading Matrix
> install.packages("Matrix")
> #> Installing package into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpSL7Etm/reprex-bc8b4fff25a6-next-esok/templib'
> #> (as 'lib' is unspecified)
> #> 
> #> The downloaded binary packages are in
> #>  /var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T//RtmpyN9yHv/downloaded_packages
> 
> # Perform implicit consistency check
> packageVersion("Matrix")
> #> [1] '1.6.1.1'
> requireNamespace("TMB")
> #> Loading required namespace: TMB
> #> Warning in checkMatrixPackageVersion(): Package version inconsistency detected.
> #> TMB was built with Matrix version 1.5.4.1
> #> Current Matrix version is 1.6.1.1
> #> Please re-install 'TMB' from source using install.packages('TMB', type = 'source') or ask CRAN for a binary version of 'TMB' matching CRAN's 'Matrix' package
> 
> 
> 
> On 25.09.23 15:22, Simon Urbanek wrote:
>> Kirill,
>> 
>> we have no way of knowing when a packages introduced a breaking change (which it really shouldn't), so the maintainers would have to inform as (Matrix authors did inform us that 1.6.0 introduces breaking change so that's why we did a manual re-bulid on that update). Also checking exact version (like TMB seems to do) doesn't work for the same reason and is not a good way to deal with the problem - we cannot re-build all packages with each change, because of the amount of time that would take (by now it takes more that a day to re-build CRAN just for one R target) and more fundamental problem with re-builds:
>> 
>> The real problem here is deeper than just triggering rebuilds: the users have no way of knowing if a package has been re-built and updated, because the version does not change. If let's say TMB is release 1.0 used Matrix 1.6.0 and then Matrix is updated to 1.6.1 then TMB cannot require it because it did not bump its version, i.e. the binary for TMB 1.0 with Matrix 1.6.0 is indistinguishable from a binary of TMB 1.0 with Matrix 1.6.1 on CRAN so if the user used update.packages() it would not count as a new TMB version. Therefore TMB really has to update its version from 1.0 to let's say 1.0-1 if it requests a rebuild against changes in Matrix 1.6.1. Clearly, this is not ideal, but currently there is other way that would guarantee consistency of binaries. We are aware of the problem and we are we are in fact thinking about possible solutions (special tags on binary versions) for future version of R, but for now the package authors have to be aware of potential breakage upstream.
>> 
>> Cheers,
>> Simon
>> 
>> 
>> 
>>> On 26/09/2023, at 7:46 AM, Kirill Müller via R-SIG-Mac <r-sig-mac using r-project.org>
>>>  wrote:
>>> 
>>> Hi
>>> 
>>> 
>>> The TMB package has Matrix in its LinkingTo dependencies. In a clean package library, I see behavior posted below.
>>> 
>>> Should the TMB package have been rebuilt when a new version of the Matrix package was pushed? More general, should we rebuild all reverse LinkingTo dependencies of a package that gets an update on CRAN? This will mean a lot of package rebuilds with Rcpp, but also a lot less frustration down the road. Thanks!
>>> 
>>> 
>>> Best regards
>>> 
>>> Kirill
>>> 
>>> 
>>> dir.create("templib")
>>> .libPaths(normalizePath("templib"))
>>> 
>>> # Sanity check
>>> rownames(installed.packages())
>>> #>  [1] "base"       "boot"       "class"      "cluster" "codetools"
>>> #>  [6] "compiler"   "datasets"   "foreign"    "graphics" "grDevices"
>>> #> [11] "grid"       "KernSmooth" "lattice"    "MASS" "Matrix"
>>> #> [16] "methods"    "mgcv"       "nlme"       "nnet" "parallel"
>>> #> [21] "rpart"      "spatial"    "splines"    "stats" "stats4"
>>> #> [26] "survival"   "tcltk"      "tools"      "utils"
>>> packageVersion("Matrix")
>>> #> [1] '1.5.4.1'
>>> 
>>> # Install fresh binary packages
>>> install.packages(c("Matrix", "TMB"))
>>> #> Installing packages into '/private/var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T/RtmpXIjIPy/reprex-87aa25cc1fa4-sugar-cob/templib'
>>> #> (as 'lib' is unspecified)
>>> #> also installing the dependencies 'Rcpp', 'RcppEigen'
>>> #>
>>> #> The downloaded binary packages are in
>>> #> /var/folders/dj/yhk9rkx97wn_ykqtnmk18xvc0000gn/T//Rtmp4GSL7m/downloaded_packages
>>> packageVersion("Matrix")
>>> #> [1] '1.6.1.1'
>>> 
>>> # Perform implicit consistency check
>>> requireNamespace("TMB")
>>> #> Loading required namespace: TMB
>>> #> Warning in checkMatrixPackageVersion(): Package version inconsistency detected.
>>> #> TMB was built with Matrix version 1.6.0
>>> #> Current Matrix version is 1.6.1.1
>>> #> Please re-install 'TMB' from source using install.packages('TMB', type = 'source') or ask CRAN for a binary version of 'TMB' matching CRAN's 'Matrix' package
>>> 
>>> _______________________________________________
>>> R-SIG-Mac mailing list
>>> 
>>> R-SIG-Mac using r-project.org
>>> https://stat.ethz.ch/mailman/listinfo/r-sig-mac
>>> 
>>> 
>>> 



More information about the R-SIG-Mac mailing list