Re: source dependencies cleanup?

Paul Flinders (ptf@datasci.co.uk)
Wed, 4 Dec 1996 10:10:48 -0000


> From: Peter T. Breuer <ptb@oboe.it.uc3m.es>
>
> > anyway but I believe (after a quick perusal of the .depend files) that
> > mkdep is fast mainly because it skips stuff.
>
> Absolutely wrong (i.e. "that turns out not to be the case" :). It is
> fast per se and it is helped to be fast by the factthat it does not skip
> stuff that a cleverer but slower implementation might be able to skip.
> (gcc is such a beast). It produces a conservative overestimate of the
> semantically exact dependencies. It is purely a syntactic dependency
> chaser!

gcc is most definately not "cleverer" in this context. It is, however, correct.

The dependancies generated by mkdep for block/drivers/genhd.c are as follows

genhd.o: \
/usr/src/linux/include/linux/config.h \
/usr/src/linux/include/linux/fs.h \
/usr/src/linux/include/linux/genhd.h \
/usr/src/linux/include/linux/kernel.h \
/usr/src/linux/include/linux/major.h \
/usr/src/linux/include/linux/string.h \
/usr/src/linux/include/linux/blk.h \
/usr/src/linux/include/asm/system.h \
/usr/src/linux/include/asm/unaligned.h \
/usr/src/linux/include/asm/byteorder.h \
/usr/src/linux/include/linux/affs_hardblocks.h

The output from gcc -MD is
genhd.o: genhd.c /usr/src/linux/include/linux/config.h \
/usr/src/linux/include/linux/autoconf.h \
/usr/src/linux/include/linux/fs.h \
/usr/src/linux/include/linux/linkage.h \
/usr/src/linux/include/linux/limits.h \
/usr/src/linux/include/linux/wait.h \
/usr/src/linux/include/linux/types.h \
/usr/src/linux/include/linux/posix_types.h \
/usr/src/linux/include/asm/posix_types.h \
/usr/src/linux/include/asm/types.h /usr/src/linux/include/linux/vfs.h \
/usr/src/linux/include/asm/statfs.h \
/usr/src/linux/include/linux/net.h \
/usr/src/linux/include/linux/socket.h \
/usr/src/linux/include/asm/socket.h \
/usr/src/linux/include/asm/sockios.h \
/usr/src/linux/include/linux/sockios.h \
/usr/src/linux/include/linux/uio.h \
/usr/src/linux/include/linux/kdev_t.h \
/usr/src/linux/include/linux/ioctl.h \
/usr/src/linux/include/asm/ioctl.h \
/usr/src/linux/include/asm/semaphore.h \
/usr/src/linux/include/asm/bitops.h \
/usr/src/linux/include/linux/pipe_fs_i.h \
/usr/src/linux/include/linux/minix_fs_i.h \
/usr/src/linux/include/linux/ext_fs_i.h \
/usr/src/linux/include/linux/ext2_fs_i.h \
/usr/src/linux/include/linux/hpfs_fs_i.h \
/usr/src/linux/include/linux/msdos_fs_i.h \
/usr/src/linux/include/linux/umsdos_fs_i.h \
/usr/src/linux/include/linux/iso_fs_i.h \
/usr/src/linux/include/linux/nfs_fs_i.h \
/usr/src/linux/include/linux/nfs.h \
/usr/src/linux/include/linux/xia_fs_i.h \
/usr/src/linux/include/linux/sysv_fs_i.h \
/usr/src/linux/include/linux/affs_fs_i.h \
/usr/src/linux/include/linux/ufs_fs_i.h \
/usr/src/linux/include/linux/ufs_fs.h \
/usr/src/linux/include/linux/kernel.h \
/usr/lib/gcc-lib/i486-linux/2.7.2/include/stdarg.h \
/usr/src/linux/include/linux/time.h \
/usr/src/linux/include/linux/stat.h /usr/src/linux/include/asm/stat.h \
/usr/src/linux/include/linux/quota.h \
/usr/src/linux/include/linux/errno.h \
/usr/src/linux/include/asm/errno.h \
/usr/src/linux/include/linux/mount.h \
/usr/src/linux/include/linux/fcntl.h \
/usr/src/linux/include/asm/fcntl.h \
/usr/src/linux/include/linux/minix_fs_sb.h \
/usr/src/linux/include/linux/ext_fs_sb.h \
/usr/src/linux/include/linux/ext2_fs_sb.h \
/usr/src/linux/include/linux/ext2_fs.h \
/usr/src/linux/include/linux/hpfs_fs_sb.h \
/usr/src/linux/include/linux/msdos_fs_sb.h \
/usr/src/linux/include/linux/iso_fs_sb.h \
/usr/src/linux/include/linux/nfs_fs_sb.h \
/usr/src/linux/include/linux/rpcsock.h \
/usr/src/linux/include/linux/xia_fs_sb.h \
/usr/src/linux/include/linux/sysv_fs_sb.h \
/usr/src/linux/include/linux/affs_fs_sb.h \
/usr/src/linux/include/linux/ufs_fs_sb.h \
/usr/src/linux/include/linux/minix_fs.h \
/usr/src/linux/include/linux/genhd.h \
/usr/src/linux/include/linux/major.h \
/usr/src/linux/include/linux/string.h \
/usr/src/linux/include/asm/string.h \
/usr/src/linux/include/asm/system.h \
/usr/src/linux/include/asm/segment.h \
/usr/src/linux/include/asm/unaligned.h

