help-make
[Top][All Lists]
Advanced

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

Re: non-recursive build question


From: Noel Yap
Subject: Re: non-recursive build question
Date: Wed, 28 Apr 2004 12:00:44 -0400
User-agent: Mozilla Thunderbird 0.5 (Windows/20040212)

It really sounds like order rules (available only in GNU make 3.80 at this 
time) will help here.  Have you investigated using these?

foo.so: $(OBJECT_FILES)

foo.exp: $(OBJECT_FILES)

bar: | foo.so

baz: | foo.exp

If you want to cut down on the foo.exp creation, it may be possible to do 
something like:

s0.e: s0.o
        # create symbol list for s0.o

foo.exp: $(E_FILES)
        # aggregate .e contents into foo.exp

HTH,
Noel

sandy currier wrote:

Paul D. Smith wrote:

%% Sandy Currier <address@hidden> writes:

  sc> Actually, though the primary point is to not have targets that
  sc> depend on foo.exp rebuild when it is not physically changed, the
  sc> secondary point IS to touch the foo.exp target.  By touching it
  sc> when it is rebuilt, then the next time that make is run, if none
  sc> of the $(ALL_FOO_OFILES) have changed, then the neither foo.exp or
  sc> foo.so is rebuilt.

Well, you can't have it both ways: either the target is updated, in
which case things that depend on the target are updated, or it's not
updated, in which case it will be re-assessed in relation to its
prerequisites the next time make is run.


As mentioned, scons supports this, allowing the user the ability
to intrinsically tell the build that something is up-to-date
irrespective of the date/MD5 check.  (Note: this question stems
from a bake-off we are having between gmake and scons as to see
which tool can build 10Gbytes of code better under a single DAG.)

In fact, there are several (many?) other places in the build where the
same feature is required.  So far, in those places we worked around
the problem in gmake by using the "include <fake-dep-file>" trick (which
is somewhat akin to http://make.paulandlesley.org/autodep.html).  This
is where as a side effect of creating and including a generated makefile
we create the actual file of interest.  Whenever the file of interest is
missing or needs to be re-created from 'non-derived' files, gmake builds the
file then reloads the DAG since an included makefile has changed.
This is cool, but it only really works in these cases since
all the generated files are derived from non-derived files (and the
DAG can be 'thrown out' and re-created without much cost). This step occurs
first in the build, and everything is ok.  Our current gmake prototype
does this with perhaps a 100 or so files, and the real build will handle many
more of this type of file.

This trick cannot be used here with the shared library example since the
need to specify-this-derived-object-is-old-because-it-has-not-changed
occurs after much building and is based itself on derived files, not from
non-derived files.  Throwing out the DAG at this point in the build
would be similar to breaking the DAG into two pieces, a pass-1 piece and
a pass-2 piece.  And I am not sure it will work in this case anyway.

Well, you could actually get both but you need an extra file; you can
use this "sentinel" file to manage controlling the expensive part and
then the only part that is run multiple times is the cheap part of
comparing the results.


For example:

    foo.so: $(ALL_FOO_OFILES) foo.exp
            create_sharedlib.pl ...

    foo.exp: .foo.exp.new
            if [ "x`stat.pl address@hidden" != "x`stat.pl $<`" ]; then \
              cp $< $@; \
            fi

    .foo.exp.new: $(ALL_FOO_OFILES)
            create_export_list.pl $@ $^

Now create_export_list.pl will only be invoked when some OFILE actually
changes, and foo.exp will only be updated when the export list has
changed, but you don't pay the cost of updating the export list every
time you only pay the cost of the comparison.


The above breaks the requirement that foo.so be fully up-to-date when the
foo.exp target completes.  Additionally, for -jN, the above has the
property that foo.exp can complete while foo.so still does not exist or
worse, is still actively being built.  Then, targets that only explicitly
depends on foo.exp:

bar.so: foo.exp
    link $@ foo.so

unittest_foo.exe : foo.exp
    link $@ foo.so

will fail without some type of explicit or implicit dependency on foo.so,
which is what we are trying to avoid on purpose since we only want to
relink the bar.so shared library if the foo.exp file has changed, NOT if
the foo.so file has changed.  Other targets to execute tests and things do
need to depend directly on foo.so:

run_unittest_foo.ts: unittest_foo.exe foo.so
    unittest_foo.exe ...
    touch $@

...and should re-execute whenever foo.so changes.  [The above example
shows that the unittest for foo only needs to relink when foo.exp changes,
but that the test needs to run whenever foo.so changes.  The former is
less frequent then the latter, and time saving estimates, on average,
total a couple hours per day per developer since we are doing continuous
building of the codeline.]

I don't know, I have tried to solve it several different ways, but keep
coming back to the fundemental requirement that the target needs to have
the mod time set (touched) AND have gmake to ignore it (-o it).  That is
why I asked about a $(old ...) function - which doesn't change the DAG, it
just tells the look-up of '...' that it is up-to-date.

thanks!
-sandy







reply via email to

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