[Rd] Revisiting and updating reproducible builds for base R in Debian

Dirk Eddelbuettel edd @end|ng |rom deb|@n@org
Wed Aug 5 00:16:21 CEST 2026


tl;dr: I would need help from someone in R Core to see why package 'tools' is
treated differently here. Please read on -- I am reasonably close to decent
progress but quite madly not quite there yet.


Reproducible builds, now also at https://reproducible-builds.org/ was once a
more niche idea within Debian. It is very much a release goal for Debian.
Being able to produce bit-by-bit identical artifacts upon repeated builds is
seen my many as a good goal towards better security, validation, and
reproducibility. Over time many packages got patched to optionally skip
'current timestamp' or machine IDs during build.

Overall, the status is generally good, and available for each (source or
binary) package via the status and qa pages [1]. For Debian as a whole most
packages now pass. For example, all the CRAN packages are in good shape and
pass.  The r-base package however is not there yet, and we can see the 'diff'
between consecutive builds [2][3].  The diffs (via [2]) clearly show that
most of the difference comes from the included packages. (There are a few
more, we can get to the remaining ones in the next iteration.)

As for enabling this for the base R package, we did an initial push in 2015
and Martin Maechler committed some changes allowing the use of passing a
'time stamp' at build time via an make variable PKG_BUILT_STAMP. The build
when instrumented for it retrieves a timestamp from the most-recent value in
the debian/changelog file. I had that disabled of late (since early 2025 it
seems) but have over the last few days looked into revitalizing it. (There
was a brief confusion earlier this year as to whether this impacts Simon's
scheme of ordering builds by the Built: flag, and it does not. This is AFAIK
only used for the Debian build; everything else remains as it is.)

In short, the PKG_BUILT_STAMP variable is used in two make rules from the
file share/make/basepkg.mk.  The rules mkdesc (for packages base and tools)
and mkdesc2 (for all others) check this for being non-empty, and if so pass
it on. (Oddly, in mkdesc it is passed to an R helper function that parses the
timestamp and returns an ISO-formatted one in UTC; in mkdesc2 it is passed
on; the resulting Built: entry always show ISO-format in UTC so from mkdesc2
it must also be parsed and replaced somewhere but I do not know where. This
could be related.)

The upshot is that I currently managed to cover all but one: 'tools' does not
behave. This outcome is identical between a local build of R-devel on my
machine (setting PKG_BUILT_STAMP in the shell script I use to drive the build
with the options I typically use) and local tests builds of the Debian
package. See [4] for the result from R-devel and [5] for the same for
R-release when locally updating the R package for Debian and installing it in
a container.

I am setting the PKG_BUILT_STAMP at all appropriate 'make' calls; this is
easiest for R-devel as there are only 'make' and 'make install'.  For the
Debian package it is similar but we have more calls (and 'make' and eg 'make
doc' are done separately, there is 'make check' and more). Now, I would truly
appreciate a nudge and helping hand from someone in R Core: when / where /
why is tools different, and when does it get re-configure / re-installed?  I
can take from my logs that the timestamp is passed on at first. (I removed
the @ from the snippet to have the code visible, and added a marker for
quicker search, see [6]).

Thanks for reading this far, and caring about a somewhat esoteric issue. Any
help would be appreciated; I am currently a little blocked on this as I can't
quite figure out when/where tools gets updated again.

Cheers, Dirk


[1] Mine is at https://qa.debian.org/developer.php?login=edd&comaint=yes 
and the info is in the fourth-last column

[2] A summary page is https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/r-base.html
from which get differences displayed in
https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/diffoscope-results/r-base.html
and also in text form
https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/diffoscope-results/r-base.html

[3] A second summary page is at https://reproduce.debian.net/excuses.html?source_name=r-base

[4] A quick grep across the installation of R-devel below /usr/local/lib
shows tools as the outlier with the current date, all others echo the last
changelog date of the R Debian package (accessed here only to fetch that timestamp)
edd using paul:~/svn/r-devel$ grep '^Built' /usr/local/lib/R-devel/lib/R/library/*/DESCRIPTION |grep 2026-08-0
/usr/local/lib/R-devel/lib/R/library/base/DESCRIPTION:Built: R 4.7.0; ; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/compiler/DESCRIPTION:Built: R 4.7.0; ; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/datasets/DESCRIPTION:Built: R 4.7.0; ; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/graphics/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/grDevices/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/grid/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/methods/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/parallel/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/splines/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/stats4/DESCRIPTION:Built: R 4.7.0; ; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/stats/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/tcltk/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/local/lib/R-devel/lib/R/library/tools/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-04 21:56:44 UTC; unix
/usr/local/lib/R-devel/lib/R/library/utils/DESCRIPTION:Built: R 4.7.0; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
edd using paul:~/svn/r-devel$ 

[5] Similar for R-release via the Debian build using currently uncommitted
local changes.
root using 893920fad19e:/work# grep Built: /usr/lib/R/library/*/DESCRIPTION | grep 2026-08-0
/usr/lib/R/library/base/DESCRIPTION:Built: R 4.6.1; ; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/compiler/DESCRIPTION:Built: R 4.6.1; ; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/datasets/DESCRIPTION:Built: R 4.6.1; ; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/graphics/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/grDevices/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/grid/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/methods/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/parallel/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/splines/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/stats4/DESCRIPTION:Built: R 4.6.1; ; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/stats/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/tcltk/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
/usr/lib/R/library/tools/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-04 21:10:07 UTC; unix
/usr/lib/R/library/utils/DESCRIPTION:Built: R 4.6.1; x86_64-pc-linux-gnu; 2026-08-02 16:37:21 UTC; unix
root using 893920fad19e:/work# 

[6] During the build, tools gets the timestamp passes just as all the other
base packages do. From the log (after removing one '@') seeing the code from
basepkg.mk, not now the correct Aug 2, 11:37:21 Central gets passed that then
gets reparsed:
make[5]: Entering directory '/build/r-base-4.6.1/src/library/tools'
echo "xxxxxx"; \
if test "Sun, 02 Aug 2026 11:37:21 -0500" != ""; then \
  echo "Built: R 4.6.1; ; Sun, 02 Aug 2026 11:37:21 -0500; unix" \
     >> ../../../library/tools/DESCRIPTION ; \
else \
  echo "Built: R 4.6.1; ; `TZ=UTC date`; unix" \
     >> ../../../library/tools/DESCRIPTION ; \
fi
xxxxxx


-- 
dirk.eddelbuettel.com | @eddelbuettel | edd using debian.org



More information about the R-devel mailing list