GNU bug report logs - #20272
Support reproducible builds

Previous Next

Package: guile;

Reported by: ludo <at> gnu.org (Ludovic Courtès)

Date: Tue, 7 Apr 2015 11:49:01 UTC

Severity: important

Tags: patch

To reply to this bug, email your comments to 20272 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 07 Apr 2015 11:49:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to ludo <at> gnu.org (Ludovic Courtès):
New bug report received and forwarded. Copy sent to bug-guile <at> gnu.org. (Tue, 07 Apr 2015 11:49:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: bug-guile <at> gnu.org
Cc: Mark H Weaver <mhw <at> netris.org>
Subject: Support reproducible builds
Date: Tue, 07 Apr 2015 13:48:16 +0200
Currently .go files embed randomly-generated symbols stemming from
‘syntax-session-id’, which prevents reproducible builds (see
<https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)

One way to fix it would be to allow users to specify a random seed used
when generating session ids, and to make that available as a
command-line option to ‘guild compile’.  (GCC does something similar
with its ‘-frandom-seed’ option.)

Probably, ‘syntax-session-id’ would have to be a SRFI-39 parameter and
we would need a ‘fresh-syntax-session-id’ procedure that would take a
seed as a parameter.  In turn, ‘fresh_syntax_session_id’ would need to
take that extra argument, and it would need to be changed to not read
directly from /dev/urandom.

WDYT?

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Thu, 04 Feb 2016 02:42:02 GMT) Full text and rfc822 format available.

Message #8 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: ludo <at> gnu.org (Ludovic Courtès)
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Wed, 03 Feb 2016 21:41:33 -0500
ludo <at> gnu.org (Ludovic Courtès) writes:

> Currently .go files embed randomly-generated symbols stemming from
> ‘syntax-session-id’, which prevents reproducible builds (see
> <https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)
>
> One way to fix it would be to allow users to specify a random seed used
> when generating session ids, and to make that available as a
> command-line option to ‘guild compile’.  (GCC does something similar
> with its ‘-frandom-seed’ option.)

We could add this, but it is not analogous to the -frandom-seed option
where it is okay to give it the same value everywhere.  Users would need
to ensure that distinct session-ids are used for every invocation of
Guile.

More precisely, users of this feature would need to observe the
following restriction, or else unspecified behavior may result:

  If   A.go is generated by a Guile session with session-id A, and
       B.go is generated by a Guile session with session-id B, and
  they are both loaded into a Guile session with session-id C, then
  A, B, and C must all be distinct session-ids.

One more thing: even with a deterministic session-id, the multi-threaded
compiling of *.go files recently added to Guix will lead to
non-deterministic outputs.  I'm not sure how to make this work
deterministically with concurrency.  Even if we switched to a fixed
number of concurrent processes with one thread each, when process A
attempts to load a .go file that is produced by process B, it is not
deterministic whether it will be there.  If it is there, the macros in
that .go file will contain B's session-id, and if not, they will contain
A's session-id.

> Probably, ‘syntax-session-id’ would have to be a SRFI-39 parameter

This might adversely affect the efficiency of our macro expander on
platforms with slow thread local variables, and I'm not sure what it
would buy us.  If the idea is that it would allow us to build things in
multiple threads, I think that won't work anyway, for the reasons given
above.

I'm not entirely sure I've not made a mistake in my thinking, however.

     Regards,
       Mark




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Thu, 04 Feb 2016 09:37:02 GMT) Full text and rfc822 format available.

Message #11 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Mark H Weaver <mhw <at> netris.org>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 04 Feb 2016 10:35:48 +0100
Mark H Weaver <mhw <at> netris.org> skribis:

> ludo <at> gnu.org (Ludovic Courtès) writes:
>
>> Currently .go files embed randomly-generated symbols stemming from
>> ‘syntax-session-id’, which prevents reproducible builds (see
>> <https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)
>>
>> One way to fix it would be to allow users to specify a random seed used
>> when generating session ids, and to make that available as a
>> command-line option to ‘guild compile’.  (GCC does something similar
>> with its ‘-frandom-seed’ option.)
>
> We could add this, but it is not analogous to the -frandom-seed option
> where it is okay to give it the same value everywhere.  Users would need
> to ensure that distinct session-ids are used for every invocation of
> Guile.

With GCC the common idiom is to use ‘-frandom-seed=$source_file’.

However, it would be best if ‘guild compile’ would choose the seed
deterministically by default somehow, because we cannot expect all users
to add the new flag and use properly.

What about having ‘guild compile’ use the canonical file name of the
source being compiled (or a hash thereof) as the seed?

> More precisely, users of this feature would need to observe the
> following restriction, or else unspecified behavior may result:
>
>   If   A.go is generated by a Guile session with session-id A, and
>        B.go is generated by a Guile session with session-id B, and
>   they are both loaded into a Guile session with session-id C, then
>   A, B, and C must all be distinct session-ids.

Right.

I wonder if we could detect collisions.  Ideally each .go could record
its session ID, but that’s probably not feasible in 2.0.

> One more thing: even with a deterministic session-id, the multi-threaded
> compiling of *.go files recently added to Guix will lead to
> non-deterministic outputs.  I'm not sure how to make this work
> deterministically with concurrency.  Even if we switched to a fixed
> number of concurrent processes with one thread each, when process A
> attempts to load a .go file that is produced by process B, it is not
> deterministic whether it will be there.  If it is there, the macros in
> that .go file will contain B's session-id, and if not, they will contain
> A's session-id.

Hmm, OK.  Well, let’s keep this use case aside for now.

>> Probably, ‘syntax-session-id’ would have to be a SRFI-39 parameter
>
> This might adversely affect the efficiency of our macro expander on
> platforms with slow thread local variables, and I'm not sure what it
> would buy us.  If the idea is that it would allow us to build things in
> multiple threads, I think that won't work anyway, for the reasons given
> above.

I was just thinking that it would be a convenient interface for (scripts
compile) to specify the session ID to use.

I think the first thing to do is to change ‘fresh_syntax_session_id’ so
that they can use a user-specified seed, when available, instead of
‘scm_i_random_bytes_from_platform’.

WDYT?

Thanks for working on it!  :-)

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Thu, 11 Feb 2016 07:11:01 GMT) Full text and rfc822 format available.

Message #14 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: ludo <at> gnu.org (Ludovic Courtès)
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 11 Feb 2016 02:09:55 -0500
ludo <at> gnu.org (Ludovic Courtès) writes:

> Currently .go files embed randomly-generated symbols stemming from
> ‘syntax-session-id’, which prevents reproducible builds (see
> <https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)

I've given this more thought, and I think I have a way that avoids
session-ids altogether.

Currently, we include both the session-id and a global gensym counter in
the names of freshly generated marks and labels in psyntax.scm.
Instead, let them include the module name and a per-module counter.

More later...

    Mark




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Fri, 12 Feb 2016 16:30:01 GMT) Full text and rfc822 format available.

Message #17 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Mark H Weaver <mhw <at> netris.org>
To: ludo <at> gnu.org (Ludovic Courtès)
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Fri, 12 Feb 2016 11:29:23 -0500
[Message part 1 (text/plain, inline)]
Mark H Weaver <mhw <at> netris.org> writes:

> ludo <at> gnu.org (Ludovic Courtès) writes:
>
>> Currently .go files embed randomly-generated symbols stemming from
>> ‘syntax-session-id’, which prevents reproducible builds (see
>> <https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)
>
> I've given this more thought, and I think I have a way that avoids
> session-ids altogether.
>
> Currently, we include both the session-id and a global gensym counter in
> the names of freshly generated marks and labels in psyntax.scm.
> Instead, let them include the module name and a per-module counter.

I've attached a preliminary implementation of this idea, but I'm not yet
confident in its correctness.

      Mark


[0001-PRELIMINARY-psyntax-Remove-uses-of-syntax-session-id.patch (text/x-patch, inline)]
From c5ce1d3ac0ccf76e0ceadf4980f2cd72379b31d8 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw <at> netris.org>
Date: Fri, 12 Feb 2016 11:19:38 -0500
Subject: [PATCH] PRELIMINARY: psyntax: Remove uses of syntax-session-id.

This is an attempted fix for <https://debbugs.gnu.org/20272>,
but I'm not yet confident in its correctness.

* module/ice-9/boot-9.scm (module-generate-unique-id!): New procedure.
  (module): Add 'next-unique-id' field.
  (the-root-module): Inherit 'next-unique-id' value from early stub.
  (make-module, make-autoload-interface): Adjust calls to
  module-constructor.
* module/ice-9/psyntax.scm (gen-label, new-mark): Generate unique
  identifiers from the module name and the per-module unique-id.
---
 module/ice-9/boot-9.scm     | 25 +++++++++++++++++++++----
 module/ice-9/psyntax-pp.scm | 15 +++++++++++++--
 module/ice-9/psyntax.scm    | 13 ++++++++++---
 3 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 872594b..1b1f185 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1,6 +1,6 @@
 ;;; -*- mode: scheme; coding: utf-8; -*-
 
-;;;; Copyright (C) 1995-2014  Free Software Foundation, Inc.
+;;;; Copyright (C) 1995-2014, 2016  Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -381,6 +381,12 @@ If there is no handler at all, Guile prints an error and then exits."
 (define (module-ref module sym)
   (let ((v (module-variable module sym)))
     (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
+(define module-generate-unique-id!
+  (let ((next-id 0))
+    (lambda (m)
+      (let ((i next-id))
+        (set! next-id (+ i 1))
+        i))))
 (define (resolve-module . args)
   #f)
 
@@ -2018,7 +2024,8 @@ VALUE."
      submodules
      submodule-binder
      public-interface
-     filename)))
+     filename
+     next-unique-id)))
 
 
 ;; make-module &opt size uses binder
@@ -2046,7 +2053,7 @@ VALUE."
                       (make-hash-table %default-import-size)
                       '()
                       (make-weak-key-hash-table 31) #f
-                      (make-hash-table 7) #f #f #f))
+                      (make-hash-table 7) #f #f #f 0))
 
 
 
@@ -2653,6 +2660,11 @@ VALUE."
   (let ((m (make-module 0)))
     (set-module-obarray! m (%get-pre-modules-obarray))
     (set-module-name! m '(guile))
+
+    ;; Inherit next-unique-id from preliminary stub of
+    ;; %module-get-next-unique-id! defined above.
+    (set-module-next-unique-id! m (module-generate-unique-id! #f))
+
     m))
 
 ;; The root interface is a module that uses the same obarray as the
@@ -2681,6 +2693,11 @@ VALUE."
       the-root-module
       (error "unexpected module to resolve during module boot" name)))
 
+(define (module-generate-unique-id! m)
+  (let ((i (module-next-unique-id m)))
+    (set-module-next-unique-id! m (+ i 1))
+    i))
+
 ;; Cheat.  These bindings are needed by modules.c, but we don't want
 ;; to move their real definition here because that would be unnatural.
 ;;
