When linux needs ‘make clean’

S. Gilles

2017-07-13

Here's a perfect example of a time when a ‘make clean’ is needed
during a git bisect:

On one of my machines, linux-mainline partially broke the other day
because a new driver (CONFIG_DRM_STM) was marked as default ‘Y’,
and having that driver compiled in breaks fbdev on my machine, which
does not have an STM panel. Once drm-stm.o is compiled (from a bad
commit), it will not be deleted from the working directory by
checking out an older, good commit.

So suppose we're bisecting, and we're on commit bbb (the one that
introduces STM), with a config that includes it. We build the kernel,
test it, and mark bbb as bad.  Then suppose that git chooses commit
aaa: the direct parent of bbb.  The only change that will be made
in the source tree is to delete a few C files and remove a few
prerequisites in a Makefile. From make's point of view, no work
needs to be done: deleting a few source files preserves “all object
files are still older than their source files”.  So the next bisection
step, for aaa, will be identical to bbb, we'll
get a false positive.

(I think there are a bit more layers in practice due to built-in.o,
and I think this might also depend on subsystem-specific rules, but
the basic idea is the same.)

After thinking about it for a bit, this is just a time-reversed
version of the following well-known problem: if a depends on b which
depends on c, deleting c (and removing references to it from the
Makefile) will not necessarily cause a rebuild of a. It might not
even cause a rebuild of b.

The easiest solution I know of is to make whatever a (and b) depend
on Makefile itself. Since Makefile has to be updated to forget c,
everything will be fine. But if everything depends on Makefile,
such a change would force a full rebuild, when perhaps d through z
don't need to be updated. In the case of linux, where the Makefiles
change pretty frequently, this could be a huge problem.

I guess, unfortunately, the solution is that sometimes ‘make clean’
is necessary, especially right before skipping through commits that
add or remove features (especially backwards).