The author is not even using the mtime-based dependency tracking. Also the targets are supposed to be PHONY but not marked as such. The author could have replaced it with a shell script that read $1 and matched on it to determine what to do.
Or just with a simple command which is guaranteed to be on most Linux systems already - make.
Maybe his Makefiles aren't complex, nor they seem to follow all the best practices invented by code gurus in sandals, but it works and, what's important, it works
for him.
There was a time when people would have said the same about make.
The shell is the simple command that is guaranteed to be on all Unix systems from the get go. Make is the new kid on the block.
If you just want to run commands in the order written down, don't need the topological sorting feature of make and value ubiquity then a shell script is the answer.
If you are not stuck in the past and you truly live by the UNIX philosophy of doing one thing and doing it well, a command runner is the answer.
The command runner avoids the ton of foot guns both shell scripts (no matter which flavor) and make files have. just also brings a couple of features out of the box that would be very tedious and error prone that replicate in make and shell scripts.
Right but writing dependency management (of targets, not package management) in shell seems like a nightmare compared to just leveraging make. Why complicate things? It's dead simple to debug, the interface is dead simple, what's the downside?
Right, but the original point which started the thread is that "The author is not even using the mtime-based dependency tracking", in which case a plain shell script is very much a viable alternative to make.
I don't particularly mind this use of make, but as an article on make it fails to exemplify what I think is its main purpose.
Software with small scopes can be finished. It doesn’t sound too complicated to just push a new bug fix each year, by anyone. If anything, make is probably a significantly more complex codebase due to all the hacks it accumulated over the years, as a result of a dumb model it started with.
> There was a time when people would have said the same about make. The shell is the simple command that is guaranteed to be on all Unix systems from the get go.
That would've been a pretty short window of time since make first came out (according to wikipedia) in 1976.
Phew, I was so worried. So for 48 years out of Unix' 53 years of existence (90% of that time), make hasn't been the new kid on the block. Oh, let alone the fact that we're talking about stuff from 48 years ago, when their "screen" was a paper printout of the output.
> There was a time when people would have said the same about make. The shell is the simple command that is guaranteed to be on all Unix systems from the get go. Make is the new kid on the block.
I seem to recall it being praised very highly at the time as a great tool that saved many billable expensive CPU minutes and made a developer's job so much easier.
I believe you to be correct. I think it's important that one uses the right tool for the job, regardless of whether or not it's widely adopted or supported.
Or just use a simple command which ALL Unix system have: sh.
If you're using make a glorified task runner, why don't you just create a scripts/ directory with shell scripts to do whatever you want. This is simpler, cleaner and works everywhere.
Make doesn't really add anything. I get the feeling that using make this way is an aesthetic preference that has somehow developed with time into a "this is the one true Unix way" cargo cult.
I remember countless times me and forum fellas debugging makefiles written under developers’ assumptions about systems. That is also what lots of developers forget or simply aren’t aware of.
Make isn’t a silver bullet for builds. It isn’t even a bullet. Most software gets built from scratch and make’s deps graph makes little to zero sense in this mode. Make is a quirky poor dev tool footgun, jack of all trades master of none.
> it works and, what's important, it works for him.
Until it doesn't. And then you really have to learn about PHONY targets, why and when there must be a tab and not spaces - good luck with an editor that doesn't treat Makefiles special and is configured to convert tabs to spaces.
But those are things that he’ll learn about as he keeps using make. And why does it matter that some editors don’t know about makefiles? The one he is using handles them just fine so what’s the problem?
> And why does it matter that some editors don’t know about makefiles?
Because it isn't fun checking if the whitespace at the beginning of the line is a tab or spaces. And as said, you must know when to use tabs and/or spaces in rules.
For doing such a simple thing as calling some commands, Make has way too many subtle footguns which _will_ bite somebody, someday. The problem (that's not a problém at all, that's a reason to celebrate!) is that most JS devs and users aren't used to Make, compared to e.g. C programmers. To rephrase: as someone writing C, you have to use something like a Makefile, as anything else (like scripts) gets unreadable and -usable quite fast. But if you can get away with a less complex solution, you should really use that instead of Make.
> Because it isn't fun checking if the whitespace at the beginning of the line is a tab or spaces. And as said, you must know when to use tabs and/or spaces in rules.
that's why https://editorconfig.org/ exists, so that neither you nor your teammates have to think about these things
I genuinely don’t understand why that matters. The fact that there exists bad editors that don’t support my workflow shouldn’t prevent me from using the tools that I like and am comfortable with. I use editors that don’t screw up makefiles so what’s the problem? If I take your argument to the absolutely absurd logical extreme, I shouldn’t use lower case letters because some character encodings don’t support them.
And as said, you must know when to use tabs and/or spaces in rules
Is that Stockholm syndrome? Or an appeal to history/authority in action? What makes people believe that this is even remotely reasonable.
inb kids these days, I started in the '90s and wrote my share of makefiles. Tolerating make only made sense until 2010-ish, then both hw and sw advances rendered it useless.
Edit: just realized my reply to a wrong person, but let it stay here
The strengths of make, in this context where it's been coaxed into serving as a task runner for small projects, are:
1) It's already installed practically everywhere
2) It reduces your cognitive load for all sorts of tasks down to just remembering one verb which you can reuse across multiple projects, even if the implementation ends up differing a bit
3) In conjunction with the similarly ubiquitous SSH and git, you have everything you need to apply the basic principles of DevOps automation and IaC
There's something special about waking up one day with an idea, and being able to create a fresh git repository where the first commit is the Makefile you've had in your back pocket for years that scripts everything from environment setup to deployment to test automation to code reviews.
There's zero effort beyond just copying your single file "cookbook" into that new repo.
This always comes up, and is a sad chicken/egg problem.
We can all somehow agree that Make mostly sucks, but OS maintainers aren’t interested in providing a default alternative, due to choice overload or something.
I always find it a questionable choice, when someone, who wants to be a professional software engineer, uses Windows. If it is a choice at all. Of course they could also be working at some job, where there are silly ideas like everyone having to use Windows or so.
If it is a choice, it sort of shows an "I do not care" attitude to software development, or being seriously uninformed about proprietary software. Usually those are the types, for whom software engineering is merely a 9 to 5 job, and not a craft they take pride in. An activity they do not really care about at other times. Which is OK to do, not a crime. If I were hiring though, I would rather look for passionate software engineers/devs, who know a lot of stuff from tinkering and exploration. Ultimately using Windows means you are not truly in control of your productive system and are at the whim of MS. It is a risk no self-respecting software engineer should take.
To clarify, that is not to say, that there cannot be craftsmanship people using Windows. It is just way less likely. More likely they are "enterprise" software people. Even the choice to explore and use a GNU/Linux distribution betrays some kind of mentality of exploration. Wanting to know what is out there. Learning a new thing. Adapting it to ones needs. This kind of learning mindset in the long term is what sets engineers apart from others.
So I would claim, that not many good software engineers use Windows to be productive. If they have to, they will likely install some VM or some means of making things work as if they were on a GNU/Linux system. WSL or whatever, to circumvent the limitations and annoyances of a Windows system.
This is a silly take, have you heard about game developers?
If there's craftmanship anywhere, its in game development, and they surely don't want to spend all their time working on a platform without proper tooling that their end users overwhelmingly do not use.
The choice of OS has nothing to do with craftmanship or "exploration". I "explored" linux many times and am not using it currently.
In fact, I'm happy to argue that most developers that care so much about the choice of OS that they are uninterested in using another one (and do not work in OS development) are probably somehow stuck in their ways and uninterested in exploration themselves.
Taken even further, currently the only important OS is the browser, and nobody cares who launches it.
I think you're generalizing from your position inside some bubble, I am not sure which. Equivalently I could imagine game developers generalizing that linux people are terminal fetishists and have no interest in getting stuff done, who would rather customize (a.k.a fight) their OS for days on end than provide end user value, and through their idealistic, puristic and dogmatic approach to FOSS they feel safe but are meanwhile vulnerable to exploits of bad actors through supply chain attacks.
I think neither take is true, nor does it hold much value to claim it, unless your aim is to divide developers into arbitrary adverse tribes.
> You think you're superior because you use something niche.
Ah? Interesting! Tell me more about what I think!
> Some people just don't want to have to worry about laptops melting in their bags...
That is funny, because this is what happens with Windows installed, due to nonsensical system default settings. I've almost had that happen with Windows 7 once, due to an idiotic default setting regarding when the system is to wake up from hibernation, so that it turned back on while in my bag, inside an inner protection bag, nicely accumulating the heat.
Recently there was a whole long thread of people describing such problems with Windows machines. Here on HN.
Perhaps you are the one, who is not properly informed? Or are all those experiences with Windows machines somehow null and void, invalid?
Nothing is installed out of the box on windows, but anyone with a functioning development environment for a large number of programming languages will have installed wsl, msys or git bash along the way and have make installed as part of it.
To me, just is make without features I don't need. There is not a lot of benefit for me, but there is a lot of benefit for other people who need to learn the repo and have no knowledge of either make or just.
Another benefit is that justfile just cannot get too complex and tangled. Simplicity at its finest.
When step one of using a tool is to disable the tools primary benefit (everything is phone) you’re reaching for the wrong tool. Like it or lump it, make deploy is much neater than docker build -t foo . && docker tag foo $item && docker login && docker push && helm apply
I wish there was a flag for make which set it to be a command runner by default for the current makefile.
No I mean Makefiles, how author uses them, are additional complexity over shell scripts.
The whole difference of Makefiles, their original idea was to not re-compile a target _file_ if it's already there. So if you need .PHONY -- you're using Makefiles wrongly.
Please help me understand why this thing exists. Like, no snark, I like using the proper tool for a job -- when would I look at the project and think "this is something that is better done with 'just' tool". Instead of readme.txt and a folder with scripts
It’s gotten some syntactic sugar recently that’s made it pretty nice. Specifically, I’m thinking of its OS-specific sections: you can do something like
[macos]
# do a thing
And without any other checks, that section will only ever run on Mac. Yes, of course you can replicate this in Make, but it isn’t nearly that easy.
I can count on one hand the number of times a simple script or make worked out of the box. Sure, part of the reason is dependencies, but then I might as well use a build tool that is actually doing what a build tool should. Makefiles/bash scripts are hacks, and I don’t get this strange Stockholm syndrome UNIX-people have for them.
why do you need a "command runner"? Have you heard of bash functions? Or... make? The thing is too simple to justify installing another tool, however nifty it is.
Here’s a one-line horror story for you (from a real project I’m working on):
.PHONY: $(MAKECMDGOALS)
> The author could have replaced it with a shell script that read $1
Sure, but `./build.sh dev` is a bit less obvious than `make dev`.
Another reason to use Make even if you don’t have any non-phony steps is that you can add those later if needed. (I agree that the author should mark {dev,build,deploy} as phony though.)
Why is this a horror story? Under certain assumptions of how the author intends to use this, this sounds like a sensible way to define a dynamic list of phony targets to me, without having to specify them by hand.
There are many reasonable scenarios why you might want to do this: determining at the point of calling make which targets to force or deactivate for safety, projects with nested or external makefiles not directly under your control, reuse of MAKECMDGOALS throughout the makefile (including propagation to submakefiles), ...
Now make bar and make foo bar will disagree on whether foo is phony, which may or may not be what one wants depending on both what foo and qux do, and how bar depends on foo and qux side effects.
It also very much depends on what the intent is, notably such a "autophony" make foo is very different from make -B foo.
First of all, misusing a tool doesn’t “give it a bad name”, and second of all who cares? A tool isn’t a human being. Make’s feelings aren’t going to be hurt by this article.
The author just shared something they think is cool. That takes guts to show the world, and our critiques should respect that.
> I’d argue it’s a waste to use separate files here
Fine. Write a `make.sh` that parses the arguments; that would be better.
> How so?
Well, read the comments here. Do you sense that Make is a beloved tool? Most of the complaints are about some details about syntax, and those complaints are completely valid. If you use Make for its intended purpose, then it's still easily well-worth using, despite that. But if you use it as a glorified script, then all you see is the warts, without any upsides. And you then tell all your friends that "Make sux!" Which is a huge shame because Make is awesome.
That's fine, the separate files are a benefit here. The only annoyance is clogging up the root project folder -- though some people don't seem to care about that. If they got too numerous (the 5 in OP's "more advanced" project would probably not be too numerous), I'd consider putting the scripts in their own folder. I might even call it 'make' just to mess with people. Then my commands are just make/build and make/deploy and so on (.sh unnecessary). But really, in OP's case, I just have no need for some of their simple wrappers. "npm run dev" is two characters longer than "make dev", pointless.
While you're technically correct, what I gathered from their experience is the consistency of usage, between not only their own projects but third-party projects too.
They could make technical improvements to their own Makefiles, sure. But it's more about being able to enter a project and have a consistent experience in "getting started".
We are not arguing whether not declaring phony targets is worse than using comments in `package.json`?
But anyway, comments in a Makefile or `package.json` are not documentation anyway, that's what the `README` or `INSTALL` (or whatever) is there for (in projects like the one the Makefile is written for).
We all were beginners at one time or another. And if you want to learn a tool, it helps to actually use it, even if your greenhorn usage is less than perfect. You can make incremental improvements as you learn, like we all do.
That's the beauty of make and shell, it's follows the UNIX principle of being simple and doing one thing and one thing well. People want it to do many other things, like be a scripting language, a dependency tracker, etc, so they're willing to pull in bloatware. New isn't necessarily better. Autoconf and automake isn't make.
None of them are simple, they are chock full of hacks upon hacks, “fixing” their own idiocies, and by extension, none of them are doing their one thing well. Especially bash scripts, they should be left behind..
Can you be more specific what you view as hacks or idiocies? Besides the criticism of .PHONY targets, which I don't think is a hack nor particularly ugly. When I mean shell I'm referring to a family of shell languages that are used run commands, change directories, etc. Fish is a shell, for example. Babashka can be considered to be a shell. It doesn't even need to be those, someone using make could use python or javascript for the scripting part if it works better than a shell language.
Yes, the UNIX principle of being simple and doing one thing and one thing well.
Make does dependency tracking relatively well (for 1976). But if you just want to run some commands, your shell already does that just as well, without any of the caveats that apply to make.
Not satire, sorry I didn't clarify. They want make to have a builtin scripting language rather than using shell scripts, and a dependency tracking system that more complex and less tooling agnostic rather than leveraging the appropriate tool (like `npm ci`).
There isn’t even a need for a shell script. The author is already invoking three separate tools, each of which has a mechanism for invoking custom commands.
Gulp? That JS tool that was last cool in 2018? After it which it was replaced with Grunt, which stopped being cool in 2020? And that was replaced with Webpack, ESBuild, Rome, Bun...
Why would anyone voluntarily subject themselves to that kind of insanity? :-))
Better to just use the hacksaw that is Make than all these Rube Goldberg contraptions :-)
I don’t personally care about the JS ecosystem. But OP is already using Gulp. He’s then calling Gulp from npm run. He’s then calling npm run from make. Adding make into the mix is solving nothing here. If you’re saying he should use make properly I agree!