This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] GNU_AR_DETERMINISTIC env var, --enable-deterministic-archives
- From: Roland McGrath <mcgrathr at google dot com>
- To: binutils at sourceware dot org
- Date: Tue, 06 Dec 2011 13:27:42 -0800
- Subject: [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?
Thanks,
Roland
2011-12-06 Roland McGrath <mcgrathr@google.com>
* configure.in (--enable-deterministic-archives): Grok new
argument. Set DEFAULT_AR_DETERMINISTIC to 1 or 0 accordingly.
* configure: Regenerated.
* config.in: 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/configure.in b/binutils/configure.in
index 965d66c..da56b2d 100644
--- a/binutils/configure.in
+++ b/binutils/configure.in
@@ -28,6 +28,18 @@ AC_ARG_ENABLE(targets,
*) enable_targets=$enableval ;;
esac])dnl
+AC_ARG_ENABLE(deterministic-archives,
+[AS_HELP_STRING([--enable-deterministic-archives],
+ [ar and ranlib default to -D behavior])], [
+if test "${enableval}" = no; then
+ default_ar_deterministic=0
+else
+ default_ar_deterministic=1
+fi], [default_ar_deterministic=0])
+
+AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, $default_ar_deterministic,
+ [Should ar and ranlib use -D behavior by default?])
+
AM_BINUTILS_WARNINGS
AC_CONFIG_HEADERS(config.h:config.in)
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
+@kindex GNU_AR_DETERMINISTIC
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
+@kindex GNU_AR_DETERMINISTIC
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