@@ -3010,7 +3027,7 @@ VALUE."
               #:warning "Failed to autoload ~a in ~a:\n" sym name))))
     (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f
                         (make-hash-table 0) '() (make-weak-value-hash-table 31) #f
-                        (make-hash-table 0) #f #f #f)))
+                        (make-hash-table 0) #f #f #f 0)))
 
 (define (module-autoload! module . args)
   "Have @var{module} automatically load the module named @var{name} when one
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index 1ec5107..c81b69e 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -312,7 +312,12 @@
          (values x (car w)))))
    (gen-label
      (lambda ()
-       (string-append "l-" (session-id) (symbol->string (gensym "-")))))
+       (let ((mod (current-module)))
+         (simple-format
+           #f
+           "l-~s~s"
+           (module-generate-unique-id! mod)
+           (module-name mod)))))
    (gen-labels
      (lambda (ls)
        (if (null? ls) '() (cons (gen-label) (gen-labels (cdr ls))))))
@@ -960,7 +965,13 @@
            ((transformer-environment (lambda (k) (k e r w s rib mod))))
            (rebuild-macro-output
              (p (source-wrap e (anti-mark w) s mod))
-             (gensym (string-append "m-" (session-id) "-")))))))
+             (let ((mod (current-module)))
+               (string->symbol
+                 (simple-format
+                   #f
+                   "m-~s~s"
+                   (module-generate-unique-id! mod)
+                   (module-name mod)))))))))
    (expand-body
      (lambda (body outer-form r w mod)
        (let* ((r (cons '("placeholder" placeholder) r))
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 79b353d..b9110f7 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -1,7 +1,7 @@
 ;;;; -*-scheme-*-
 ;;;;
 ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
-;;;;   2012, 2013 Free Software Foundation, Inc.
+;;;;   2012, 2013, 2016 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -642,7 +642,10 @@
     ;; labels must be comparable with "eq?", have read-write invariance,
     ;; and distinct from symbols.
     (define (gen-label)
-      (string-append "l-" (session-id) (symbol->string (gensym "-"))))
+      (let ((mod (current-module)))
+        (simple-format #f "l-~s~s"
+                       (module-generate-unique-id! mod)
+                       (module-name mod))))
 
     (define gen-labels
       (lambda (ls)
@@ -671,7 +674,11 @@
                    (cons 'shift (wrap-subst w)))))
 
     (define-syntax-rule (new-mark)
-      (gensym (string-append "m-" (session-id) "-")))
+      (let ((mod (current-module)))
+        (string->symbol
+         (simple-format #f "m-~s~s"
+                        (module-generate-unique-id! mod)
+                        (module-name mod)))))
 
     ;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
     ;; internal definitions, in which the ribcages are built incrementally
-- 
2.6.3


Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 20 Jun 2016 15:47:02 GMT) Full text and rfc822 format available.

Message #20 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> pobox.com>
To: Mark H Weaver <mhw <at> netris.org>
Cc: 20272 <at> debbugs.gnu.org, Ludovic Courtès <ludo <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Mon, 20 Jun 2016 17:46:27 +0200
On Thu 04 Feb 2016 03:41, Mark H Weaver <mhw <at> netris.org> writes:

>> Probably, ‘syntax-session-id’ would have to be a SRFI-39 parameter
>
> This might adversely affect the efficiency of our macro expander on
> platforms with slow thread local variables

I think you shouldn't worry about this.  The VM keeps a pointer to the
current thread, and accesses the dynamic state / dynamic stack from
there.  There are no pthread_getkey calls when accessing parameters in
the normal case.

Andy




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 20 Jun 2016 15:49:01 GMT) Full text and rfc822 format available.

Message #23 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> pobox.com>
To: Mark H Weaver <mhw <at> netris.org>
Cc: 20272 <at> debbugs.gnu.org, Ludovic Courtès <ludo <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Mon, 20 Jun 2016 17:48:49 +0200
On Fri 12 Feb 2016 17:29, Mark H Weaver <mhw <at> netris.org> writes:

> Mark H Weaver <mhw <at> netris.org> writes:
>
>> ludo <at> gnu.org (Ludovic Courtès) writes:
>>
>>> Currently .go files embed randomly-generated symbols stemming from
>>> ‘syntax-session-id’, which prevents reproducible builds (see
>>> <https://lists.gnu.org/archive/html/guix-devel/2013-09/msg00159.html>.)
>>
>> I've given this more thought, and I think I have a way that avoids
>> session-ids altogether.
>>
>> Currently, we include both the session-id and a global gensym counter in
>> the names of freshly generated marks and labels in psyntax.scm.
>> Instead, let them include the module name and a per-module counter.
>
> I've attached a preliminary implementation of this idea, but I'm not yet
> confident in its correctness.

Looks pretty good to me but I think we should put it off until after
2.0.12, just so we can get the release out the door.  WDYT?

Andy




Added tag(s) patch. Request was from ludo <at> gnu.org (Ludovic Courtès) to control <at> debbugs.gnu.org. (Mon, 20 Jun 2016 16:10:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Thu, 23 Jun 2016 19:23:01 GMT) Full text and rfc822 format available.

Message #28 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> pobox.com>
To: Mark H Weaver <mhw <at> netris.org>
Cc: 20272 <at> debbugs.gnu.org, Ludovic Courtès <ludo <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 23 Jun 2016 21:22:37 +0200
On Mon 20 Jun 2016 17:48, Andy Wingo <wingo <at> pobox.com> writes:

>>> Currently, we include both the session-id and a global gensym counter in
>>> the names of freshly generated marks and labels in psyntax.scm.
>>> Instead, let them include the module name and a per-module counter.
>>
>> I've attached a preliminary implementation of this idea, but I'm not yet
>> confident in its correctness.
>
> Looks pretty good to me but I think we should put it off until after
> 2.0.12, just so we can get the release out the door.  WDYT?

On the other hand, maybe including it in 2.0.12 is the right thing;
dunno.  What do you think?

Andy




Severity set to 'important' from 'normal' Request was from ludo <at> gnu.org (Ludovic Courtès) to control <at> debbugs.gnu.org. (Tue, 11 Oct 2016 07:57:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Thu, 03 Nov 2016 06:56:02 GMT) Full text and rfc822 format available.

Message #33 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Jan Nieuwenhuizen <janneke <at> gnu.org>
To: 20272 <at> debbugs.gnu.org
Subject: bug#20272: Support reproducible builds
Date: Thu, 03 Nov 2016 07:54:44 +0100
[Message part 1 (text/plain, inline)]
Hi!

[sent to guile-devel yesterday, probably should have gone here]

I have rebased Mark's patch to master and added a fix on top of that,
needed on 2.1 to pass make check.

Also, I found that to pass make check these patches depend on
(yesterday's) latest master commit

    Use atomics for async interrupts

that patch seems to depend on (at least git rebase-wise)

     Deprecate user asyncs
     Deprecate arbiters
     Fold 2.1.4 news into 2.2 news

Having these 6 patches on top op 2.1.4 has guile produce deterministic
.go files...mostly.

My client code is seems to be happy with this, however Guix tells me
that some files are still not deterministic:

    lib/guile/2.2/ccache/ice-9/peg/cache.go
    lib/guile/2.2/ccache/system/repl/coop-server.go
    lib/libguile-2.2.so.0.0.0

and in Guix's debug output (only after I removed this hoping to get
guile-next reproducible, guix informed me about the plain output
nondeterminism?)

    lib/guile/2.2/ccache/ice-9/peg/cache.go.debug
    lib/guile/2.2/ccache/web/server/http.go.debug

Any ideas on what's causing this remaining nondeterminism?

Greetings,
Jan.

[0001-PRELIMINARY-psyntax-Remove-uses-of-syntax-session-id.patch (text/x-patch, inline)]
From a52fe09b584a99ff39997c47c5aa7f4c0ca428db Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw <at> netris.org>
Date: Fri, 12 Feb 2016 11:19:38 -0500
Subject: [PATCH 1/2] PRELIMINARY: psyntax: Remove uses of syntax-session-id.

This is an attempted fix for <https://debbugs.gnu.org/20272>,
but I'm not yet confident in its correctness.

* module/ice-9/boot-9.scm (module-generate-unique-id!): New procedure.
  (module): Add 'next-unique-id' field.
  (the-root-module): Inherit 'next-unique-id' value from early stub.
  (make-module, make-autoload-interface): Adjust calls to
  module-constructor.
* module/ice-9/psyntax.scm (gen-label, new-mark): Generate unique
  identifiers from the module name and the per-module unique-id.
---
 module/ice-9/boot-9.scm     | 25 +++++++++++++++++++++----
 module/ice-9/psyntax-pp.scm | 15 +++++++++++++--
 module/ice-9/psyntax.scm    | 13 ++++++++++---
 3 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 7f62097..f1d684d 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1,6 +1,6 @@
 ;;; -*- mode: scheme; coding: utf-8; -*-
 
-;;;; Copyright (C) 1995-2014  Free Software Foundation, Inc.
+;;;; Copyright (C) 1995-2014, 2016  Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -374,6 +374,12 @@ a-cont
 (define (module-ref module sym)
   (let ((v (module-variable module sym)))
     (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
+(define module-generate-unique-id!
+  (let ((next-id 0))
+    (lambda (m)
+      (let ((i next-id))
+        (set! next-id (+ i 1))
+        i))))
 (define (resolve-module . args)
   #f)
 
@@ -1973,7 +1979,8 @@ written into the port is returned."
      submodules
      submodule-binder
      public-interface
-     filename)))
+     filename
+     next-unique-id)))
 
 
 ;; make-module &opt size uses binder
@@ -1997,7 +2004,7 @@ written into the port is returned."
                       (make-hash-table)
                       '()
                       (make-weak-key-hash-table 31) #f
-                      (make-hash-table 7) #f #f #f))
+                      (make-hash-table 7) #f #f #f 0))
 
 
 
@@ -2579,6 +2586,11 @@ written into the port is returned."
   (let ((m (make-module 0)))
     (set-module-obarray! m (%get-pre-modules-obarray))
     (set-module-name! m '(guile))
+
+    ;; Inherit next-unique-id from preliminary stub of
+    ;; %module-get-next-unique-id! defined above.
+    (set-module-next-unique-id! m (module-generate-unique-id! #f))
+
     m))
 
 ;; The root interface is a module that uses the same obarray as the
@@ -2607,6 +2619,11 @@ written into the port is returned."
       the-root-module
       (error "unexpected module to resolve during module boot" name)))
 
+(define (module-generate-unique-id! m)
+  (let ((i (module-next-unique-id m)))
+    (set-module-next-unique-id! m (+ i 1))
+    i))
+
 ;; Cheat.  These bindings are needed by modules.c, but we don't want
 ;; to move their real definition here because that would be unnatural.
 ;;
@@ -2936,7 +2953,7 @@ written into the port is returned."
               #:warning "Failed to autoload ~a in ~a:\n" sym name))))
     (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f
                         (make-hash-table 0) '() (make-weak-value-hash-table 31) #f
-                        (make-hash-table 0) #f #f #f)))
+                        (make-hash-table 0) #f #f #f 0)))
 
 (define (module-autoload! module . args)
   "Have @var{module} automatically load the module named @var{name} when one
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index d797665..207d534 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -297,7 +297,12 @@
          (values x (car w)))))
    (gen-label
      (lambda ()
-       (string-append "l-" (session-id) (symbol->string (gensym "-")))))
+       (let ((mod (current-module)))
+         (simple-format
+           #f
+           "l-~s~s"
+           (module-generate-unique-id! mod)
+           (module-name mod)))))
    (gen-labels
      (lambda (ls)
        (if (null? ls) '() (cons (gen-label) (gen-labels (cdr ls))))))
@@ -1001,7 +1006,13 @@
              (lambda ()
                (rebuild-macro-output
                  (p (source-wrap e (anti-mark w) s mod))
-                 (gensym (string-append "m-" (session-id) "-")))))))))
+                 (let ((mod (current-module)))
+                   (string->symbol
+                     (simple-format
+                       #f
+                       "m-~s~s"
+                       (module-generate-unique-id! mod)
+                       (module-name mod)))))))))))
    (expand-body
      (lambda (body outer-form r w mod)
        (let* ((r (cons '("placeholder" placeholder) r))
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 88df4c7..8fa0ff3 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -1,7 +1,7 @@
 ;;;; -*-scheme-*-
 ;;;;
 ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
-;;;;   2012, 2013, 2015 Free Software Foundation, Inc.
+;;;;   2012, 2013, 2015, 2016 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -632,7 +632,10 @@
     ;; labels must be comparable with "eq?", have read-write invariance,
     ;; and distinct from symbols.
     (define (gen-label)
-      (string-append "l-" (session-id) (symbol->string (gensym "-"))))
+      (let ((mod (current-module)))
+        (simple-format #f "l-~s~s"
+                       (module-generate-unique-id! mod)
+                       (module-name mod))))
 
     (define gen-labels
       (lambda (ls)
@@ -661,7 +664,11 @@
                    (cons 'shift (wrap-subst w)))))
 
     (define-syntax-rule (new-mark)
-      (gensym (string-append "m-" (session-id) "-")))
+      (let ((mod (current-module)))
+        (string->symbol
+         (simple-format #f "m-~s~s"
+                        (module-generate-unique-id! mod)
+                        (module-name mod)))))
 
     ;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
     ;; internal definitions, in which the ribcages are built incrementally
-- 
2.10.1

[0002-psyntax-fix-gen-label-for-unset-module.patch (text/x-patch, inline)]
From ff6ddce535d5cc02a6574fe3baf238cf6533d218 Mon Sep 17 00:00:00 2001
From: Jan Nieuwenhuizen <janneke <at> gnu.org>
Date: Tue, 1 Nov 2016 15:10:01 +0100
Subject: [PATCH 2/2] psyntax: fix gen-label for unset module.

* module/ice-9/boot-9.scm (generate-unique-id!): New function.
  (module-generate-unique-id!): Use it.
* module/ice-9/psyntax.scm (gen-label): Use it to cater for unset
  module.
* module/ice-9/psyntax-pp.scm: Regenerate.
---
 module/ice-9/boot-9.scm     | 3 ++-
 module/ice-9/psyntax-pp.scm | 2 +-
 module/ice-9/psyntax.scm    | 6 ++++--
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index f1d684d..e18818e 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -374,12 +374,13 @@ a-cont
 (define (module-ref module sym)
   (let ((v (module-variable module sym)))
     (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
-(define module-generate-unique-id!
+(define generate-unique-id!
   (let ((next-id 0))
     (lambda (m)
       (let ((i next-id))
         (set! next-id (+ i 1))
         i))))
+(define module-generate-unique-id! generate-unique-id!)
 (define (resolve-module . args)
   #f)
 
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index 207d534..c47df7f 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -301,7 +301,7 @@
          (simple-format
            #f
            "l-~s~s"
-           (module-generate-unique-id! mod)
+           (if mod (module-generate-unique-id! mod) (generate-unique-id! #f))
            (module-name mod)))))
    (gen-labels
      (lambda (ls)
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 8fa0ff3..7e5c863 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -634,8 +634,10 @@
     (define (gen-label)
       (let ((mod (current-module)))
         (simple-format #f "l-~s~s"
-                       (module-generate-unique-id! mod)
-                       (module-name mod))))
+                        (if mod
+                            (module-generate-unique-id! mod)
+                            (generate-unique-id! #f))
+                        (module-name mod))))
 
     (define gen-labels
       (lambda (ls)
-- 
2.10.1

[Message part 4 (text/plain, inline)]

-- 
Jan Nieuwenhuizen <janneke <at> gnu.org> | GNU LilyPond http://lilypond.org
Freelance IT http://JoyofSource.com | Avatar®  http://AvatarAcademy.nl  

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 14 Nov 2016 21:45:02 GMT) Full text and rfc822 format available.

Message #36 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Jan Nieuwenhuizen <janneke <at> gnu.org>
To: 20272 <at> debbugs.gnu.org
Subject: bug#20272: Support reproducible builds
Date: Mon, 14 Nov 2016 22:44:20 +0100
[Message part 1 (text/plain, inline)]
Jan Nieuwenhuizen writes:

I have been building quite some versions of Guile the past week.  There
re a couple of .go files that keep giving me problems wrt
nondeterminism:

    web/server/http.go

(define *timer* (gettimeofday)) seemed suspect, but seems harmless.

    rnrs/arithmetic/fixnums.go

make-implementation-restriction-violation seemed suspect, but commenting
it out does not seem to help.

After commenting out all of http.scm and fixnums.scm, yesterday I had 3
Guix builds on two machines (GuixSD and one Ubuntu+Guix) that were
bit-identical, but one build showed differences in

    system/repl/commands.go

Apparently most of the time this file builds deterministicly, but some
times it does not!?  Ideas?

In the mean time, one more obviously correct and trivial patch attatched
that removes a build time stamp.

Greetings,
Jan

[0001-Reproducible-build-Set-buildstamp-to-EPOCH.patch (text/x-patch, inline)]
From 2050673bffaa0ba18fabb8e92c3bc388f40bcea5 Mon Sep 17 00:00:00 2001
From: Jan Nieuwenhuizen <janneke <at> gnu.org>
Date: Fri, 4 Nov 2016 16:12:55 +0100
Subject: [PATCH] Reproducible build: Set buildstamp to EPOCH.

* libguile/Makefile.am (libpath.h): Set buildstamp to EPOCH.
---
 libguile/Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 31cff75..4471d16 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -743,7 +743,7 @@ libpath.h: $(srcdir)/Makefile.in  $(top_builddir)/config.status
 		>> libpath.tmp
 	@echo '	{ "LIBS",	   "@GUILE_LIBS@" }, \' >> libpath.tmp
 	@echo '	{ "CFLAGS",	   "@GUILE_CFLAGS@" }, \' >> libpath.tmp
-	@echo '	{ "buildstamp",    "'`date -u +'%Y-%m-%d %T'`'" }, \' >> libpath.tmp
+	@echo '	{ "buildstamp",    "'`date -u -d <at> 0`'" }, \' >> libpath.tmp
 	@echo '}' >> libpath.tmp
 	$(AM_V_GEN)mv libpath.tmp libpath.h
 
-- 
2.10.1

[Message part 3 (text/plain, inline)]
-- 
Jan Nieuwenhuizen <janneke <at> gnu.org> | GNU LilyPond http://lilypond.org
Freelance IT http://JoyofSource.com | Avatar®  http://AvatarAcademy.nl  

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Wed, 14 Dec 2016 16:27:02 GMT) Full text and rfc822 format available.

Message #39 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Wed, 14 Dec 2016 17:25:38 +0100
Hello Jan!

Jan Nieuwenhuizen <janneke <at> gnu.org> skribis:

> I have been building quite some versions of Guile the past week.  There
> re a couple of .go files that keep giving me problems wrt
> nondeterminism:
>
>     web/server/http.go
>
> (define *timer* (gettimeofday)) seemed suspect, but seems harmless.
>
>     rnrs/arithmetic/fixnums.go
>
> make-implementation-restriction-violation seemed suspect, but commenting
> it out does not seem to help.
>
> After commenting out all of http.scm and fixnums.scm, yesterday I had 3
> Guix builds on two machines (GuixSD and one Ubuntu+Guix) that were
> bit-identical, but one build showed differences in
>
>     system/repl/commands.go
>
> Apparently most of the time this file builds deterministicly, but some
> times it does not!?  Ideas?

Did you look at these differences with diffoscope?  That would be
useful.

> In the mean time, one more obviously correct and trivial patch attatched
> that removes a build time stamp.

I’ve committed something similar but that honors ‘SOURCE_DATE_EPOCH’.
So by default there’s no difference compared to the previous behavior,
but if ‘SOURCE_DATE_EPOCH’ is given, then it is used as the build date.

Thanks!

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Wed, 14 Dec 2016 23:34:02 GMT) Full text and rfc822 format available.

Message #42 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 15 Dec 2016 00:32:47 +0100
ludo <at> gnu.org (Ludovic Courtès) skribis:

> Jan Nieuwenhuizen <janneke <at> gnu.org> skribis:
>
>> I have been building quite some versions of Guile the past week.  There
>> re a couple of .go files that keep giving me problems wrt
>> nondeterminism:
>>
>>     web/server/http.go
>>
>> (define *timer* (gettimeofday)) seemed suspect, but seems harmless.
>>
>>     rnrs/arithmetic/fixnums.go
>>
>> make-implementation-restriction-violation seemed suspect, but commenting
>> it out does not seem to help.
>>
>> After commenting out all of http.scm and fixnums.scm, yesterday I had 3
>> Guix builds on two machines (GuixSD and one Ubuntu+Guix) that were
>> bit-identical, but one build showed differences in
>>
>>     system/repl/commands.go
>>
>> Apparently most of the time this file builds deterministicly, but some
>> times it does not!?  Ideas?
>
> Did you look at these differences with diffoscope?  That would be
> useful.

I built it with ‘guix build --rounds=2 -K’ and got 17 differing .go
files.  I looked at srfi/srfi-9/gnu.go with ediff + hexl-mode in Emacs
and found a dozen of “t-XYZ” and “tmp-XYZ” identifiers with a different
value for XYZ (an integer).

To be continued…

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Wed, 14 Dec 2016 23:43:02 GMT) Full text and rfc822 format available.

Message #45 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 15 Dec 2016 00:42:22 +0100
[Message part 1 (text/plain, inline)]
ludo <at> gnu.org (Ludovic Courtès) skribis:

> ludo <at> gnu.org (Ludovic Courtès) skribis:
>
>> Jan Nieuwenhuizen <janneke <at> gnu.org> skribis:
>>
>>> I have been building quite some versions of Guile the past week.  There
>>> re a couple of .go files that keep giving me problems wrt
>>> nondeterminism:
>>>
>>>     web/server/http.go
>>>
>>> (define *timer* (gettimeofday)) seemed suspect, but seems harmless.
>>>
>>>     rnrs/arithmetic/fixnums.go
>>>
>>> make-implementation-restriction-violation seemed suspect, but commenting
>>> it out does not seem to help.
>>>
>>> After commenting out all of http.scm and fixnums.scm, yesterday I had 3
>>> Guix builds on two machines (GuixSD and one Ubuntu+Guix) that were
>>> bit-identical, but one build showed differences in
>>>
>>>     system/repl/commands.go
>>>
>>> Apparently most of the time this file builds deterministicly, but some
>>> times it does not!?  Ideas?
>>
>> Did you look at these differences with diffoscope?  That would be
>> useful.
>
> I built it with ‘guix build --rounds=2 -K’ and got 17 differing .go
> files.  I looked at srfi/srfi-9/gnu.go with ediff + hexl-mode in Emacs
> and found a dozen of “t-XYZ” and “tmp-XYZ” identifiers with a different
> value for XYZ (an integer).

To demonstrate non-reproducibility (with the attached patch, which is a
rebased version of Mark’s), just build the same module twice: once with
its dependency evaluated, and then with its dependency compiled.  The
results differ:

--8<---------------cut here---------------start------------->8---
ludo <at> pluto ~/src/guile$ rm -f module/srfi/srfi-9/gnu.go module/srfi/srfi-9.go
ludo <at> pluto ~/src/guile$ make -C module srfi/srfi-9/gnu.go
make: Entering directory '/home/ludo/src/guile/module'
  GUILEC srfi/srfi-9/gnu.go
wrote `srfi/srfi-9/gnu.go'
make: Leaving directory '/home/ludo/src/guile/module'
ludo <at> pluto ~/src/guile$ mv module/srfi/srfi-9/gnu.go{,.v1}
ludo <at> pluto ~/src/guile$ make -C module srfi/srfi-9.go
make: Entering directory '/home/ludo/src/guile/module'
  GUILEC srfi/srfi-9.go
wrote `srfi/srfi-9.go'
make: Leaving directory '/home/ludo/src/guile/module'
ludo <at> pluto ~/src/guile$ make -C module srfi/srfi-9/gnu.go
make: Entering directory '/home/ludo/src/guile/module'
  GUILEC srfi/srfi-9/gnu.go
wrote `srfi/srfi-9/gnu.go'
make: Leaving directory '/home/ludo/src/guile/module'
ludo <at> pluto ~/src/guile$ mv module/srfi/srfi-9/gnu.go{,.v2}
ludo <at> pluto ~/src/guile$ diff -u module/srfi/srfi-9/gnu.go.{v1,v2}
Ciferecaj dosieroj module/srfi/srfi-9/gnu.go.v1 kaj module/srfi/srfi-9/gnu.go.v2 estas malsamaj
--8<---------------cut here---------------end--------------->8---

In gnu.go.v2 the integers appended to generated symbols are lower
because fewer symbols had to be generated.

Ludo’.

[0001-psyntax-Remove-uses-of-syntax-session-id.patch (text/x-patch, inline)]
From 4301d4b53d7243012bbf6ee4d7558910dd712330 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw <at> netris.org>
Date: Fri, 12 Feb 2016 11:19:38 -0500
Subject: [PATCH] psyntax: Remove uses of syntax-session-id.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is an attempted fix for <https://debbugs.gnu.org/20272>,
but I'm not yet confident in its correctness.

* module/ice-9/boot-9.scm (module-generate-unique-id!): New procedure.
  (module): Add 'next-unique-id' field.
  (the-root-module): Inherit 'next-unique-id' value from early stub.
  (make-module, make-autoload-interface): Adjust calls to
  module-constructor.
* module/ice-9/psyntax.scm (gen-label, new-mark): Generate unique
  identifiers from the module name and the per-module unique-id.
* module/ice-9/psyntax-pp.scm: Regenerate.

Signed-off-by: Ludovic Courtès <ludo <at> gnu.org>
---
 module/ice-9/boot-9.scm     | 25 +++++++++++++++++++++----
 module/ice-9/psyntax-pp.scm | 15 +++++++++++++--
 module/ice-9/psyntax.scm    | 11 +++++++++--
 3 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 426d831..8ef7e5f 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1,6 +1,6 @@
 ;;; -*- mode: scheme; coding: utf-8; -*-
 
-;;;; Copyright (C) 1995-2014  Free Software Foundation, Inc.
+;;;; Copyright (C) 1995-2014, 2016  Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -384,6 +384,12 @@ If there is no handler at all, Guile prints an error and then exits."
 (define (module-ref module sym)
   (let ((v (module-variable module sym)))
     (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
+(define module-generate-unique-id!
+  (let ((next-id 0))
+    (lambda (m)
+      (let ((i next-id))
+        (set! next-id (+ i 1))
+        i))))
 (define (resolve-module . args)
   #f)
 
@@ -2021,7 +2027,8 @@ VALUE."
      submodules
      submodule-binder
      public-interface
-     filename)))
+     filename
+     next-unique-id)))
 
 
 ;; make-module &opt size uses binder
@@ -2049,7 +2056,7 @@ VALUE."
                       (make-hash-table %default-import-size)
                       '()
                       (make-weak-key-hash-table 31) #f
-                      (make-hash-table 7) #f #f #f))
+                      (make-hash-table 7) #f #f #f 0))
 
 
 
@@ -2656,6 +2663,11 @@ VALUE."
   (let ((m (make-module 0)))
     (set-module-obarray! m (%get-pre-modules-obarray))
     (set-module-name! m '(guile))
+
+    ;; Inherit next-unique-id from preliminary stub of
+    ;; %module-get-next-unique-id! defined above.
+    (set-module-next-unique-id! m (module-generate-unique-id! #f))
+
     m))
 
 ;; The root interface is a module that uses the same obarray as the
@@ -2684,6 +2696,11 @@ VALUE."
       the-root-module
       (error "unexpected module to resolve during module boot" name)))
 
+(define (module-generate-unique-id! m)
+  (let ((i (module-next-unique-id m)))
+    (set-module-next-unique-id! m (+ i 1))
+    i))
+
 ;; Cheat.  These bindings are needed by modules.c, but we don't want
 ;; to move their real definition here because that would be unnatural.
 ;;
@@ -3013,7 +3030,7 @@ VALUE."
               #:warning "Failed to autoload ~a in ~a:\n" sym name))))
     (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f
                         (make-hash-table 0) '() (make-weak-value-hash-table 31) #f
-                        (make-hash-table 0) #f #f #f)))
+                        (make-hash-table 0) #f #f #f 0)))
 
 (define (module-autoload! module . args)
   "Have @var{module} automatically load the module named @var{name} when one
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index 1ec5107..c81b69e 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -312,7 +312,12 @@
          (values x (car w)))))
    (gen-label
      (lambda ()
-       (string-append "l-" (session-id) (symbol->string (gensym "-")))))
+       (let ((mod (current-module)))
+         (simple-format
+           #f
+           "l-~s~s"
+           (module-generate-unique-id! mod)
+           (module-name mod)))))
    (gen-labels
      (lambda (ls)
        (if (null? ls) '() (cons (gen-label) (gen-labels (cdr ls))))))
@@ -960,7 +965,13 @@
            ((transformer-environment (lambda (k) (k e r w s rib mod))))
            (rebuild-macro-output
              (p (source-wrap e (anti-mark w) s mod))
-             (gensym (string-append "m-" (session-id) "-")))))))
+             (let ((mod (current-module)))
+               (string->symbol
+                 (simple-format
+                   #f
+                   "m-~s~s"
+                   (module-generate-unique-id! mod)
+                   (module-name mod)))))))))
    (expand-body
      (lambda (body outer-form r w mod)
        (let* ((r (cons '("placeholder" placeholder) r))
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 79b353d..7d12469 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -642,7 +642,10 @@
     ;; labels must be comparable with "eq?", have read-write invariance,
     ;; and distinct from symbols.
     (define (gen-label)
-      (string-append "l-" (session-id) (symbol->string (gensym "-"))))
+      (let ((mod (current-module)))
+        (simple-format #f "l-~s~s"
+                       (module-generate-unique-id! mod)
+                       (module-name mod))))
 
     (define gen-labels
       (lambda (ls)
@@ -671,7 +674,11 @@
                    (cons 'shift (wrap-subst w)))))
 
     (define-syntax-rule (new-mark)
-      (gensym (string-append "m-" (session-id) "-")))
+      (let ((mod (current-module)))
+        (string->symbol
+         (simple-format #f "m-~s~s"
+                        (module-generate-unique-id! mod)
+                        (module-name mod)))))
 
     ;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
     ;; internal definitions, in which the ribcages are built incrementally
-- 
2.10.2


Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 20 Dec 2016 23:02:01 GMT) Full text and rfc822 format available.

Message #48 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Wed, 21 Dec 2016 00:00:47 +0100
[Message part 1 (text/plain, inline)]
ludo <at> gnu.org (Ludovic Courtès) skribis:

> To demonstrate non-reproducibility (with the attached patch, which is a
> rebased version of Mark’s), just build the same module twice: once with
> its dependency evaluated, and then with its dependency compiled.  The
> results differ:

[...]

> In gnu.go.v2 the integers appended to generated symbols are lower
> because fewer symbols had to be generated.

This is fixed by introducing a “per-module gensym” (patch attached; to
be applied on top of the previous one).  That way, the sequence number
in generated identifiers only depends on the module being compiled, not
on whether other modules are being interpreted or not.

The ‘module-gensym’ procedure I added adds a hash of the module name in
the identifier, to distinguish from symbols introduced by ‘gensym’.
This makes symbols 3–4 characters longer; perhaps we could avoid it.

Thoughts?

Thanks,
Ludo’.

[Message part 2 (text/x-patch, inline)]
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 8ef7e5f..5d0e727 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -390,6 +390,7 @@ If there is no handler at all, Guile prints an error and then exits."
       (let ((i next-id))
         (set! next-id (+ i 1))
         i))))
+(define module-gensym gensym)
 (define (resolve-module . args)
   #f)
 
@@ -2731,6 +2732,20 @@ VALUE."
             (nested-define-module! (resolve-module '() #f) name mod)
             (accessor mod))))))
 
+(define* (module-gensym #:optional (id " mg") (m (current-module)))
+  "Return a fresh symbol in the context of module M, based on ID (a
+string or symbol).  As long as M is a valid module, this procedure is
+deterministic."
+  (define (->string number)
+    (number->string number 16))
+
+  (if m
+      (string->symbol
+       (string-append id "-"
+                      (->string (hash (module-name m) 10000)) "-"
+                      (->string (module-generate-unique-id! m))))
+      (gensym id)))
+
 (define (make-modules-in module name)
   (or (nested-ref-module module name)
       (let ((m (make-module 31)))
@@ -4322,7 +4337,6 @@ when none is available, reading FILE-NAME with READER."
                      syntax-locally-bound-identifiers
                      syntax-session-id)))
 
-
 
 
 ;;; Place the user in the guile-user module.
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index c81b69e..e46951d 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -1483,7 +1483,8 @@
                                         s
                                         mod
                                         get-formals
-                                        (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                                        (map (lambda (tmp-c0a-a89 tmp-c0a-a88 tmp-c0a-a87)
+                                               (cons tmp-c0a-a87 (cons tmp-c0a-a88 tmp-c0a-a89)))
                                              e2*
                                              e1*
                                              args*)))
@@ -1515,7 +1516,7 @@
    (gen-var
      (lambda (id)
        (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
-         (gensym (string-append (symbol->string id) "-")))))
+         (module-gensym (symbol->string id)))))
    (lambda-var-list
      (lambda (vars)
        (let lvl ((vars vars) (ls '()) (w '(())))
@@ -1777,7 +1778,8 @@
             (apply (lambda (args e1 e2)
                      (build-it
                        '()
-                       (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                       (map (lambda (tmp-c0a-c54 tmp-c0a-c53 tmp-c0a-c52)
+                              (cons tmp-c0a-c52 (cons tmp-c0a-c53 tmp-c0a-c54)))
                             e2
                             e1
                             args)))
@@ -1789,7 +1791,8 @@
                 (apply (lambda (docstring args e1 e2)
                          (build-it
                            (list (cons 'documentation (syntax->datum docstring)))
-                           (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                           (map (lambda (tmp-c0a-c6a tmp-c0a-c69 tmp-c0a-c68)
+                                  (cons tmp-c0a-c68 (cons tmp-c0a-c69 tmp-c0a-c6a)))
                                 e2
                                 e1
                                 args)))
@@ -1812,7 +1815,8 @@
             (apply (lambda (args e1 e2)
                      (build-it
                        '()
-                       (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                       (map (lambda (tmp-c0a-c8a tmp-c0a-c89 tmp-c0a-c88)
+                              (cons tmp-c0a-c88 (cons tmp-c0a-c89 tmp-c0a-c8a)))
                             e2
                             e1
                             args)))
@@ -1824,7 +1828,8 @@
                 (apply (lambda (docstring args e1 e2)
                          (build-it
                            (list (cons 'documentation (syntax->datum docstring)))
-                           (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                           (map (lambda (tmp-c0a-ca0 tmp-c0a-c9f tmp-c0a-c9e)
+                                  (cons tmp-c0a-c9e (cons tmp-c0a-c9f tmp-c0a-ca0)))
                                 e2
                                 e1
                                 args)))
@@ -2340,7 +2345,7 @@
         (if (not (list? x))
           (syntax-violation 'generate-temporaries "invalid argument" x)))
       (let ((mod (cons 'hygiene (module-name (current-module)))))
-        (map (lambda (x) (wrap (gensym "t-") '((top)) mod)) ls))))
+        (map (lambda (x) (wrap (module-gensym "t-") '((top)) mod)) ls))))
   (set! free-identifier=?
     (lambda (x y)
       (let ((x x))
@@ -2710,7 +2715,8 @@
                          #f
                          k
                          '()
-                         (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                         (map (lambda (tmp-c0a-1 tmp-c0a tmp-c0a-10ff)
+                                (list (cons tmp-c0a-10ff tmp-c0a) tmp-c0a-1))
                               template
                               pattern
                               keyword)))
@@ -2726,7 +2732,8 @@
                              #f
                              k
                              (list docstring)
-                             (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                             (map (lambda (tmp-c0a-111a tmp-c0a-1 tmp-c0a)
+                                    (list (cons tmp-c0a tmp-c0a-1) tmp-c0a-111a))
                                   template
                                   pattern
                                   keyword)))
@@ -2741,7 +2748,8 @@
                                  dots
                                  k
                                  '()
-                                 (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                                 (map (lambda (tmp-c0a-2 tmp-c0a-1 tmp-c0a)
+                                        (list (cons tmp-c0a tmp-c0a-1) tmp-c0a-2))
                                       template
                                       pattern
                                       keyword)))
@@ -2757,7 +2765,8 @@
                                      dots
                                      k
                                      (list docstring)
-                                     (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                                     (map (lambda (tmp-c0a-2 tmp-c0a-1 tmp-c0a)
+                                            (list (cons tmp-c0a tmp-c0a-1) tmp-c0a-2))
                                           template
                                           pattern
                                           keyword)))
@@ -2876,7 +2885,7 @@
                                              (apply (lambda (p)
                                                       (if (= lev 0)
                                                         (quasilist*
-                                                          (map (lambda (tmp) (list "value" tmp)) p)
+                                                          (map (lambda (tmp-c0a-11b7) (list "value" tmp-c0a-11b7)) p)
                                                           (quasi q lev))
                                                         (quasicons
                                                           (quasicons
@@ -2894,7 +2903,8 @@
                                                  (apply (lambda (p)
                                                           (if (= lev 0)
                                                             (quasiappend
-                                                              (map (lambda (tmp) (list "value" tmp)) p)
+                                                              (map (lambda (tmp-c0a-11bc) (list "value" tmp-c0a-11bc))
+                                                                   p)
                                                               (quasi q lev))
                                                             (quasicons
                                                               (quasicons
@@ -2927,7 +2937,9 @@
                               (if tmp
                                 (apply (lambda (p)
                                          (if (= lev 0)
-                                           (quasilist* (map (lambda (tmp) (list "value" tmp)) p) (vquasi q lev))
+                                           (quasilist*
+                                             (map (lambda (tmp-c0a-11d2) (list "value" tmp-c0a-11d2)) p)
+                                             (vquasi q lev))
                                            (quasicons
                                              (quasicons
                                                '("quote" #(syntax-object unquote ((top)) (hygiene guile)))
@@ -2943,7 +2955,7 @@
                                     (apply (lambda (p)
                                              (if (= lev 0)
                                                (quasiappend
-                                                 (map (lambda (tmp) (list "value" tmp)) p)
+                                                 (map (lambda (tmp-c0a-11d7) (list "value" tmp-c0a-11d7)) p)
                                                  (vquasi q lev))
                                                (quasicons
                                                  (quasicons
@@ -3031,7 +3043,7 @@
                               (let ((tmp-1 ls))
                                 (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                   (if tmp
-                                    (apply (lambda (t) (cons "vector" t)) tmp)
+                                    (apply (lambda (t--c0a) (cons "vector" t--c0a)) tmp)
                                     (syntax-violation
                                       #f
                                       "source expression failed to match any pattern"
@@ -3039,7 +3051,8 @@
                    (let ((tmp y))
                      (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") each-any))))
                        (if tmp-1
-                         (apply (lambda (y) (k (map (lambda (tmp) (list "quote" tmp)) y)))
+                         (apply (lambda (y)
+                                  (k (map (lambda (tmp-c0a-122c) (list "quote" tmp-c0a-122c)) y)))
                                 tmp-1)
                          (let ((tmp-1 ($sc-dispatch tmp '(#(atom "list") . each-any))))
                            (if tmp-1
@@ -3048,7 +3061,8 @@
                                (if tmp-1
                                  (apply (lambda (y z) (f z (lambda (ls) (k (append y ls))))) tmp-1)
                                  (let ((else tmp))
-                                   (let ((tmp x)) (let ((t tmp)) (list "list->vector" t)))))))))))))))))
+                                   (let ((tmp x))
+                                     (let ((t--c0a-123b tmp)) (list "list->vector" t--c0a-123b)))))))))))))))))
        (emit (lambda (x)
                (let ((tmp x))
                  (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") any))))
@@ -3061,7 +3075,8 @@
                                   (let ((tmp-1 (map emit x)))
                                     (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                       (if tmp
-                                        (apply (lambda (t) (cons '#(syntax-object list ((top)) (hygiene guile)) t))
+                                        (apply (lambda (t--c0a-124a)
+                                                 (cons '#(syntax-object list ((top)) (hygiene guile)) t--c0a-124a))
                                                tmp)
                                         (syntax-violation
                                           #f
@@ -3077,8 +3092,10 @@
                                           (let ((tmp-1 (list (emit (car x*)) (f (cdr x*)))))
                                             (let ((tmp ($sc-dispatch tmp-1 '(any any))))
                                               (if tmp
-                                                (apply (lambda (t-1 t)
-                                                         (list '#(syntax-object cons ((top)) (hygiene guile)) t-1 t))
+                                                (apply (lambda (t--c0a-125e t--c0a-125d)
+                                                         (list '#(syntax-object cons ((top)) (hygiene guile))
+                                                               t--c0a-125e
+                                                               t--c0a-125d))
                                                        tmp)
                                                 (syntax-violation
                                                   #f
@@ -3091,8 +3108,9 @@
                                           (let ((tmp-1 (map emit x)))
                                             (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                               (if tmp
-                                                (apply (lambda (t)
-                                                         (cons '#(syntax-object append ((top)) (hygiene guile)) t))
+                                                (apply (lambda (t--c0a-126a)
+                                                         (cons '#(syntax-object append ((top)) (hygiene guile))
+                                                               t--c0a-126a))
                                                        tmp)
                                                 (syntax-violation
                                                   #f
@@ -3105,8 +3123,9 @@
                                               (let ((tmp-1 (map emit x)))
                                                 (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                                   (if tmp
-                                                    (apply (lambda (t)
-                                                             (cons '#(syntax-object vector ((top)) (hygiene guile)) t))
+                                                    (apply (lambda (t--c0a)
+                                                             (cons '#(syntax-object vector ((top)) (hygiene guile))
+                                                                   t--c0a))
                                                            tmp)
                                                     (syntax-violation
                                                       #f
@@ -3117,8 +3136,9 @@
                                        (if tmp-1
                                          (apply (lambda (x)
                                                   (let ((tmp (emit x)))
-                                                    (let ((t tmp))
-                                                      (list '#(syntax-object list->vector ((top)) (hygiene guile)) t))))
+                                                    (let ((t--c0a tmp))
+                                                      (list '#(syntax-object list->vector ((top)) (hygiene guile))
+                                                            t--c0a))))
                                                 tmp-1)
                                          (let ((tmp-1 ($sc-dispatch tmp '(#(atom "value") any))))
                                            (if tmp-1
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 7d12469..13e15be 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -1,7 +1,7 @@
 ;;;; -*-scheme-*-
 ;;;;
 ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
-;;;;   2012, 2013 Free Software Foundation, Inc.
+;;;;   2012, 2013, 2016 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -460,9 +460,10 @@
               (make-letrec src in-order? ids vars val-exps body-exp)))))
 
 
-    ;; FIXME: use a faster gensym
     (define-syntax-rule (build-lexical-var src id)
-      (gensym (string-append (symbol->string id) "-")))
+      ;; Use a per-module counter instead of the global counter of
+      ;; 'gensym' so that the generated identifier is reproducible.
+      (module-gensym (symbol->string id)))
 
     (define-structure (syntax-object expression wrap module))
 
@@ -2598,7 +2599,9 @@
           (lambda (ls)
             (arg-check list? ls 'generate-temporaries)
             (let ((mod (cons 'hygiene (module-name (current-module)))))
-              (map (lambda (x) (wrap (gensym "t-") top-wrap mod)) ls))))
+              (map (lambda (x)
+                     (wrap (module-gensym "t-") top-wrap mod))
+                   ls))))
 
     (set! free-identifier=?
           (lambda (x y)
diff --git a/module/language/tree-il/fix-letrec.scm b/module/language/tree-il/fix-letrec.scm
index 60c87e3..23d37a8 100644
--- a/module/language/tree-il/fix-letrec.scm
+++ b/module/language/tree-il/fix-letrec.scm
@@ -1,6 +1,6 @@
 ;;; transformation of letrec into simpler forms
 
-;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2010, 2011, 2012, 2016 Free Software Foundation, Inc.
 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -267,7 +267,9 @@
                     ;; bindings, in a `let' to indicate that order doesn't
                     ;; matter, and bind to their variables.
                     (list
-                     (let ((tmps (map (lambda (x) (gensym)) c)))
+                     (let ((tmps (map (lambda (x)
+                                        (module-gensym "fixlr"))
+                                      c)))
                        (make-let
                         #f (map cadr c) tmps (map caddr c)
                         (make-sequence
diff --git a/module/system/base/syntax.scm b/module/system/base/syntax.scm
index 249961d..d280869 100644
--- a/module/system/base/syntax.scm
+++ b/module/system/base/syntax.scm
@@ -1,6 +1,6 @@
 ;;; Guile VM specific syntaxes and utilities
 
-;; Copyright (C) 2001, 2009 Free Software Foundation, Inc
+;; Copyright (C) 2001, 2009, 2016 Free Software Foundation, Inc
 
 ;;; This library is free software; you can redistribute it and/or
 ;;; modify it under the terms of the GNU Lesser General Public
@@ -72,7 +72,7 @@
                            '()
                            (cons (car slots) (lp (cdr slots))))))
                (opts (list-tail slots (length reqs)))
-               (tail (gensym)))
+               (tail (module-gensym "defrec")))
           `(define (,(symbol-append 'make- stem) ,@reqs . ,tail)
              (let ,(map (lambda (o)
                           `(,(car o) (cond ((null? ,tail) ,(cadr o))
@@ -243,8 +243,8 @@
 ;; code looks good.
 
 (define-macro (transform-record type-and-common record . clauses)
-  (let ((r (gensym))
-        (rtd (gensym))
+  (let ((r (module-gensym "rec"))
+        (rtd (module-gensym "rtd"))
         (type-stem (trim-brackets (car type-and-common))))
     (define (make-stem s)
       (symbol-append type-stem '- s))

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Wed, 21 Dec 2016 23:55:01 GMT) Full text and rfc822 format available.

Message #51 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Andy Wingo <wingo <at> igalia.com>
Subject: Re: bug#20272: Support reproducible builds
Date: Thu, 22 Dec 2016 00:53:20 +0100
[Message part 1 (text/plain, inline)]
With the attached patch I can build ‘stable-2.0’ with --rounds=2 and
there are no discrepancies.

I’ll apply it next week if there are no objections.

Next I’ll adjust it for ‘master’.

Thanks,
Ludo’.

[0001-psyntax-Generate-identifiers-in-a-deterministic-fash.patch (text/x-patch, inline)]
From 33ac270ad8d6f2fbb7fcb07294d1149aa82caf9e Mon Sep 17 00:00:00 2001
From: Mark H Weaver <mhw <at> netris.org>
Date: Fri, 12 Feb 2016 11:19:38 -0500
Subject: [PATCH] psyntax: Generate identifiers in a deterministic fashion.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Fixes <http://bugs.gnu.org/20272>.

* module/ice-9/boot-9.scm (module-generate-unique-id!)
(module-gensym): New procedures.
(module): Add 'next-unique-id' field.
(the-root-module): Inherit 'next-unique-id' value from early stub.
(make-module, make-autoload-interface): Adjust calls to
module-constructor.
* module/ice-9/psyntax.scm (gen-label, new-mark): Generate unique
identifiers from the module name and the per-module unique-id.
(build-lexical-var, generate-temporaries): Use
'module-gensym' instead of 'gensym'.
* module/ice-9/psyntax-pp.scm: Regenerate.
* module/language/tree-il/fix-letrec.scm (fix-letrec!): Use
'module-gensym' instead of 'gensym'.
* module/system/base/syntax.scm (define-record): Likewise.
(transform-record): Likewise.

Co-authored-by: Ludovic Courtès <ludo <at> gnu.org>
---
 module/ice-9/boot-9.scm                | 42 +++++++++++++++--
 module/ice-9/psyntax-pp.scm            | 83 +++++++++++++++++++++-------------
 module/ice-9/psyntax.scm               | 15 +++---
 module/language/tree-il/fix-letrec.scm |  6 ++-
 module/system/base/syntax.scm          |  8 ++--
 5 files changed, 106 insertions(+), 48 deletions(-)

diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index 426d831..7f35325 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -1,6 +1,6 @@
 ;;; -*- mode: scheme; coding: utf-8; -*-
 
-;;;; Copyright (C) 1995-2014  Free Software Foundation, Inc.
+;;;; Copyright (C) 1995-2014, 2016  Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -384,6 +384,13 @@ If there is no handler at all, Guile prints an error and then exits."
 (define (module-ref module sym)
   (let ((v (module-variable module sym)))
     (if v (variable-ref v) (error "badness!" (pk module) (pk sym)))))
+(define module-generate-unique-id!
+  (let ((next-id 0))
+    (lambda (m)
+      (let ((i next-id))
+        (set! next-id (+ i 1))
+        i))))
+(define module-gensym gensym)
 (define (resolve-module . args)
   #f)
 
@@ -2021,7 +2028,8 @@ VALUE."
      submodules
      submodule-binder
      public-interface
-     filename)))
+     filename
+     next-unique-id)))
 
 
 ;; make-module &opt size uses binder
@@ -2049,7 +2057,7 @@ VALUE."
                       (make-hash-table %default-import-size)
                       '()
                       (make-weak-key-hash-table 31) #f
-                      (make-hash-table 7) #f #f #f))
+                      (make-hash-table 7) #f #f #f 0))
 
 
 
@@ -2656,6 +2664,11 @@ VALUE."
   (let ((m (make-module 0)))
     (set-module-obarray! m (%get-pre-modules-obarray))
     (set-module-name! m '(guile))
+
+    ;; Inherit next-unique-id from preliminary stub of
+    ;; %module-get-next-unique-id! defined above.
+    (set-module-next-unique-id! m (module-generate-unique-id! #f))
+
     m))
 
 ;; The root interface is a module that uses the same obarray as the
@@ -2684,6 +2697,11 @@ VALUE."
       the-root-module
       (error "unexpected module to resolve during module boot" name)))
 
+(define (module-generate-unique-id! m)
+  (let ((i (module-next-unique-id m)))
+    (set-module-next-unique-id! m (+ i 1))
+    i))
+
 ;; Cheat.  These bindings are needed by modules.c, but we don't want
 ;; to move their real definition here because that would be unnatural.
 ;;
@@ -2714,6 +2732,21 @@ VALUE."
             (nested-define-module! (resolve-module '() #f) name mod)
             (accessor mod))))))
 
+(define* (module-gensym #:optional (id " mg") (m (current-module)))
+  "Return a fresh symbol in the context of module M, based on ID (a
+string or symbol).  As long as M is a valid module, this procedure is
+deterministic."
+  (define (->string number)
+    (number->string number 16))
+
+  (if m
+      (string->symbol
+       (string-append id "-"
+                      (->string (hash (module-name m) most-positive-fixnum))
+                      "-"
+                      (->string (module-generate-unique-id! m))))
+      (gensym id)))
+
 (define (make-modules-in module name)
   (or (nested-ref-module module name)
       (let ((m (make-module 31)))
@@ -3013,7 +3046,7 @@ VALUE."
               #:warning "Failed to autoload ~a in ~a:\n" sym name))))
     (module-constructor (make-hash-table 0) '() b #f #f name 'autoload #f
                         (make-hash-table 0) '() (make-weak-value-hash-table 31) #f
-                        (make-hash-table 0) #f #f #f)))
+                        (make-hash-table 0) #f #f #f 0)))
 
 (define (module-autoload! module . args)
   "Have @var{module} automatically load the module named @var{name} when one
@@ -4305,7 +4338,6 @@ when none is available, reading FILE-NAME with READER."
                      syntax-locally-bound-identifiers
                      syntax-session-id)))
 
-
 
 
 ;;; Place the user in the guile-user module.
diff --git a/module/ice-9/psyntax-pp.scm b/module/ice-9/psyntax-pp.scm
index 1ec5107..3df661d 100644
--- a/module/ice-9/psyntax-pp.scm
+++ b/module/ice-9/psyntax-pp.scm
@@ -310,9 +310,7 @@
            (syntax-object-expression x)
            (join-marks (car w) (car (syntax-object-wrap x))))
          (values x (car w)))))
-   (gen-label
-     (lambda ()
-       (string-append "l-" (session-id) (symbol->string (gensym "-")))))
+   (gen-label (lambda () (symbol->string (module-gensym "l"))))
    (gen-labels
      (lambda (ls)
        (if (null? ls) '() (cons (gen-label) (gen-labels (cdr ls))))))
@@ -960,7 +958,7 @@
            ((transformer-environment (lambda (k) (k e r w s rib mod))))
            (rebuild-macro-output
              (p (source-wrap e (anti-mark w) s mod))
-             (gensym (string-append "m-" (session-id) "-")))))))
+             (module-gensym "m"))))))
    (expand-body
      (lambda (body outer-form r w mod)
        (let* ((r (cons '("placeholder" placeholder) r))
@@ -1472,7 +1470,8 @@
                                         s
                                         mod
                                         get-formals
-                                        (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                                        (map (lambda (tmp-bde397a-a85 tmp-bde397a-a84 tmp-bde397a-a83)
+                                               (cons tmp-bde397a-a83 (cons tmp-bde397a-a84 tmp-bde397a-a85)))
                                              e2*
                                              e1*
                                              args*)))
@@ -1504,7 +1503,7 @@
    (gen-var
      (lambda (id)
        (let ((id (if (syntax-object? id) (syntax-object-expression id) id)))
-         (gensym (string-append (symbol->string id) "-")))))
+         (module-gensym (symbol->string id)))))
    (lambda-var-list
      (lambda (vars)
        (let lvl ((vars vars) (ls '()) (w '(())))
@@ -1766,7 +1765,8 @@
             (apply (lambda (args e1 e2)
                      (build-it
                        '()
-                       (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                       (map (lambda (tmp-bde397a-c50 tmp-bde397a-c4f tmp-bde397a-c4e)
+                              (cons tmp-bde397a-c4e (cons tmp-bde397a-c4f tmp-bde397a-c50)))
                             e2
                             e1
                             args)))
@@ -1778,7 +1778,8 @@
                 (apply (lambda (docstring args e1 e2)
                          (build-it
                            (list (cons 'documentation (syntax->datum docstring)))
-                           (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                           (map (lambda (tmp-bde397a-c66 tmp-bde397a-c65 tmp-bde397a-c64)
+                                  (cons tmp-bde397a-c64 (cons tmp-bde397a-c65 tmp-bde397a-c66)))
                                 e2
                                 e1
                                 args)))
@@ -1801,7 +1802,8 @@
             (apply (lambda (args e1 e2)
                      (build-it
                        '()
-                       (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                       (map (lambda (tmp-bde397a-c86 tmp-bde397a-c85 tmp-bde397a-c84)
+                              (cons tmp-bde397a-c84 (cons tmp-bde397a-c85 tmp-bde397a-c86)))
                             e2
                             e1
                             args)))
@@ -1813,7 +1815,8 @@
                 (apply (lambda (docstring args e1 e2)
                          (build-it
                            (list (cons 'documentation (syntax->datum docstring)))
-                           (map (lambda (tmp-2 tmp-1 tmp) (cons tmp (cons tmp-1 tmp-2)))
+                           (map (lambda (tmp-bde397a-c9c tmp-bde397a-c9b tmp-bde397a-c9a)
+                                  (cons tmp-bde397a-c9a (cons tmp-bde397a-c9b tmp-bde397a-c9c)))
                                 e2
                                 e1
                                 args)))
@@ -2329,7 +2332,7 @@
         (if (not (list? x))
           (syntax-violation 'generate-temporaries "invalid argument" x)))
       (let ((mod (cons 'hygiene (module-name (current-module)))))
-        (map (lambda (x) (wrap (gensym "t-") '((top)) mod)) ls))))
+        (map (lambda (x) (wrap (module-gensym "t") '((top)) mod)) ls))))
   (set! free-identifier=?
     (lambda (x y)
       (let ((x x))
@@ -2699,7 +2702,8 @@
                          #f
                          k
                          '()
-                         (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                         (map (lambda (tmp-bde397a-10fd tmp-bde397a-10fc tmp-bde397a-10fb)
+                                (list (cons tmp-bde397a-10fb tmp-bde397a-10fc) tmp-bde397a-10fd))
                               template
                               pattern
                               keyword)))
@@ -2715,7 +2719,8 @@
                              #f
                              k
                              (list docstring)
-                             (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                             (map (lambda (tmp-bde397a-2 tmp-bde397a-1 tmp-bde397a)
+                                    (list (cons tmp-bde397a tmp-bde397a-1) tmp-bde397a-2))
                                   template
                                   pattern
                                   keyword)))
@@ -2730,7 +2735,8 @@
                                  dots
                                  k
                                  '()
-                                 (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                                 (map (lambda (tmp-bde397a-112f tmp-bde397a-112e tmp-bde397a-112d)
+                                        (list (cons tmp-bde397a-112d tmp-bde397a-112e) tmp-bde397a-112f))
                                       template
                                       pattern
                                       keyword)))
@@ -2746,7 +2752,8 @@
                                      dots
                                      k
                                      (list docstring)
-                                     (map (lambda (tmp-2 tmp-1 tmp) (list (cons tmp tmp-1) tmp-2))
+                                     (map (lambda (tmp-bde397a-114e tmp-bde397a-114d tmp-bde397a-114c)
+                                            (list (cons tmp-bde397a-114c tmp-bde397a-114d) tmp-bde397a-114e))
                                           template
                                           pattern
                                           keyword)))
@@ -2865,7 +2872,9 @@
                                              (apply (lambda (p)
                                                       (if (= lev 0)
                                                         (quasilist*
-                                                          (map (lambda (tmp) (list "value" tmp)) p)
+                                                          (map (lambda (tmp-bde397a-11b3)
+                                                                 (list "value" tmp-bde397a-11b3))
+                                                               p)
                                                           (quasi q lev))
                                                         (quasicons
                                                           (quasicons
@@ -2883,7 +2892,9 @@
                                                  (apply (lambda (p)
                                                           (if (= lev 0)
                                                             (quasiappend
-                                                              (map (lambda (tmp) (list "value" tmp)) p)
+                                                              (map (lambda (tmp-bde397a-11b8)
+                                                                     (list "value" tmp-bde397a-11b8))
+                                                                   p)
                                                               (quasi q lev))
                                                             (quasicons
                                                               (quasicons
@@ -2916,7 +2927,9 @@
                               (if tmp
                                 (apply (lambda (p)
                                          (if (= lev 0)
-                                           (quasilist* (map (lambda (tmp) (list "value" tmp)) p) (vquasi q lev))
+                                           (quasilist*
+                                             (map (lambda (tmp-bde397a-11ce) (list "value" tmp-bde397a-11ce)) p)
+                                             (vquasi q lev))
                                            (quasicons
                                              (quasicons
                                                '("quote" #(syntax-object unquote ((top)) (hygiene guile)))
@@ -2932,7 +2945,7 @@
                                     (apply (lambda (p)
                                              (if (= lev 0)
                                                (quasiappend
-                                                 (map (lambda (tmp) (list "value" tmp)) p)
+                                                 (map (lambda (tmp-bde397a-11d3) (list "value" tmp-bde397a-11d3)) p)
                                                  (vquasi q lev))
                                                (quasicons
                                                  (quasicons
@@ -3020,7 +3033,7 @@
                               (let ((tmp-1 ls))
                                 (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                   (if tmp
-                                    (apply (lambda (t) (cons "vector" t)) tmp)
+                                    (apply (lambda (t-bde397a-121c) (cons "vector" t-bde397a-121c)) tmp)
                                     (syntax-violation
                                       #f
                                       "source expression failed to match any pattern"
@@ -3028,7 +3041,8 @@
                    (let ((tmp y))
                      (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") each-any))))
                        (if tmp-1
-                         (apply (lambda (y) (k (map (lambda (tmp) (list "quote" tmp)) y)))
+                         (apply (lambda (y)
+                                  (k (map (lambda (tmp-bde397a) (list "quote" tmp-bde397a)) y)))
                                 tmp-1)
                          (let ((tmp-1 ($sc-dispatch tmp '(#(atom "list") . each-any))))
                            (if tmp-1
@@ -3037,7 +3051,8 @@
                                (if tmp-1
                                  (apply (lambda (y z) (f z (lambda (ls) (k (append y ls))))) tmp-1)
                                  (let ((else tmp))
-                                   (let ((tmp x)) (let ((t tmp)) (list "list->vector" t)))))))))))))))))
+                                   (let ((tmp x))
+                                     (let ((t-bde397a tmp)) (list "list->vector" t-bde397a)))))))))))))))))
        (emit (lambda (x)
                (let ((tmp x))
                  (let ((tmp-1 ($sc-dispatch tmp '(#(atom "quote") any))))
@@ -3050,7 +3065,8 @@
                                   (let ((tmp-1 (map emit x)))
                                     (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                       (if tmp
-                                        (apply (lambda (t) (cons '#(syntax-object list ((top)) (hygiene guile)) t))
+                                        (apply (lambda (t-bde397a)
+                                                 (cons '#(syntax-object list ((top)) (hygiene guile)) t-bde397a))
                                                tmp)
                                         (syntax-violation
                                           #f
@@ -3066,8 +3082,10 @@
                                           (let ((tmp-1 (list (emit (car x*)) (f (cdr x*)))))
                                             (let ((tmp ($sc-dispatch tmp-1 '(any any))))
                                               (if tmp
-                                                (apply (lambda (t-1 t)
-                                                         (list '#(syntax-object cons ((top)) (hygiene guile)) t-1 t))
+                                                (apply (lambda (t-bde397a-125a t-bde397a)
+                                                         (list '#(syntax-object cons ((top)) (hygiene guile))
+                                                               t-bde397a-125a
+                                                               t-bde397a))
                                                        tmp)
                                                 (syntax-violation
                                                   #f
@@ -3080,8 +3098,9 @@
                                           (let ((tmp-1 (map emit x)))
                                             (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                               (if tmp
-                                                (apply (lambda (t)
-                                                         (cons '#(syntax-object append ((top)) (hygiene guile)) t))
+                                                (apply (lambda (t-bde397a)
+                                                         (cons '#(syntax-object append ((top)) (hygiene guile))
+                                                               t-bde397a))
                                                        tmp)
                                                 (syntax-violation
                                                   #f
@@ -3094,8 +3113,9 @@
                                               (let ((tmp-1 (map emit x)))
                                                 (let ((tmp ($sc-dispatch tmp-1 'each-any)))
                                                   (if tmp
-                                                    (apply (lambda (t)
-                                                             (cons '#(syntax-object vector ((top)) (hygiene guile)) t))
+                                                    (apply (lambda (t-bde397a)
+                                                             (cons '#(syntax-object vector ((top)) (hygiene guile))
+                                                                   t-bde397a))
                                                            tmp)
                                                     (syntax-violation
                                                       #f
@@ -3106,8 +3126,9 @@
                                        (if tmp-1
                                          (apply (lambda (x)
                                                   (let ((tmp (emit x)))
-                                                    (let ((t tmp))
-                                                      (list '#(syntax-object list->vector ((top)) (hygiene guile)) t))))
+                                                    (let ((t-bde397a-127e tmp))
+                                                      (list '#(syntax-object list->vector ((top)) (hygiene guile))
+                                                            t-bde397a-127e))))
                                                 tmp-1)
                                          (let ((tmp-1 ($sc-dispatch tmp '(#(atom "value") any))))
                                            (if tmp-1
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index 79b353d..c09a551 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -1,7 +1,7 @@
 ;;;; -*-scheme-*-
 ;;;;
 ;;;; Copyright (C) 2001, 2003, 2006, 2009, 2010, 2011,
-;;;;   2012, 2013 Free Software Foundation, Inc.
+;;;;   2012, 2013, 2016 Free Software Foundation, Inc.
 ;;;;
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -460,9 +460,10 @@
               (make-letrec src in-order? ids vars val-exps body-exp)))))
 
 
-    ;; FIXME: use a faster gensym
     (define-syntax-rule (build-lexical-var src id)
-      (gensym (string-append (symbol->string id) "-")))
+      ;; Use a per-module counter instead of the global counter of
+      ;; 'gensym' so that the generated identifier is reproducible.
+      (module-gensym (symbol->string id)))
 
     (define-structure (syntax-object expression wrap module))
 
@@ -642,7 +643,7 @@
     ;; labels must be comparable with "eq?", have read-write invariance,
     ;; and distinct from symbols.
     (define (gen-label)
-      (string-append "l-" (session-id) (symbol->string (gensym "-"))))
+      (symbol->string (module-gensym "l")))
 
     (define gen-labels
       (lambda (ls)
@@ -671,7 +672,7 @@
                    (cons 'shift (wrap-subst w)))))
 
     (define-syntax-rule (new-mark)
-      (gensym (string-append "m-" (session-id) "-")))
+      (module-gensym "m"))
 
     ;; make-empty-ribcage and extend-ribcage maintain list-based ribcages for
     ;; internal definitions, in which the ribcages are built incrementally
@@ -2591,7 +2592,9 @@
           (lambda (ls)
             (arg-check list? ls 'generate-temporaries)
             (let ((mod (cons 'hygiene (module-name (current-module)))))
-              (map (lambda (x) (wrap (gensym "t-") top-wrap mod)) ls))))
+              (map (lambda (x)
+                     (wrap (module-gensym "t") top-wrap mod))
+                   ls))))
 
     (set! free-identifier=?
           (lambda (x y)
diff --git a/module/language/tree-il/fix-letrec.scm b/module/language/tree-il/fix-letrec.scm
index 60c87e3..23d37a8 100644
--- a/module/language/tree-il/fix-letrec.scm
+++ b/module/language/tree-il/fix-letrec.scm
@@ -1,6 +1,6 @@
 ;;; transformation of letrec into simpler forms
 
-;; Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2010, 2011, 2012, 2016 Free Software Foundation, Inc.
 
 ;;;; This library is free software; you can redistribute it and/or
 ;;;; modify it under the terms of the GNU Lesser General Public
@@ -267,7 +267,9 @@
                     ;; bindings, in a `let' to indicate that order doesn't
                     ;; matter, and bind to their variables.
                     (list
-                     (let ((tmps (map (lambda (x) (gensym)) c)))
+                     (let ((tmps (map (lambda (x)
+                                        (module-gensym "fixlr"))
+                                      c)))
                        (make-let
                         #f (map cadr c) tmps (map caddr c)
                         (make-sequence
diff --git a/module/system/base/syntax.scm b/module/system/base/syntax.scm
index 249961d..d280869 100644
--- a/module/system/base/syntax.scm
+++ b/module/system/base/syntax.scm
@@ -1,6 +1,6 @@
 ;;; Guile VM specific syntaxes and utilities
 
-;; Copyright (C) 2001, 2009 Free Software Foundation, Inc
+;; Copyright (C) 2001, 2009, 2016 Free Software Foundation, Inc
 
 ;;; This library is free software; you can redistribute it and/or
 ;;; modify it under the terms of the GNU Lesser General Public
@@ -72,7 +72,7 @@
                            '()
                            (cons (car slots) (lp (cdr slots))))))
                (opts (list-tail slots (length reqs)))
-               (tail (gensym)))
+               (tail (module-gensym "defrec")))
           `(define (,(symbol-append 'make- stem) ,@reqs . ,tail)
              (let ,(map (lambda (o)
                           `(,(car o) (cond ((null? ,tail) ,(cadr o))
@@ -243,8 +243,8 @@
 ;; code looks good.
 
 (define-macro (transform-record type-and-common record . clauses)
-  (let ((r (gensym))
-        (rtd (gensym))
+  (let ((r (module-gensym "rec"))
+        (rtd (module-gensym "rtd"))
         (type-stem (trim-brackets (car type-and-common))))
     (define (make-stem s)
       (symbol-append type-stem '- s))
-- 
2.10.2


Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Fri, 30 Dec 2016 21:02:01 GMT) Full text and rfc822 format available.

Message #54 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Andy Wingo <wingo <at> igalia.com>
Subject: Re: bug#20272: Support reproducible builds
Date: Fri, 30 Dec 2016 22:00:21 +0100
ludo <at> gnu.org (Ludovic Courtès) skribis:

> With the attached patch I can build ‘stable-2.0’ with --rounds=2 and
> there are no discrepancies.
>
> I’ll apply it next week if there are no objections.

Pushed as 458ae248ab353af24e27b8fb3e5fe7a8b78ae219!

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 28 Feb 2017 13:27:02 GMT) Full text and rfc822 format available.

Message #57 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> pobox.com>
To: ludo <at> gnu.org (Ludovic Courtès)
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Jan Nieuwenhuizen <janneke <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Tue, 28 Feb 2017 14:26:26 +0100
On Thu 22 Dec 2016 00:53, ludo <at> gnu.org (Ludovic Courtès) writes:

> +(define (module-generate-unique-id! m)
> +  (let ((i (module-next-unique-id m)))
> +    (set-module-next-unique-id! m (+ i 1))
> +    i))

This introduces a race condition when expanding from multiple threads at
once.  Any plan here?

Andy




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Sun, 05 Mar 2017 20:51:01 GMT) Full text and rfc822 format available.

Message #60 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Andy Wingo <wingo <at> pobox.com>
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Jan Nieuwenhuizen <janneke <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Sun, 05 Mar 2017 21:49:58 +0100
Hi!

Andy Wingo <wingo <at> pobox.com> skribis:

> On Thu 22 Dec 2016 00:53, ludo <at> gnu.org (Ludovic Courtès) writes:
>
>> +(define (module-generate-unique-id! m)
>> +  (let ((i (module-next-unique-id m)))
>> +    (set-module-next-unique-id! m (+ i 1))
>> +    i))
>
> This introduces a race condition when expanding from multiple threads at
> once.  Any plan here?

Good point!  We could grab a per-module mutex for that, though that’s
again a fat mutex.

Thoughts?

Ludo’.




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 06 Mar 2017 20:14:01 GMT) Full text and rfc822 format available.

Message #63 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andy Wingo <wingo <at> pobox.com>
To: ludo <at> gnu.org (Ludovic Courtès)
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Jan Nieuwenhuizen <janneke <at> gnu.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Mon, 06 Mar 2017 21:13:00 +0100
Hi,

On Sun 05 Mar 2017 21:49, ludo <at> gnu.org (Ludovic Courtès) writes:

> Andy Wingo <wingo <at> pobox.com> skribis:
>
>> On Thu 22 Dec 2016 00:53, ludo <at> gnu.org (Ludovic Courtès) writes:
>>
>>> +(define (module-generate-unique-id! m)
>>> +  (let ((i (module-next-unique-id m)))
>>> +    (set-module-next-unique-id! m (+ i 1))
>>> +    i))
>>
>> This introduces a race condition when expanding from multiple threads at
>> once.  Any plan here?
>
> Good point!  We could grab a per-module mutex for that, though that’s
> again a fat mutex.
>
> Thoughts?

I would use atomic boxes if possible, but they are in another module :/
Even mutexes aren't directly available in boot-9 any more... Alternately
we can make a new primitive for module-generate-unique-id! which can
obviously use C.  That's probably the easiest option, sadly!

Andy




Reply sent to ludo <at> gnu.org (Ludovic Courtès):
You have taken responsibility. (Tue, 07 Mar 2017 19:57:01 GMT) Full text and rfc822 format available.

Notification sent to ludo <at> gnu.org (Ludovic Courtès):
bug acknowledged by developer. (Tue, 07 Mar 2017 19:57:02 GMT) Full text and rfc822 format available.

Message #68 received at 20272-done <at> debbugs.gnu.org (full text, mbox):

From: ludo <at> gnu.org (Ludovic Courtès)
To: Jan Nieuwenhuizen <janneke <at> gnu.org>
Cc: 20272-done <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>,
 Andy Wingo <wingo <at> igalia.com>
Subject: Re: bug#20272: Support reproducible builds
Date: Tue, 07 Mar 2017 20:55:36 +0100
ludo <at> gnu.org (Ludovic Courtès) skribis:

> ludo <at> gnu.org (Ludovic Courtès) skribis:
>
>> With the attached patch I can build ‘stable-2.0’ with --rounds=2 and
>> there are no discrepancies.
>>
>> I’ll apply it next week if there are no objections.
>
> Pushed as 458ae248ab353af24e27b8fb3e5fe7a8b78ae219!

Applied as commit 84a740d86a5afd235f1b47ac66c88db010b1d56b in master (2.1).

I haven’t yet done a --rounds=2 build of master, but hopefully that’ll
be fine!

Ludo’.




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Wed, 05 Apr 2017 11:24:04 GMT) Full text and rfc822 format available.

Did not alter fixed versions and reopened. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Mon, 23 Sep 2019 08:03:01 GMT) Full text and rfc822 format available.

bug unarchived. Request was from andi <at> notmuch.email to control <at> debbugs.gnu.org. (Mon, 01 Jun 2020 21:00:02 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 01 Jun 2020 21:01:01 GMT) Full text and rfc822 format available.

Message #77 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Rammhold <andi <at> notmuch.email>
To: 20272 <at> debbugs.gnu.org
Subject: Re: Support reproducible builds
Date: Mon, 1 Jun 2020 22:45:51 +0200
I've just stumpled upon this as within Nixpkgs we have a pending [PR]
that references this issue. Since it reads as if it should be solved in
Guile 2.1+ but still occurs for us in nixpkgs when using parallel builds
(aka using multiple cores in a single build) I thought it might be a
good to get in touch.

Updating our expression to Guile 3.0.2 did not fix the reproducibility
issues either (when built using multiple cores).

I've just now tried a Guix 1.1.0 QEMU image and invoked `guix build
--round=2 -K guile --check -c 8` and it also wasn't reproducible. A
bunch of .go files showed differences between the builds.

Am I missings something?

Would gladly help if there is something I can do.

[PR]: https://github.com/NixOS/nixpkgs/pull/78778




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 02 Jun 2020 12:26:02 GMT) Full text and rfc822 format available.

Message #80 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Rammhold <andi <at> notmuch.email>
To: 20272 <at> debbugs.gnu.org
Subject: Support reproducible builds
Date: Tue, 2 Jun 2020 14:25:24 +0200
I've just stumpled upon this as within Nixpkgs we have a pending [PR]
that references this issue. Since it reads as if it should be solved in
Guile 2.1+ but still occurs for us in nixpkgs when using parallel builds
(aka using multiple cores in a single build) I thought it might be a
good to get in touch.

Updating our expression to Guile 3.0.2 did not fix the reproducibility
issues either (when built using multiple cores).

I've just now tried a Guix 1.1.0 QEMU image and invoked `guix build
--round=2 -K guile --check -c 8` and it also wasn't reproducible. A
bunch of .go files showed differences between the builds.

Am I missings something?

Would gladly help if there is something I can do.

[PR]: https://github.com/NixOS/nixpkgs/pull/78778




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Wed, 01 Jul 2020 11:24:06 GMT) Full text and rfc822 format available.

bug unarchived. Request was from Maxim Cournoyer <maxim.cournoyer <at> gmail.com> to control <at> debbugs.gnu.org. (Thu, 08 Oct 2020 16:20:03 GMT) Full text and rfc822 format available.

Did not alter fixed versions and reopened. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Thu, 08 Oct 2020 16:20:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 24 Nov 2020 04:46:02 GMT) Full text and rfc822 format available.

Message #89 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: Vagrant Cascadian <vagrant <at> reproducible-builds.org>
To: Maxim Cournoyer <maxim.cournoyer <at> gmail.com>, Ludovic Courtès <ludo <at> gnu.org>
Cc: 20272 <at> debbugs.gnu.org, Mark H Weaver <mhw <at> netris.org>
Subject: Re: bug#20272: Support reproducible builds
Date: Mon, 23 Nov 2020 20:44:56 -0800
[Message part 1 (text/plain, inline)]
On 2020-10-08, Maxim Cournoyer wrote:
> I've hit a .go non-reproducibility issue fairly trivially on
> core-updates.  I think it sufficed to change a core library file (e.g.,
> commit 7102c18678dc02d5ee6c77a9a70ae344482af841 which touched (guix
> build utils)) and then attempting to build something with --rounds=2
> flagged it:
>
> --8<---------------cut here---------------start------------->8---
> ./pre-inst-env guix build --rounds=2 mit-krb5 -K --no-substitutes
>
> building /gnu/store/74fh18318l4f9zmkl3y3klyasnc1jqc2-module-import-compiled.drv...
> building /gnu/store/40wzfd27s4i50rc1q86dqks986ff8fq2-module-import-compiled.drv...
> building /gnu/store/dlzy98gvyddjg3zrv5f1l3nvgjvaxjmf-module-import-compiled.drv...
> building /gnu/store/0i3sqm9cl2rbbikfas2y28wibnmqr1pa-module-import-compiled.drv...
> [ 1/ 2] Loading './guix/build/utils.scm'...
> [ 2/ 2] Compiling './guix/build/utils.scm'...
> building /gnu/store/dlzy98gvyddjg3zrv5f1l3nvgjvaxjmf-module-import-compiled.drv...
> building /gnu/store/40wzfd27s4i50rc1q86dqks986ff8fq2-module-import-compiled.drv...
> output ‘/gnu/store/czbmygd6id8qk3bfb0rcjjkmpn5bh7f1-module-import-compiled’ of ‘/gnu/store/dlzy98gvyddjg3zrv5f1l3nvgjvaxjmf-module-import-compiled.drv’ differs from ‘/gnu/store/czbmygd6id8qk3bfb0rcjjkmpn5bh7f1-module-import-compiled-check’ from previous round
> build of /gnu/store/dlzy98gvyddjg3zrv5f1l3nvgjvaxjmf-module-import-compiled.drv failed
> View build log at '/var/log/guix/drvs/dl/zy98gvyddjg3zrv5f1l3nvgjvaxjmf-module-import-compiled.drv.bz2'.
> --8<---------------cut here---------------end--------------->8---

I'm not *positive* this is the same issue, but disabling parallelism
building the Debian package of guix appears to fix reproducibility of
almost all of the .go files... (the one exception is gnu/ci.go embeds
the build path, and just filed a bug for that: #44835)

https://tests.reproducible-builds.org/debian/rb-pkg/experimental/i386/diffoscope-results/guix.html

Notice the somewhat arbitrary list of different gnu/packages/*.scm files
and arbitrary order:

./usr/lib/i386-linux-gnu/guile/3.0/site-ccache/gnu/packages/admin.go

strings --all --bytes=8 {}
Offset 1402, 20 lines modified	Offset 1402, 20 lines modified
1402 	-4AI[4-AI[-4AI[	1402 	-4AI[4-AI[-4AI[
1403 	Guile·3.0.4                     1403 	Guile·3.0.4
1404 	arguments	                    1404 	arguments
1405 	native-inputs	                1405 	native-inputs
1406 	propagated-inputs	            1406 	propagated-inputs
1407 	sunxi-tools-source	            1407 	sunxi-tools-source
1408 	gnu/packages/admin.scm	        1408 	gnu/packages/admin.scm
                                        1409 	gnu/packages/aidc.scm
1409 	gnu/packages/algebra.scm        1410 	gnu/packages/algebra.scm
1410 	gnu/packages/anthy.scm	        1411 	gnu/packages/anthy.scm
1411 	gnu/packages/android.scm        1412 	gnu/packages/android.scm
1412 	gnu/packages/animation.scm	 
1413 	gnu/packages/aidc.scm	 
1414 	gnu/packages/agda.scm           1413 	gnu/packages/agda.scm
                                        1414 	gnu/packages/adns.scm
1415 	arguments                       1415 	arguments
1416 	native-inputs                   1416 	native-inputs
1417 	propagated-inputs	            1417 	propagated-inputs
1418 	sunxi-tools-source	            1418 	sunxi-tools-source
1419 	file-name	                    1419 	file-name
1420 	build-system                    1420 	build-system
1421 	supported-systems	            1421 	supported-systems


While building in serial rather than parallel is a significant slowdown,
it seems like being able to build reproducibly might be worth the cost,
at least for certain guix variants, such as the package used for
guix-daemon... I'll likely disable parallel building for the next guix
upload to Debian, at least. :)


live well,
  vagrant
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Fri, 17 Nov 2023 20:29:02 GMT) Full text and rfc822 format available.

Message #92 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: "Bernhard M. Wiedemann" <bwiedemann <at> suse.de>
To: 20272 <at> debbugs.gnu.org
Subject: Support reproducible builds
Date: Fri, 17 Nov 2023 21:28:08 +0100
[Message part 1 (text/plain, inline)]
Parallel builds with guile-3.0.9 still introduce non-determinism

I tested with openSUSE's guile-newt package
and found (with filterdiff[1])
filterdiff strings */site-ccache/newt/checkboxtree.go
produced among others

 newtCheckboxTree
-/usr/lib64/libnewt
+config
+%libnewt
 dynamic-link
 dynamic-func

[...]

 newt/bindings.scm
 newt/checkboxtree.scm
-newt/config.scm
 ice-9/boot-9.scm
 make-checkboxtree


so it is not just a simple ordering issue, but certain entries are 
missing or replaced.
Is there an equivalent of objdump for .go files to see what is in there?


[1]https://github.com/bmwiedemann/reproducibleopensuse/blob/master/filterdiff
[OpenPGP_signature.asc (application/pgp-signature, attachment)]

Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Mon, 08 Apr 2024 17:29:03 GMT) Full text and rfc822 format available.

Message #95 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: "Thompson, David" <dthompson2 <at> worcester.edu>
To: "Bernhard M. Wiedemann" <bwiedemann <at> suse.de>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Mon, 8 Apr 2024 13:27:40 -0400
On Fri, Nov 17, 2023 at 3:29 PM Bernhard M. Wiedemann
<bwiedemann <at> suse.de> wrote:
>
> Parallel builds with guile-3.0.9 still introduce non-determinism

I recently learned that the cross-module inlining optimization pass is
a source of nondeterminism. If module A imports module B, inlining of
procedures from B into A may occur *if* B has already been compiled.
Depending on the value of n in `make -j $n` you will likely get a
different build.

While working on Guile Hoot, I encountered a bug on my machine that
Andy Wingo couldn't reproduce on his. Turns out it was because my
`make -j6` build was different from his `make -j32` build. I don't
recall the details but apparently Guile's bootstrap process takes
great care to avoid sequencing issues like this.

I don't know what the solution might be, though. I want parallel *and*
reproducible builds!

- Dave




Information forwarded to bug-guile <at> gnu.org:
bug#20272; Package guile. (Tue, 09 Apr 2024 04:03:02 GMT) Full text and rfc822 format available.

Message #98 received at 20272 <at> debbugs.gnu.org (full text, mbox):

From: "Bernhard M. Wiedemann" <bwiedemann <at> suse.de>
To: "Thompson, David" <dthompson2 <at> worcester.edu>
Cc: 20272 <at> debbugs.gnu.org
Subject: Re: bug#20272: Support reproducible builds
Date: Tue, 9 Apr 2024 06:02:33 +0200
[Message part 1 (text/plain, inline)]

On 08/04/2024 19.27, Thompson, David wrote:
> I don't know what the solution might be, though. I want parallel *and*
> reproducible builds!

For openSUSE we are using -j1 builds everywhere until a better solution 
is found.
https://code.opensuse.org/package/guix/blob/006c5b9d16/f/guix.spec#_112


> If module A imports module B, inlining of
> procedures from B into A may occur *if* B has already been compiled.

So this means, module A would need to wait for compilation of B to 
finish, so that it always inlines it.

This could be implemented either in Makefile or guile.

Ciao
Bernhard M.
[OpenPGP_signature.asc (application/pgp-signature, attachment)]

This bug report was last modified 258 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.