[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patch] sort 'find' output to enable deterministic builds.

From: Chris Demetriou
Subject: Re: [patch] sort 'find' output to enable deterministic builds.
Date: Tue, 16 Mar 2010 00:28:12 -0700

Hi Ralf,

On Mon, Mar 15, 2010 at 23:37, Ralf Wildenhues <address@hidden> wrote:
> libtool also uses 'ar' in a number of places and cases, most
> prominently, but not limited to, the static linking scenario.
> Do you have measures in place to use 'D' there too?

Yes.  At least in all the places I've noticed (or that are relevant
for a Linux / ELF build), libtool actually uses $AR.  Likewise with

If you want a repeatable build that avoids ar timestamps, you need:
  AR=... wrapper script that adds 'D' and strips 'u' from ar's first arg ...
  RANLIB=/bin/true or wrapper script that invokes /bin/true.

(i didn't grep through all of the libtool code, but AFAICT at least uses $AR and $RANLIB in preference to hard-coding ar and
ranlib ... which makes sense, since, for example, it's gotta be
cross-compilation friendly.)

> IIRC some (non-GNU) compilers (or the assemblers they call, I don't
> recall) also add time stamps to generated objects.  Are they relevant to
> you?  I'm not sure whether one can turn stamps off everywhere; have you
> looked into normalizing output like in GCC's contrib/compare-debug?

In my experience, it's the object formats.  E.g., COFF objects
(including ECOFF and PE) include a timestamp.  Looks like BFD puts in
0 for that in most cases, but e.g. the bfd/peXXigen.c code looks like
it *will* generate a timestamp.  Those object file formats are not
relevant to me, though i've seen environments before were they're
overridden.  (I once wrote a small set of tools to do a
timestamp-insensitive compare for windows builds.  I've thankfully
been *mostly* COFF-free for the past 10+ years.  8-)

(BTW, my purpose isn't to be able to compare output files so much as
create bit-identical output files.  There are several reasons for
this, but in summary, comparison isn't quite good enough.  In order to
do this, you've gotta do a bunch of other things, e.g., build with the
same paths, use -frandom-seed appropriately if building some C++ code,

> Then, it would be nice to be able to confirm that we produce stable
> output in cases where this is desirable; IOW, have testsuite exposure.
> Can you describe your setup in a bit more detail?  (You could also
> provide a test case, but that will probably require copyright papers
> then first.)

Actually,  my employer has a blanket assignment AFAIU, so that's not a problem.

My test case is a GCC build, built on three different host system
types (Ubuntu Dapper, Ubuntu Hardy, and Ubuntu pre-Lucid).  libstdc++
is big enough and the filesystems different enough w.r.t. 'find'
behavior that I get different orders on different systems.  Not an
easily-rolled-up test case.  8-)

The problem with writing a test case is that find's traversal order is
not guaranteed.  It depends on a whole bunch of things, but most
especially the implementation of readdir (or whatever similar
interface it uses to read dir entries -- I haven't looked inside of
GNU find ... maybe ever 8-), which often depends on the underlying
file system.

e.g., on my (Hardy) workstation:

# /tmp is on the ext3 root file system:
address@hidden v14]$ mkdir /tmp/a
address@hidden v14]$ touch /tmp/a/a.o
address@hidden v14]$ touch /tmp/a/b.o
address@hidden v14]$ mkdir /tmp/b
address@hidden v14]$ touch /tmp/b/b.o
address@hidden v14]$ touch /tmp/b/a.o
address@hidden v14]$ find /tmp/a
address@hidden v14]$ find /tmp/b

# ~/tmp is on NFs.
address@hidden v14]$ mkdir ~/tmp/a ~/tmp/b
address@hidden v14]$ touch ~/tmp/a/a.o
address@hidden v14]$ touch ~/tmp/a/b.o
address@hidden v14]$ touch ~/tmp/b/b.o
address@hidden v14]$ touch ~/tmp/b/a.o
address@hidden v14]$ find ~/tmp/a
address@hidden v14]$ find ~/tmp/b

(Note how in /tmp, things came out in a consistent order, and in ~/tmp
things came out in the order that they were created.)

This makes it harder to make a test case where you're *sure* that the
test is actually effective.

Probably the easiest test likely to expose the problem would be...
 * create an archive (normal or libtool, I don't know what ltmain's
func_extract_archive wants to operate on) with members b.o and a.o (in
that order)
 * convince ltmain to generate a new archive including them then
verify that the new archive has them in the order a.o and b.o.

but obviously that wouldn't actually test anything in many
circumstances (e.g., my /tmp example above).  (AFAICT it doesn't look
like libtool ever has to deal with indexless/ancient-BSD archives,
where you had to use lorder|tsort to order the archive members...
that's good because that would make the test a lot more difficult.

Unfortunately, to be honest... I don't really have a clue about how to
implement a test case like this.  I've never actually attempted to use
libtool to do anything (e.g., create archives)...

Also complicating the issue is that I really don't know think one
about libtool, e.g., how to make it do what I want in this case.
Getting a working testcase out of me is going to be ... difficult.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]