genhd.c uses the MKDEV macro, defined in /usr/src/linux/include/linux/kdev_t.h
which isn't listed in the mkdep output but is in the -MD output.

If I change the definition of MKDEV and re-build then genhd.c will not
be re-compiled, this is just plain wrong and I really can't reconcile this with
your statement that mkdep "produces a conservative overestimate of the
semantically exact dependencies".

I think this example supports my earlier statement that mkdep is fast
because it does half a job.

> That's wrong. Linus updates the alpha stuff practically every release,
> and I am not going to recompile _that_! Then there is the m68k stuff,
> the scsi stuff on a non-scsi machine, all the net drivers that I don't
> need (I only have one type of card and I use it as a versioned module)
> plus the sound that I don't use, all the isdn stuff, all the file systems
> that I don't use etc. etc. etc.
>
> > Can you suggest a concrete example of when you would touch a file
> > which you don't want to be re-compiled.
>
> see above. Pick any file not in my architecture.

I see your mis-understanding. As others have pointed out this is tangential
to a discussion on mkdep. If the *object* files are not listed as dependancies
of the kernel then the source files will not be compiled. In fact the current
"make depend" probably wastes effort by generating dependancies for object
files which are never going to be re-compiled.

> > Using -MD kives you an accurate picture of the dependancies which
> > is always up-to-date. mkdep appears to give a partial picture (it doesn't
> > on brief examination appear to output dependancies for nested files).
>
> That is incorrect.- unless there is a real bug in the mkdep code!

See my example above

> > the dependancies generated by mkdep can also become out of date
> > (as soon as you add a new header to a source file)
>
> Of course, so what?
So I won't get files re-compiled when they should be.

>
> > mkdep also ignores #if/#endif which means that I might end up
> > re-compiling a file un-necessarily because I edit a header which a
> > source file includes in *some* circumstances but not in the current
> > configuration.
>
> Yes - that is what I said. It is a conservative (i.e. "safe") over
> estimate of the semantic dependencies.

No it's not "safe", see the genhd/MKDEV example.

>
> >
> > In my experience
> > a) "make depend" is still a noticable addition to the compilation time
> > (although some of this is to do with modules which may still need
> > to be done & making sure that happens appropriately will need
> > though)
>
> Use versions.
I do (I assume that you mean MODVERSIONS)

> There is no problem with the dependency tracking unless there is a bug.
> The mkdep dependencies are already over-robust.
No, see earlier discussion

> I am afraid you cannot beat the math above. You may wish to suggest
> alternative figures? Your method should produce at least a 30%
> slowdown according to what I suggested as reasonable. I tried to err on
> your side - though maybe 0.7 should be 0.75.

Your argument rests on the assumption that using -MD will cause files
to be re-compiled when there is no need. This is not the case because
files for features which I don't need won't be compiled unless the list of
object files required to build the kernel is wrong which is nothing to do
with this discussion.

After a given update using -MD may appear to take longer because
more files are re-compiled. However this warrants closer examination...

Lets say that after some edit of a header 75% of the source files need to
be re-compiled. Unfortunately because mkdep doesn't track nested headers
make will think that 50% of the source files need to be compiled.

So, if the time for a full build is Y and the extra time for -MD is X then the
two build times are

mkdep = 0.5Y

-MD = 0.75Y + YX

You appear to win, but the new kernel with mkdep generated dependancies
doesn't work properly, so I spend some time debugging it (D) and come to the
conclusion that I need to do a make clean; make, I also become frustrated
by this (F)

therefore mkdep = 1.5Y + D + F

which is clearly worse unless X > (0.75Y + D + F). However X is very small -
in fact I can't measure it. On 10 runs of compiling genhd.c the difference between
a compilation with -MD and one without is smaller than the variation between
different compiler runs.

Regards

Paul.