guix build: Add '--rounds'.
* guix/scripts/build.scm (show-build-options-help) (%standard-build-options): Add --rounds. (set-build-options-from-command-line): Honor it. * doc/guix.texi (Invoking guix build): Document it. * doc/contributing.texi (Submitting Patches): Mention it.
This commit is contained in:
		
							parent
							
								
									2fba87ac7c
								
							
						
					
					
						commit
						5b74fe065b
					
				
					 3 changed files with 44 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -279,15 +279,31 @@ not affected by the change; @code{guix refresh --list-dependent
 | 
			
		|||
@var{package}} will help you do that (@pxref{Invoking guix refresh}).
 | 
			
		||||
 | 
			
		||||
@item
 | 
			
		||||
@cindex determinism, of build processes
 | 
			
		||||
@cindex reproducible builds, checking
 | 
			
		||||
Check whether the package's build process is deterministic.  This
 | 
			
		||||
typically means checking whether an independent build of the package
 | 
			
		||||
yields the exact same result that you obtained, bit for bit.
 | 
			
		||||
 | 
			
		||||
A simple way to do that is with @command{guix challenge}
 | 
			
		||||
(@pxref{Invoking guix challenge}).  You may run it once the package has
 | 
			
		||||
been committed and built by @code{hydra.gnu.org} to check whether it
 | 
			
		||||
obtains the same result as you did.  Better yet: Find another machine
 | 
			
		||||
that can build it and run @command{guix publish}.
 | 
			
		||||
A simple way to do that is by building the same package several times in
 | 
			
		||||
a row on your machine (@pxref{Invoking guix build}):
 | 
			
		||||
 | 
			
		||||
@example
 | 
			
		||||
guix build --rounds=2 my-package
 | 
			
		||||
@end example
 | 
			
		||||
 | 
			
		||||
This is enough to catch a class of common non-determinism issues, such
 | 
			
		||||
as timestamps or randomly-generated output in the build result.
 | 
			
		||||
 | 
			
		||||
Another option is to use @command{guix challenge} (@pxref{Invoking guix
 | 
			
		||||
challenge}).  You may run it once the package has been committed and
 | 
			
		||||
built by @code{hydra.gnu.org} to check whether it obtains the same
 | 
			
		||||
result as you did.  Better yet: Find another machine that can build it
 | 
			
		||||
and run @command{guix publish}.  Since the remote build machine is
 | 
			
		||||
likely different from yours, this can catch non-determinism issues
 | 
			
		||||
related to the hardware---e.g., use of different instruction set
 | 
			
		||||
extensions---or to the operating system kernel---e.g., reliance on
 | 
			
		||||
@code{uname} or @file{/proc} files.
 | 
			
		||||
 | 
			
		||||
@end enumerate
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3876,6 +3876,20 @@ Do not use substitutes for build products.  That is, always build things
 | 
			
		|||
locally instead of allowing downloads of pre-built binaries
 | 
			
		||||
(@pxref{Substitutes}).
 | 
			
		||||
 | 
			
		||||
@item --rounds=@var{n}
 | 
			
		||||
Build each derivation @var{n} times in a row, and raise an error if
 | 
			
		||||
consecutive build results are not bit-for-bit identical.
 | 
			
		||||
 | 
			
		||||
This is a useful way to detect non-deterministic builds processes.
 | 
			
		||||
Non-deterministic build processes are a problem because they make it
 | 
			
		||||
practically impossible for users to @emph{verify} whether third-party
 | 
			
		||||
binaries are genuine.  @xref{Invoking guix challenge}, for more.
 | 
			
		||||
 | 
			
		||||
Note that, currently, the differing build results are not kept around,
 | 
			
		||||
so you will have to manually investigate in case of an error---e.g., by
 | 
			
		||||
stashing one of the build results with @code{guix archive --export},
 | 
			
		||||
then rebuilding, and finally comparing the two results.
 | 
			
		||||
 | 
			
		||||
@item --no-build-hook
 | 
			
		||||
Do not attempt to offload builds @i{via} the daemon's ``build hook''
 | 
			
		||||
(@pxref{Daemon Offload Setup}).  That is, always build things locally
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,6 +170,8 @@ options handled by 'set-build-options-from-command-line', and listed in
 | 
			
		|||
      --timeout=SECONDS  mark the build as failed after SECONDS of activity"))
 | 
			
		||||
  (display (_ "
 | 
			
		||||
      --verbosity=LEVEL  use the given verbosity LEVEL"))
 | 
			
		||||
  (display (_ "
 | 
			
		||||
      --rounds=N         build N times in a row to detect non-determinism"))
 | 
			
		||||
  (display (_ "
 | 
			
		||||
  -c, --cores=N          allow the use of up to N CPU cores for the build"))
 | 
			
		||||
  (display (_ "
 | 
			
		||||
| 
						 | 
				
			
			@ -181,6 +183,7 @@ options handled by 'set-build-options-from-command-line', and listed in
 | 
			
		|||
  ;; TODO: Add more options.
 | 
			
		||||
  (set-build-options store
 | 
			
		||||
                     #:keep-failed? (assoc-ref opts 'keep-failed?)
 | 
			
		||||
                     #:rounds (assoc-ref opts 'rounds)
 | 
			
		||||
                     #:build-cores (or (assoc-ref opts 'cores) 0)
 | 
			
		||||
                     #:max-build-jobs (or (assoc-ref opts 'max-jobs) 1)
 | 
			
		||||
                     #:fallback? (assoc-ref opts 'fallback?)
 | 
			
		||||
| 
						 | 
				
			
			@ -210,6 +213,12 @@ options handled by 'set-build-options-from-command-line', and listed in
 | 
			
		|||
                  (apply values
 | 
			
		||||
                         (alist-cons 'keep-failed? #t result)
 | 
			
		||||
                         rest)))
 | 
			
		||||
        (option '("rounds") #t #f
 | 
			
		||||
                (lambda (opt name arg result . rest)
 | 
			
		||||
                  (apply values
 | 
			
		||||
                         (alist-cons 'rounds (string->number* arg)
 | 
			
		||||
                                     result)
 | 
			
		||||
                         rest)))
 | 
			
		||||
        (option '("fallback") #f #f
 | 
			
		||||
                (lambda (opt name arg result . rest)
 | 
			
		||||
                  (apply values
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue