Make is old-fashioned. Clunky. Weird. It even differentiates between the use of tabs and spaces in opaque and, frankly, stupid ways (don’t believe me? Look at page 281 of this document ).
But it’s the best tool for many jobs.
Its original job.
Yes, you read right.
Its original job was to manage compilation of C programs. Clearly, you can still use it for that purpose. But in 2018, I believe you shouldn’t. There are better alternatives.
If your project is small, fine, any tool (including make) will do. But once it starts to get serious in terms of complexity, using make will make things needlessly difficult for you.
There are more modern alternatives.
For C or C++, pick CMake, or SCons, or any of the other newer ones (originating in the 1980s counts as newer, mind you).
However, make is still supremely useful. In fact, it’s my secret weapon in all process automation endeavours.
I advocate its use on all projects I’m involved in. Not for building the sources into executables or other artefacts of whatever shape, but for building the product and infrastructure.
Being shaped similar to a shell script (but with dependency resolution), it’s a lingua franca for anyone with some familiarity with Unix-ish environments.
Anyone can add to it. Even more importantly: anyone can read it and understand what’s going on.
What’s better, it’s very easy to prototype a new approach or figure out an existing one, by typing its commands into the shell, and going from there.
To me, that’s a big part of make’s appeal for this sort of documentation: it’s all plain shell commands. No new system that you need to translate to or from. No syntax elements from the build script (well, except for targets, but that’s completely outside of the actual commands). This immediacy is what makes it so useful IMO.
I like to run my CMake/Maven/whatever build scripts from make targets.
This makes it very easy to find out how something is being used: the Makefile provides executable documentation. And we all know this is the best kind of documentation: it can’t be incomplete, out of date or open to interpretation. If something were incorrect about it, we’d know pretty much instantly.
If everybody on the team uses the make targets for handling the project, there can’t be subtly different ways of doing something. There is no risk of miscommunication, or different people performing the same tasks only almost the same.
There will be no doubt about which compiler flags are in use, or the location of various items. Just look at the Makefile, it’ll tell you.
Whenever we find a new task which we need to do more than once, we include it in the Makefile. Safe, versioned, visible.
And “once a year” is certainly more than once. In fact, the once-a-year tasks especially should go in the Makefile – or would you like to re-learn every year how to do a certain thing? No? Well, write it down, as executable documentation: as a make target.
I also make sure my CI systems run nothing but make commands (with the exception of housekeeping that’s strictly only relevant to how the CI system works internally). I want humans and the CI system to be on the same page, do the same things in the same manner, make it immediately comprehensible what the CI system does.
Sorry, couldn’t resist the pun.
Make is the glue that keeps my build system together.
It’s the foundation on which all higher-level operations on the product are built. Get this step right, and you’ve avoided a lot of problems already.
How has your experience been? Do you have an opinion on this use of make (or its friends)? Please drop me an email and let me know! I love to learn more.
Do you have a question? A project proposal? Something special in mind? Contact me, and let’s talk about how I can make your team, your products, and your life better