This makefile does look simple to me, although it is not easy; but TFA never claimed it was supposed to be "easy".
The shell you mentioned is not in any way "simpler" nor even "easier". The same thing can be done with bash substitutions and loops (all supported by zsh), and someone would argue that it'd be simpler by virtue of not suffering e.g gnu vs bsd vs posix sed nor needing xargs; also, pipefail and such.
Also it doesn't do "the same thing": you have to be at a specific pwd and not in any subdir + you can't do a subset (e.g "make git")
Note I'm not saying it's better or worse.
I really like the article as it showcased a few advanced make features in a concrete and limited use case (symlinks). The result is simple to use and maintain.
TFA> Another reason to use it is this turned out to be a surprisingly easy task.
I'm very prone to being entranced by the eerily lisp-like nature of GNU Make. Got side tracked in one of my projects trying to recreate GNU autoconf inside it. That was the day I finally understood what autoconf was even doing.
The real point of make is it's a declarative build system. You just tell it to make and it will do what needs to be done by figuring out dependencies and rebuilds.
A Makefile with tasks that just run external scripts is much easier to find than the scripts directly. Add some help texts and it’s a great DevEx multiplier.
With a Makefile I can generally just run `make` or `make <tab>` to have a feel for what's available. It's right there on my terminal, which is usually the first thing I interact with when I open a repository. If enough of the engineers use it, it stays up-to-date as it gets fixed and updated along with any other changes.
Documentation OTOH has a tendency to be forgotten and left for dead. IME this is especially true for internal documentation, and the closest to the code the docs are, the less attention they receive - since higher level documentation is more likely to be consumed by people outside of the team.
With a README, I need to:
* remember to read it * trust that it will have the information * trust that the information is up-to-date * finally, figure out paths to scripts, arguments and/or copy-paste commands
Not at all. The rules are generic. I can give make any path inside my home directory and it will try to match it against an equivalent file in the repository.
$ make /home/matheus/.vimrc
ln -snf /home/matheus/.files/~/.vimrc /home/matheus/.vimrc
I only need to update the makefile if I want easy to use phony targets. These phony targets in turn simply depend on the paths to the real files which activate the generic rules I described in the article.It looks complicated because I used functions to compute all these paths from the items in the repository. Here's what the final result looks like:
$ phony-targets GNUmakefile
git
/home/matheus/.config/git/config
mpv
/home/matheus/.config/mpv/mpv.conf
vim
/home/matheus/.vimrc
# ...
I could have used any of those paths and it would have worked. The phony targets are nice but not strictly needed.The bulk of the makefile is dealing with environment variables such as XDG_*_HOME and GNUPGHOME variables which affect where the links are supposed to end up.
This Makefile is anything but simple. It uses advanced features that are meant for complicated situations, just to create a few symlinks. The same symlinks, every time. And if you introduce a new dotfile to the repo, you have to update the Makefile too.
It also makes no use of the main feature of make(1) - to track files for changes, and update them.
For demonstration, here is the same functionality, in sh(1):
Doesn't use advanced features, shorter, and you don't need to update the script for new dotfiles. And more "ubiquitous" than GNU make.