Make Clean: Usman's Law

[article]
Summary:

Usman's Law (named after a smart coworker of mine who spent months working with customer Makefiles). make clean is intended to take you back to a state where everything will be rebuilt from scratch.   Often times it doesn't. Here's why.

Usman's Law (named after a smart coworker of mine who spent months working with customer Makefiles).  make clean is intended to take you back to a state where everything will be rebuilt from scratch.   Often times it doesn't. Here's why.

The Human Factor

Here's the clean rule from the OpenSSL Makefile:

clean:

~    rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff $(EXE)

Notice how it's a long list of, clearly human maintained, things that need to be deleted to get back to a clean state.  Human maintained means human error.  Suppose someone adds a rule that creates a temporary file with a fixed name.  That temporary file needs adding to the clean rule; mostly likely it won't be.

Usman's Law strikes.
<size=12pt>

Poor Naming

Here's a snippet found in many automatically generated Makefiles:

mostlyclean::

~    rm -f *.o

clean:: mostlyclean

~    -$(LIBTOOL) --mode=clean rm -f $(program) $(programs)

~    rm -f $(library).a squeeze *.bad *.dvi *.lj

extraclean::

~    rm -f *.aux *.bak *.bbl *.blg *.dvi *.log *.pl *.tfm *.vf *.vpl

~    rm -f *.*pk *.*gf *.mpx *.i *.s *~ *.orig  *.rej *\#*

~    rm -f CONTENTS.tex a.out core mfput.* texput.* mpout.*

Here there are three sorts of clean which appear to have different degrees of cleanliness: mostlyclean, clean and extraclean.

mostlyclean just deletes the object files compiled from source.

~ clean does that plus the generated library and a few other

files.   You'd think that extraclean would delete more than the

other two, but it actually deletes a different set of files.

You can't tell from the naming what does what.  And I've seen others with reallyclean, veryclean, deepclean and even partiallyclean!

Usman's Law strikes.

<size=12pt>Silent Failure

Here's another Makefile snippet that works some of the time:

clean:

~    @-rm *.o &> /dev/null

The @ means that the command isn't echoed.  The - means that any error return is ignored and all output is redirected,

with &>, to /dev/null making it invisible.   Since

there's no -f on the rm command a failure (say a permissions problem) will be totally unnoticed.

Usman's Law strikes.
<size=12pt>
Recursive Clean

Most Makefiles are recursive and make clean has to be recursive too, so you see the pattern:

SUBDIRS := foo bar baz

CLEAN_SUBDIRS := $(addprefix clean_,$(SUBDIRS))

clean: $(CLEAN_SUBDIRS)

$(CLEAN_SUBDIRS):

    @make -C $(subst clean_,,$@) clean

The problem with this is that it means that make clean has to be maintained throughout the code hierarchy leading to more opportunity for error.

Usman's Law strikes.

<size=12pt>The only way to win is not to play

Because of the pitfalls of make clean the best way is not to

have a make clean .   The most reliable method is as follows:

    1. The project Makefile must writes output to a sub-directory of the directory it is in.
    2. To make clean you go up one directory and delete the entire hierarchy.

 

  1. Then to make you create a new directory, check out the sources, enter the directory and run make.

About the author

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!