This is the mail archive of the mailing list for the binutils project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] GNU_AR_DETERMINISTIC env var, --enable-deterministic-archives

ar member headers are one of the last remaining common barriers to
reproducible builds (of development packages).  Hence we have the D option.
But it is devilishly difficult to get the option override--or even AR and
RANLIB settings pointing to a wrapper script--through configure et al into
all corners of e.g. the gcc build.

Instead, this change lets the user set the environment variable
GNU_AR_DETERMINISTIC=1 to enable "deterministic mode" by default.
That's far easier to use in practice.

In most places, the only use of "ar" is on libraries for linking and there
is no benefit whatsoever to the timestamp, UID, or GID fields in these.
So --enable-deterministic-archives lets one choose the GNU_AR_DETERMINISTIC=1
mode at build time.  Users can still set GNU_AR_DETERMINISTIC=0 to reverse
the build-time default.

Since D is incompatible with u and some packages run "ar cru",
when the environment variable or build-time default sets D, we
just silently ignore u.

Ok for trunk?


2011-12-06  Roland McGrath  <>

	* (--enable-deterministic-archives): Grok new
	argument.  Set DEFAULT_AR_DETERMINISTIC to 1 or 0 accordingly.
	* configure: Regenerated.
	* Regenerated.
	* ar.c (default_deterministic): New function.
	(ranlib_main, main): Call it.
	* doc/binutils.texi (ar cmdline, ranlib): Document that.

diff --git a/binutils/ar.c b/binutils/ar.c
index 676e92c..8706d94 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -37,6 +37,7 @@
 #include "filenames.h"
 #include "binemul.h"
 #include "plugin.h"
+#include <ctype.h>
 #include <sys/stat.h>
 #ifdef __GO32___
@@ -553,6 +554,34 @@ decode_options (int argc, char **argv)
   return &argv[optind];
+/* If -D was not specified explicitly, then default it to on or off
+   depending on the environment variable GNU_AR_DETERMINISTIC, or to
+   the configured default.  */
+static void
+default_deterministic (void)
+  if (!deterministic)
+    {
+      const char *env = getenv ("GNU_AR_DETERMINISTIC");
+      if (env != NULL && env[0] != '\0')
+        {
+          if (isdigit(env[0]))
+            {
+              char *endp = NULL;
+              long int value = strtol (env, &endp, 0);
+              if (endp != NULL)
+                deterministic = value != 0;
+            }
+          else
+            deterministic = 1;
+        }
+      else
+        deterministic = DEFAULT_AR_DETERMINISTIC;
+      if (deterministic)
+        newer_only = 0;
+    }
 static void
 ranlib_main (int argc, char **argv)
@@ -590,6 +619,8 @@ ranlib_main (int argc, char **argv)
   if (show_version)
     print_version ("ranlib");
+  default_deterministic ();
   arg_index = optind;
   while (arg_index < argc)
@@ -702,6 +733,8 @@ main (int argc, char **argv)
       if (newer_only && deterministic)
 	fatal (_("`u' is not meaningful with the `D' option."));
+      default_deterministic ();
       if (postype != pos_default)
 	posname = argv[arg_index++];
diff --git a/binutils/ b/binutils/
index 965d66c..da56b2d 100644
--- a/binutils/
+++ b/binutils/
@@ -28,6 +28,18 @@ AC_ARG_ENABLE(targets,
   *)        enable_targets=$enableval ;;
+		[ar and ranlib default to -D behavior])], [
+if test "${enableval}" = no; then
+  default_ar_deterministic=0
+  default_ar_deterministic=1
+fi], [default_ar_deterministic=0])
+		   [Should ar and ranlib use -D behavior by default?])
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 3217a1a..678379b 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -418,6 +418,7 @@ using this modifier.
 @item D
 @cindex deterministic archives
 Operate in @emph{deterministic} mode.  When adding files and the archive
 index use zero for UIDs, GIDs, timestamps, and use consistent file modes
 for all files.  When this option is used, if @command{ar} is used with
@@ -425,6 +426,14 @@ identical options and identical input files, multiple runs will create
 identical output files regardless of the input files' owners, groups,
 file modes, or modification times.
+If the environment variable @code{GNU_AR_DETERMINISTIC} is set to a
+nonempty value that is not @code{0}, then this mode is enabled by default.
+In this case, the @code{u} modifier is ignored.  If that environment
+variable is absent or has an empty value and @file{binutils} was configured
+with @option{--enable-deterministic-archives}, then this mode is on by
+default.  If @code{GNU_AR_DETERMINISTIC} is set to @code{0} then this mode
+is never enabled without the @code{D} modifier.
 @item f
 Truncate names in the archive.  @sc{gnu} @command{ar} will normally permit file
 names of any length.  This will cause it to create archives which are
@@ -2386,10 +2395,18 @@ Show the version number of @command{ranlib}.
 @item -D
 @cindex deterministic archives
 Operate in @emph{deterministic} mode.  The symbol map archive member's
 header will show zero for the UID, GID, and timestamp.  When this
 option is used, multiple runs will produce identical output files.
+If the environment variable @code{GNU_AR_DETERMINISTIC} is set to a nonempty
+value that is not @code{0}, then this mode is enabled by default.  If that
+environment variable is absent or has an empty value and @file{binutils} was
+configured with @option{--enable-deterministic-archives}, then this mode is
+on by default.  If @code{GNU_AR_DETERMINISTIC} is set to @code{0} then this
+mode is never enabled without the @code{D} modifier.
 @item -t
 Update the timestamp of the symbol map of an archive.
 @end table

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]