I prefer to use memoize.py whenever possible instead of Make. I think it is much simpler to let it manage the dependencies rather than having to code them explicitly. Almost every other make system I have ever used eventually devolves to the point where 'make clean; make' is the only reliable way to use it. https://github.com/kgaughan/memoize.py
tup[0] is a another implementation of the same idea, that does work on Windows (unlike memoize) and has a few other goodies.
I would also recommend having a look at djb's "redo", implemented by apenwarr - it is much easier than to do right than a makefile, but unfortunately you still have to get the dependencies right yourself (which tup and memoize do for you automatically).