How to properly clean in a Makefile?
For small C/C++ 开发者_运维知识库projects I am used to write my clean target as follow:
clean:
$(RM) *.o *~
For slightly bigger projects, when sources are dispatched in subdirectories, say src1
and src2
, I would write
clean:
$(RM) src1/*.o src1/*~ src2/*.o src2/*~
With even more subdirectories, it quickly becomes messy… So I realized I could use the find
command like this:
clean:
find . -name "*.o" -exec $(RM) {} \;
find . -name "*~" -exec $(RM) {} \;
However I saw that people often use find
in conjunction with xargs
instead of using -exec
and I wonder why since it seems to work fine…
What do you use and why?
I know that for big projects, or for better compatibility, I should probably use cmake or autotools but I like the simplicity of a Makefile for small projects.
The version of 'find' I'm used to (GNU find) also supports a '-delete' flag. I might do something like:
clean:
find . -name '*.o' -delete
because it's effective, simple and clean.
If I have multiple patterns to delete, I normally repeat the command:
clean:
rm -f a.out
find . -name '*.o' -delete
find . -name '*~' -delete
Because exec
creates one sub-process per file being deleted. xargs
, on the other hand, batches them up.
It's effectively the difference between:
rm src1/a.o
rm src1/b.o
rm src2/c.o
and:
rm src1/a.o src1/b.o src2/c.o
It's probably not going to matter that much unless you have a lot of files but it's worth knowing for that use case.
But I don't use either of those methods. I make each directory responsible for building itself (and it's subordinate directories), by having a Makefile in there. Then, from the top level make, I have something like:
all:
for i in module1 module2 \
do \
cd $i \
$(MAKE) all \
cd .. \
done
Same deal for the clean
target. I don't assume that cleaning is the same action for every single subdirectory.
By doing that, the relevant actions are localised. If I have a directory where .o
files are actually third party objects for me to link with (so I don't have the source), I make sure that clean
won't delete them in that relevant makefile. The solution you have would hose them, causing much angst and gnashing of teeth :-)
精彩评论