Notes for new Make users
gromnitsky.users.sourceforge.net
gromnitsky.users.sourceforge.net
I used make for years before I understood pattern rules, even though they're pretty simple. I kept trying to use foreach loops all over the place. If you're using foreach loops, check whether a pattern rule can do the job.
> The popular clamour is that the autovars are too short & confusing.
I finally realized, after years of using make and then learning pattern rules, that the three autovars listed here are visual mnemonics. $@ looks like a target, a ring with a bullseye. $< is pointing left, so it's the first prereq. $^ is like a horizontal bracket that groups all prereqs.
I've been illuminated, sincerely! Meanwhile, bmake has some more memorable synonyms for them like ".TARGET" and ".ALLSRC".
foo: foo.o bar.o
$(LD) foo.o bar.o ...
My other gripe with bmake is that this rule is needed as there is no implicit rule for linking multiple object files, or so it seems.Honest question for the webpack power-users here.
What are some important webpack features that you lose by using a Makefile like this? Because it seems like pretty much every part of a regular webpack buildchain has a command-line equivalent that you could potentially use in a Makefile.
There are tens of thousands of examples to choose from. For a makefile-based webpack, there are zero.
Unfortunately concerns like this matter.
They can also rename function and variable names with shorter ones, and compile code to be shorter (marginal gains since it's all going to be served compressed).
The other issue is that essentially no one uses make in frontend development. So you go and convert to make from something that was working fine and is the standard in that part of the industry and what's the pay off? Now no one in your team or who you hire knows how to change the build chain? Great.
Webpack is pretty new. Lots and lots of websites were developed before webpack existed, and some of them still use make for builds. The majority of new web projects are probably webpack now.
> The other issue is that essentially no one uses make in frontend development.
I don't know how many people do or don't use make, but I've had two web jobs that did. One was my own company and I wrote the makefiles, so that's not exactly fair. :P The other was an established web app. In both cases, the biggest reason for the makefile was to integrate the Google Closure Compiler into the build. Last time I checked, Webpack didn't have support for the Closure compiler. I am aware that the Closure compiler isn't exactly the most popular js minification tool today, and isn't generally necessary with webpack.
> So you go and convert to make from something that was working fine and is the standard in that part of the industry and what's the pay off?
I agree with you generally, but I'm old enough that this also makes me chuckle a little. make was working fine and was the industry standard for decades before webpack or npm.
Just before Webpack there was Gulp, and Gulp is essentially a re-invention of unix pipes and lots of the unix tools. Build systems made with gulpfiles have to bend over backwards to get right make's basic concepts like dependency evaluation, building a target only once, and skipping already built targets.
Make is for performing any variety of commands, most of which don't fit into webpack - deploy scripts, git scripts, whatever. It's a unified entrypoint for scripts project-wide. It's not a great resolver for JS dependencies, but it's a great resolver for "I need freshly-compiled JS baked into a docker container and uploaded to my docker repo".
Having something like Make is especially important in large teams in my experience. Under-the-hood tooling can often change (NPM -> Yarn, needing different test suite arguments, new docker commands, whatever) and having a single expected API for developers across your teams is particularly useful when you're the person working on dev tooling. Knowing `make test` should prepare and run a test suite or `make run` should run an app no matter which repo you're working on gives devs a consistent development workflow.
I originally did think about forgoing webpack but it does it’s job nice enough
https://github.com/shmup/react-makefile/blob/master/Makefile
Transparent cross-platform usage, specifically on Windows. Yes, you can set up Make on Windows, but it's not really the norm, especially for web developers.
FLAGS += -MMD
CFLAGS += $(FLAGS)
CXXFLAGS += $(FLAGS)
OBJECTS += $(patsubst %, build/%.o, $(SOURCES))
DEPS = $(patsubst %, build/%.d, $(SOURCES))
$(TARGET): $(OBJECTS)
$(CXX) -o $@ $^ $(LDFLAGS)
-include $(DEPS)
build/%.c.o: %.c
@mkdir -p $(@D)
$(CC) $(CFLAGS) -c -o $@ $<
build/%.cpp.o: %.cpp
@mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -c -o $@ $<I looked at clang manual when I searched for it, but unlike GCC it does not explain it.
SOURCES += $(wildcard src/*.cpp)
SOURCES += other_files.c
TARGET = foo
include compile.mkIt's very very powerfull, clear to read, and simplify all these if/else/end no end...
For example:
CFLAGS = -std=gnu99 -Werror
release/%.elf: CFLAGS += -DRELEASE
debug/%.elf: CFLAGS += -DDEBUG
Basically you can add your own context flags and variables for each individual targets, and they are 'inherited' by any of their /sub/ targets...Oh, people also need to learn about VPATH or course [0]!
[0]: https://www.gnu.org/software/make/manual/html_node/General-S...
I've thought about adding a couple of sentences about vpath (in a cautious style akin to "think twice before using it" [0]), but ultimately decided that the topic is too obscure; besides I practically never use vpath myself.
The killer feature of snakemake for me is that it can run a workflow on a single core or as many as you give it, or in the case of a cluster it can actually submit jobs to a queue and wait for them to finish before submitting more.
The tradeoff is that you need to install it (conda install -c bioconda snakemake), and that it can be very slow if you have thousands of target files. But for most workflows it's the right tool for me.
Other than your cluster example isn't this the same as passing -j to make to run jobs in parallel?
For a while, I muddled through with Make and a custom cluster job-submitter script, but the real Snakemake killer feature for me was multiple, independent wildcards. So I can, in one rule, have dir/{databasename}/{query}.tsv and rapidly hit multiple databases at once. If you are very clever (and rule one of Make is don’t be clever), you can have a GNUMake wildcard get parsed into multiple wildcards with the wimpy pattern substitution rules, but this is not a fun way to relax.
When I made extensive use of Make for my graduate thesis, I bought the book and read the majority of the text.
The cover illustration brings me joy every time I see or think about it.
POSIX make is rather limited but if you start to rely on GNU make features, you'll end up bound to a single implementation.
Which will be just fine for something like 99% of us.
I'm not advocating to use a BSD make, nor saying not to use GNU make. But appreciating GNU make's points of departure from POSIX make helps keep your makefiles simple and to the point. Which is important because another virtue of make generally (GNU make included) is that it'll likely still be around long after all these alternatives have been long forgotten. But time is never kind to complexity.
My personal favourite "watcher" implementation is this:
while true; do make; sleep 0.5; doneOr watch -n 0.5 make does the job too
Not always:
$ echo $LANG
pt_BR.UTF-8
$ watch -n 0.5 false
watch: failed to parse argument: '0.5'
(but "watch -n 0,5 ..." works for me)You can literally write it as a shell script
#!/bin/bash
N=2
while true; do
clear
echo Every $N\s: $*
$*
sleep $N
doneworks well while running on battery :)
Even if you don't directly use make, it makes for great, verifiable documentation.
Yes! Thank you! This needs to be banged into peoples heads when talking about build systems. Every time you add an edge, you're automating an otherwise manual task. Very important realization.
In addition you can have different shell for each rule with the rule specific macros if you do desire:
.ONESHELL:
.SILENT:
.PHONY: rule1
rule1: SHELL := /usr/bin/python3
rule1:
foo=bar
print("python: {}".format(foo))Also, author prepared a surprice for all coming to his blog from russian IP addresses. That was the first time I came across such thing.
But popular consensus (from here and Lobsters) seemed to be "avoid any type of space at all cost and do not speak of it again!". Pity.
> It also requires a filesystem that can support Unicode (or in my case, UTF-8) and a command line that also supports Unicode (or again in my case, UTF-8).
> And it was also not that easy to create the filename and Makefile with the non-breaking space..
Looks like setting up the compose key on linux did the trick.
I posted my own recipe for naming files using non-breaking spaces[0] after someone asked for it. A beginner here so the steps may look a little too primitive but it gets the work done. Thanks for introducing me to a hack. Now I can have a folder with two files whose name look exactly the same(ASCII 32, NBSP).
I have a project in which I'm juggling a large amount of files imported from external sources, which need to be variably processed and used as-is and in either case must have their names preserved. I wanted to use Make to handle the dependency chaining, but munging file names when inducting them means that I have to unmunge them on every output. Suddenly you can't just zip or grep -H a selection of some of the files anymore; you have to do a whole dance of copy-and-unmunge-name, clean-up-the-temporary-directory, and so on and so on and.
If I could just assign my own names, I could just as well avoid spaces, if it were purely an aesthetic issue. But it really isn't. You don't often need “something that displays as a space but you still get to decide its representation”, you need “passing through exactly the ASCII space without having to worry about it”, or the interoperability concerns still explode in your face one way or another (if they exist in the first place).
This applies to most GNU software.
I've heard in the past about my "w/" and "&" misuse (apart from my pitiful grammar) but I haven't released it can put people off. I'm sorry.
besides, you're right, "ppl" and especially "2fold" were a bit too much :)
but I've never really tried to use such a hack
What do you use instead?
I think a lot of people use make on Windows. I've had several jobs with a Windows dev environment, and they've all used make. My current dev env is cmake on Windows, so I don't touch the makefiles, but it's still using make on Windows.
There aren't that many options for cross-platform projects. A lot of people use cygwin or the Windows Subsystem for Linux with make and/or cmake native.
I also go directly to make on either cygwin or unix for one-off builds all the time, in non-C/C++ projects. make is super handy for resizing images or running a batch of tests on a program generating graphs. Anything where you need to generate files that only update when another file is touched is a good job for make.
make -j is extra handy on windows for some situations since it's hard to get gnu parallel to run in cygwin and the parallel perf wasn't very good last time I checked.
I use Make for everything from frontend builds (don't like grunt/gulp) to rust apps. The better I get at Make, the more I love it.
Make is in no way limited to C or C++ projects and there is absolutely nothing wrong in using Make for a JavaScript project.
The only thing that sucks a bit is maintaining the list of inputs and outputs if you have a lot of files.
Well, that and the fact that Makefiles are not generally portable between GNU and BSD Make so if you use both Linux and a BSD you need to install either gmake on BSD or bmake on Linux and then remember to invoke that rather than just make for your project. Of course you could have a bash function that will look and pick GNU make if there is a GNUmakefile in your directory and BSD make if there is a BSDmakefile, but maintaining such things is a hassle as well.
It always comes down to picking the right tool and sometimes Make will be it and sometimes it won’t but whether the output is JavaScript or a PDF (e.g. from LaTeX documents) or JPEGs or whatever has very little to do with it.
The fact that you have to acknowledge this proves how unorthodox it is, and ignores team concerns. So no, there is something wrong with using Make for a JavaScript project: people don't normally do it.
> It always comes down to picking the right tool
You're right, stick to the ones people actively use and don't pretend features exist in bubbles.
I'm sure my comments would be more popular if I ignored the realities of software development and only praised the novelties of it.
im astounded so many idiots have such high karma counts on hn, what a wonderful place to have discourse
I don’t see why your comments have to be grey at all, if that helps, just pointed out where few may have ‘misheard your tune’. But if it is unthoughtful, then it’s their problem, not yours. They’ll use make and suffer, isn’t it fair?
I say this as someone who doesn't really like the JS ecosystem and its churn. I suppose you could argue the JS community itself has valued novelty over using tooling others will be familiar with. But if you have two tools that do roughly the same thing, one known to a majority of contributors and one known to a minority, I would go with the more popular.
I am a developer who works with other developers, so most of us will be comfortable with make.
so is gradle, maven, xcode, it does not matter what target is or what source is (as language, file etc)
they have tasks/recipes and dependencies/prerequistes imho JS's stack of build system still not good at all. changing to new system every 2-3 years. (note that i am not a js-dev, just outside point of view)
which is kind of a not-stable-ecosystem feeling. I see small agencies spending days maybe weeks to port their 'themes' to new stacks (long ago jquery, then gulp, now webpack) where as haven't encountered single "porting to new makefile format" case, because, of course solid history/background of make.
brilliant
But it does matter what the language is for the build script for each build system, e.g. Apache Groovy for Gradle, XML for Maven.