bug-make
[Top][All Lists]
Advanced

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

[bug #30340] dependency handling


From: anonymous
Subject: [bug #30340] dependency handling
Date: Sun, 04 Jul 2010 04:12:39 +0000
User-agent: Opera/9.80 (X11; Linux i686; U; en) Presto/2.5.24 Version/10.52

URL:
  <http://savannah.gnu.org/bugs/?30340>

                 Summary: dependency handling
                 Project: make
            Submitted by: None
            Submitted on: Sun 04 Jul 2010 04:12:38 AM UTC
                Severity: 3 - Normal
              Item Group: Documentation
                  Status: None
                 Privacy: Public
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
       Component Version: 3.81
        Operating System: Any
           Fixed Release: None
           Triage Status: None

    _______________________________________________________

Details:

In section 4.14, GNU make's info manual recommends the following construct to
handle header files dependencies.

%.d: %.c
        @set -e; rm -f $@; \
        $(CC) -M $(CPPFLAGS) $< > address@hidden; \
        sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < address@hidden > $@; \
        rm -f address@hidden

sources = foo.c bar.c
include $(sources:.c=.d)

Indeed, this works, but I believe there are better solutions, both from an
efficiency point of view, and from a pedagogic point of view. Let me give a
couple of examples of what is less than ideal with this solution, and then
show an alternative proposal.

1) .d files are generated and included even when they are not needed. When
the .o file hasn't been created yet, knowing its .c source file is enough, and
information on header file dependencies, while harmless, is of no practical
use.

2) The rule for the %d: %c command is relatively complex, involving a sed
expression that is likely to be cryptic for people in the process of learning
the various GNU tools.

3) Generating the .d file and the .o file in completely independent steps is
relatively inefficient, because it makes rather poor use of the file system's
cache, and because it creates more processes than strictly necessary.

Instead I propose this:

%.o %.d: %.c
        $(COMPILE.c) -MD -o $*.o $<

sources = foo.c bar.c
objects = $(sources:.c=.o)
include $(patsubst %.o,%.d,$(wildcard $(objects)))


The advantages are:

Only the .d files matching existing objects are included. As these are the
only .d files actually needed, this is more efficient, and addresses point 1.

There is no need to compute the dependencies of the .d file itself. As they
are identical to the dependencies of the .o file, the .d file should be
recreated every time the .o file is. The proposed rule takes care of that.
This gets us rid of most of the complexity of the original rule for making the
.d files, and in particular the sed command, addressing point 2.

Fewer process creations are needed. Instead of 4 per source file (cc for the
.o file, cc for the .d file, sed, and rm), we have 1, addressing part of the
efficiency concerns expressed in point 3.

The disc/file system is used more efficiently. The source file is only read
once, causing much fewer disc accesses than the method proposed in GNU make's
info manual. As compilation tends to be I/O bound, this can be significant.
This also addresses the efficiency concerns expressed in point 3.

The only downside I see with this method is that when only the .d file is
missing when the .o the other exists and is up to date, will we recreate both
anyway, which is slightly inefficient. However, I don't consider this a big
issue, because this will only happen in rare situations. As the two file are
generated together, in normal use it shouldn't happen often that only one of
them is present. Besides, even if the .d is missing, the regeneration of the
.o will not be that expensive, given that both files are generated with a
single invocation of the compiler.

I don't know any compiler that supports -M and doesn't support -MD, but if
there is one, the rule can be very simply adapted:

%.o %.d: %.c
        $(COMPILE.c) -o $*.o $<
        $(COMPILE.c) -M -o $*.d $<

This still creates fewer processes than the method proposed in GNU make's
manual, and is still easier to understand. The two accesses to the source file
are immediately after each other, and likely to play well with the file
system's cache.

If you see problems with the method I suggest, I would be delighted to get
your feedback on this topic. If you agree that the method I propose would be
an improvement to the one currently described in the info manual, I will try
to write a replacement for section 4.14, unless of course, you prefer to do
that yourself.




    _______________________________________________________

Reply to this item at:

  <http://savannah.gnu.org/bugs/?30340>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.gnu.org/




reply via email to

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