Misusing makefiles as a poor man's bash script with a switch statement.
I still don't get it.
If you write a bash or POSIX shell script then you need to learn bash/POSIX shell (or suffer the consequences of not learning it).
If you write a Makefile and ignore 99% of it's features you now also need to learn GNU or POSIX make (or suffer the consequences of not learning it).
Strictly a worse deal and an extra dependency.
And no, "everyone uses make this way so it's a common interface which everyone agrees on" is not the answer.
1. Nobody agrees on target names other than `all` and `clean`. So you need some documentation or some help target.
2. Nobody agrees on a help target. So you need documentation or force your developers to read the makefile.
3. Nobody remembers that parallel make does not guarantee the execution order of the targets. So if someone stumbles into your project directory and runs `make -j 8` they will likely be surprised when everything breaks and you will need to document this or force them to read the Makefile.
4. Not every project actually uses Makefiles, a bunch of them use the kind of script(s) I mentioned, some use purpose built "task runners" (i.e. the bits of Make which people who misuse makefiles actually like to use except more ergonomic), some rely on people knowing how to build the project using the normal build tools, some just document the commands you need. Either way, you're going to either have to document which approach you're using in a `^README(\..*)?$` file or rely on your developers to either ls and discover things for themselves or try random commands until something works or gives a useful error message.
So please, if all your project does is use the language default build system, don't bother misusing Make to allow people to run `make` to either a: have the project build itself, b: have the project build and run itself, c: have the makefile dump out a help output, or d: get an error because you used GNU make and I'm on BSD.
If your project needs some non-trivial commands to build it, shove them in a script. If there's more than one command, either use a collection of scripts at the root, or in a sub directory, or a single script with a case statement and a help output. Also, document this in the `^README(\..*)?$`.
Maybe I should be writing this kind of stuff in my blog rather than writing long-form HN comments. I am certainly
I use Makefiles to build Go applications for two reasons: it is available on the systems we develop on, and it provides a real alternative to writing bash scripts.
Build scripts are bad. They tend to lead to complexity over time. It is very easy to just add some ad-hoc magic to solve a problem than to sit down and think about how one should structure things better. This makes it harder for people unfamiliar with the codebase to understand what is going on.
Then you need to choose a language. Bash? Well, not a lot of people know Bash all that well. And it isn't a very nice language to express the kinds of things you need to deal with to solve build problems. People don't bother learning Bash because Bash isn't a very useful language.
Python? What version? What libraries? Now you need to choose what tooling to use for maintaining your tooling. The embedded world uses lots of Python. The short version: it only makes things worse. People waste time having to learn how to maintain the tooling. If they don't, they will struggle.
Makefiles were made for building C. They are tailored to how to C toolchain works. When you make "proper" use of Makefiles this can provide you with a lot of help. If you program C. If you are programming in other languages: not so much.
The good thing about using Makefiles with as little magic as possible is that it forces people to keep things simple. It is okay that you don't make use of 99% of its features. Not everything has to be a demonstration of your mad <tool> skillz.
That being said: it would be nice to have a more approachable alternative to Make that can be used across languages. Something that promotoes declarative builds rather than allow scripting. Because if you allow people to write code to build things, you are not going to be able to understand most people's builds without setting aside time to study them.
You seem to be describing the use of makefiles for the purpose they're intended for: Describing a DAG where each node is a file and each edge is a build step. This is not a misuse of Make and not what I'm complaining about.
That being said, you're under the impression that you're somehow not writing posix shell/bash when writing a makefile. You still are.
Sure, but we're often making sparing use of what make has to offer, like the pattern rules. I think that's okay, but it is also a reminder that perhaps there is room for a similar tool that can support patterns and built-in mechanisms that are more useful to today's languages. Rust and Go in particular.
I think there is a huge difference between implementing logic in bash and invoking programs using shell syntax.
I am aware of the fact that a lot of people used to put shell script beyond simple invocations in Makefiles, but I see that as a degenerate case. You shouldn't do that.
> I am aware of the fact that a lot of people used to put shell script beyond simple invocations in Makefiles, but I see that as a degenerate case. You shouldn't do that.
Okay, so I am not sure why you seemed to object to my initial comment specifically talking about this kind of use of Make.
I was guilty of this habit of misusing Makefiles for a few years. I see why it's appealing but you're totally right for all of the given reasons.
Nowadays I use (and highly recommend) using standard-library Python for this sort of thing.
It's much more readable than shell scripts and it's completely cross-platform so you can use the same script for Windows, Mac, Linux.
I still don't get it.
If you write a bash or POSIX shell script then you need to learn bash/POSIX shell (or suffer the consequences of not learning it).
If you write a Makefile and ignore 99% of it's features you now also need to learn GNU or POSIX make (or suffer the consequences of not learning it).
Strictly a worse deal and an extra dependency.
And no, "everyone uses make this way so it's a common interface which everyone agrees on" is not the answer.
1. Nobody agrees on target names other than `all` and `clean`. So you need some documentation or some help target.
2. Nobody agrees on a help target. So you need documentation or force your developers to read the makefile.
3. Nobody remembers that parallel make does not guarantee the execution order of the targets. So if someone stumbles into your project directory and runs `make -j 8` they will likely be surprised when everything breaks and you will need to document this or force them to read the Makefile.
4. Not every project actually uses Makefiles, a bunch of them use the kind of script(s) I mentioned, some use purpose built "task runners" (i.e. the bits of Make which people who misuse makefiles actually like to use except more ergonomic), some rely on people knowing how to build the project using the normal build tools, some just document the commands you need. Either way, you're going to either have to document which approach you're using in a `^README(\..*)?$` file or rely on your developers to either ls and discover things for themselves or try random commands until something works or gives a useful error message.
So please, if all your project does is use the language default build system, don't bother misusing Make to allow people to run `make` to either a: have the project build itself, b: have the project build and run itself, c: have the makefile dump out a help output, or d: get an error because you used GNU make and I'm on BSD.
If your project needs some non-trivial commands to build it, shove them in a script. If there's more than one command, either use a collection of scripts at the root, or in a sub directory, or a single script with a case statement and a help output. Also, document this in the `^README(\..*)?$`.
Maybe I should be writing this kind of stuff in my blog rather than writing long-form HN comments. I am certainly