diff --git a/configure.ac b/configure.ac index 0b7b403..9dce607 100644 --- a/configure.ac +++ b/configure.ac @@ -542,6 +542,18 @@ AC_ARG_ENABLE(gtk-deprecation-warnings, [Show Gtk+/Gdk deprecation warnings for Gtk+ >= 3.0])], [ac_enable_gtk_deprecation_warnings="${enableval}"],[]) +AC_ARG_ENABLE(deterministic-build, +[AS_HELP_STRING([--enable-deterministic-build], + [Make the build deterministic by omitting host names, + time stamps, etc. from the output.])]) +if test "x${enableval}" = xno ; then + AC_DEFINE(DETERMINISTIC_BUILD, false, + [Set this to true to make dumping deterministic.]) +else + AC_DEFINE(DETERMINISTIC_BUILD, true, + [Set this to true to make dumping deterministic.]) +fi + dnl This used to use changequote, but, apart from 'changequote is evil' dnl per the autoconf manual, we can speed up autoconf somewhat by quoting dnl the great gob of text. Thus it's not processed for possible expansion. diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi index e620da0..1b7dcfa 100644 --- a/doc/lispref/internals.texi +++ b/doc/lispref/internals.texi @@ -64,6 +64,14 @@ Building Emacs and are not able to implement dumping, then Emacs must load @file{loadup.el} each time it starts. address@hidden deterministic build address@hidden @option{--enable-deterministic-build} option to @command{configure} + By default the dumped @file{emacs} executable contains details such +as the build time and host name. Use the address@hidden option of @command{configure} to +suppress these details, so that building and installing Emacs twice +from the same sources should result in identical copies of Emacs. + @cindex @file{site-load.el} You can specify additional files to preload by writing a library named @file{site-load.el} that loads them. You may need to rebuild Emacs diff --git a/doc/lispref/intro.texi b/doc/lispref/intro.texi index 865c698..24a7131 100644 --- a/doc/lispref/intro.texi +++ b/doc/lispref/intro.texi @@ -491,19 +491,6 @@ Version Info giving a prefix argument makes @var{here} address@hidden @end deffn address@hidden emacs-build-time -The value of this variable indicates the time at which Emacs was -built. It is a list of four integers, like the value of address@hidden (@pxref{Time of Day}). - address@hidden address@hidden -emacs-build-time - @result{} (20614 63694 515336 438000) address@hidden group address@hidden example address@hidden defvar - @defvar emacs-version The value of this variable is the version of Emacs being run. It is a string such as @code{"23.1.1"}. The last number in this string is not diff --git a/etc/NEWS b/etc/NEWS index 20a1232..e0ddc79 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -25,6 +25,14 @@ otherwise leave it unmarked. * Installation Changes in Emacs 25.2 +** New configure option ‘--enable-deterministic-build’ attempts to +build an Emacs that is reproducible; that is, if you build and +install Emacs twice, the second installation is a copy of the first. +Deterministic builds omit the build date from the output of the +emacs-version and erc-cmd-SV functions, and the leave the following +variables nil: emacs-build-system, emacs-build-time, +erc-emacs-build-time. + ** 'configure' detects the kqueue file notification library on *BSD and Mac OS X machines. diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el index d8af692..7c7edd1 100644 --- a/lisp/erc/erc-compat.el +++ b/lisp/erc/erc-compat.el @@ -54,10 +54,10 @@ erc-set-write-file-functions (set (make-local-variable 'write-file-functions) new-val)) (defvar erc-emacs-build-time - (if (stringp emacs-build-time) + (if (or (stringp emacs-build-time) (not emacs-build-time)) emacs-build-time (format-time-string "%Y-%m-%d" emacs-build-time)) - "Time at which Emacs was dumped out.") + "Time at which Emacs was dumped out, or nil if not available.") ;; Emacs 21 and XEmacs do not have user-emacs-directory, but XEmacs ;; has user-init-directory. @@ -164,4 +164,3 @@ erc-subseq ;; indent-tabs-mode: t ;; tab-width: 8 ;; End: - diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index cd8e427..3ff919a 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3574,7 +3574,7 @@ gtk-version-string (defun erc-cmd-SV () "Say the current ERC and Emacs version into channel." - (erc-send-message (format "I'm using ERC with %s %s (%s%s) of %s." + (erc-send-message (format "I'm using ERC with %s %s (%s%s)%s." (if (featurep 'xemacs) "XEmacs" "GNU Emacs") emacs-version system-configuration @@ -3595,7 +3595,9 @@ erc-cmd-SV x-toolkit-scroll-bars))) "") (if (featurep 'multi-tty) ", multi-tty" "")) - erc-emacs-build-time)) + (if erc-emacs-build-time + (concat " of " erc-emacs-build-time) + ""))) t) (defun erc-cmd-SM () diff --git a/lisp/version.el b/lisp/version.el index 43103fd..a6686e1 100644 --- a/lisp/version.el +++ b/lisp/version.el @@ -38,13 +38,12 @@ emacs-minor-version "Minor version number of this version of Emacs. This variable first existed in version 19.23.") -(defconst emacs-build-time (current-time) - "Time at which Emacs was dumped out.") +(defconst emacs-build-time (if (not deterministic-build) (current-time)) + "Time at which Emacs was dumped out, or nil if not available.") -;; I think this should be obsoleted/removed. It's just one more meaningless -;; difference between different builds. It's usually not even an fqdn. -(defconst emacs-build-system (system-name) - "Name of the system on which Emacs was built.") +(defconst emacs-build-system + (if (not deterministic-build) (system-name)) + "Name of the system on which Emacs was built, or nil if not available.") (defvar motif-version-string) (defvar gtk-version-string) @@ -58,9 +57,7 @@ emacs-version to the system configuration; look at `system-configuration' instead." (interactive "P") (let ((version-string - (format (if (not (called-interactively-p 'interactive)) - "GNU Emacs %s (%s%s%s%s)\n of %s" - "GNU Emacs %s (%s%s%s%s) of %s") + (format "GNU Emacs %s (%s%s%s%s)%s" emacs-version system-configuration (cond ((featurep 'motif) @@ -79,7 +76,14 @@ emacs-version (format ", %s scroll bars" (capitalize (symbol-name x-toolkit-scroll-bars))) "") - (format-time-string "%Y-%m-%d" emacs-build-time)))) + (if emacs-build-time + (format-time-string (concat + (if (called-interactively-p + 'interactive) + "" "\n") + " of %Y-%m-%d") + emacs-build-time) + "")))) (if here (insert version-string) (if (called-interactively-p 'interactive) diff --git a/src/emacs.c b/src/emacs.c index 2e9f950..e7c153f 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2566,6 +2566,13 @@ libraries; only those already known by Emacs will be loaded. */); Vdynamic_library_alist = Qnil; Fput (intern_c_string ("dynamic-library-alist"), Qrisky_local_variable, Qt); + DEFVAR_BOOL ("deterministic-build", Vdeterministic_build, + doc: /* If non-nil, make builds deterministic by omitting +host names, time stamps, etc. from the output. */); + if (DETERMINISTIC_BUILD) + Vdeterministic_build = true; + XSYMBOL (intern_c_string ("deterministic-build"))->constant = 1; + #ifdef WINDOWSNT Vlibrary_cache = Qnil; staticpro (&Vlibrary_cache); diff --git a/src/sysdep.c b/src/sysdep.c index 1af323e..8147afe 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -1399,6 +1399,12 @@ setup_pty (int fd) void init_system_name (void) { + if (DETERMINISTIC_BUILD && (might_dump || ! NILP (Vpurify_flag))) + { + /* Set system-name to nil so that the build is deterministic. */ + Vsystem_name = Qnil; + return; + } char *hostname_alloc = NULL; char *hostname; #ifndef HAVE_GETHOSTNAME