At Cesanta, we use Makefiles to build our firmwares, libraries, and perform other things. But the more I use make , the less I like it. I want my incremental builds to be reliable, and I want to be able to reuse my Makefiles as needed. make can't provide that, and builds just kinda-sorta work most of the time.
Consider: we have a library mylib , which is a separate project on its own, and it has its own Makefile . The end product is a file mylib.a . So, among others, there is a rule which looks like:
mylib.a: src1.c src2.c src3.c .... some recipe to build mylib.a ....
Now, we have a project app with a separate Makefile, and we want to use mylib.a there, and of course we want it to be up to date. How would we do that?
We can't just include ../mylib/Makefile , because it has a lot of irrelevant stuff such as unit tests, etc, and we don't want variable names to clash.
We could add a target wich a simple recipe which just invokes make properly:
mylib.a: $(MAKE) -C ../mylib mylib.a
The obvious problem here is that there are no prerequisites, so make won't be invoked when we change some mylib 's sources. That's not acceptable.
We could factor out prerequisites in a third Makefile , specifically and carefully designed for inclusion, and include it in both mylib/Makefile and app/Makefile , and we'll make sure all the paths are correct, etc, etc. But this is really too much work here, in the app's Makefile: we want to just use the lib. We don't want to care about how to build it.
My next idea was to make mylib.a target phony, so that make will get invoked every time (and will be a no-op if no prerequisites changed), but is's also bad since a target which depends on a phony target will be rebuilt every time. We don't want the app target to always get rebuilt.
Ok, something that would really work is to add the make invocation to the recipe for every target which depends on mylib , like:
app: prereq1 prereq2 ... $(MAKE) -C ../mylib mylib.a ..... the rest of actual recipe for app .....
But this is just ugly. We actually end up specifying prerequisites in a recipe. Still, this is the easiest way that I'm aware of.