26 ms·
The Makefile I use with JavaScript projects
- juliend2 9y agoOne thing I've found useful about gulp and webpack is the fact that it's multiplatform. What is the best approach to make sure your Makefile will work as expected on every platform, meaning, windows included? For example: Can we write file paths using forward-slashes, or is it still an issue? I imagine running it via git bash (bash provided by the git installer on windows).
- metalliqaz 9y agoAh yes, the horror of autoconf and automake...
- rmgraham 9y agoYou can use forward slashes for paths on Windows in your Makefile. They are actually required if you want to use wildcards.
- jcadam 9y agoCMake! No, I'm kidding, don't really use CMake...
- jcadam 9y agoDownvote?! Looks like we have a CMake fan...
- theothershoe 9y agoGood point - cross platform issues are a concern. I've noticed in the past that OS X machines tend to run older versions of Make (unless the owner has installed a newer version with Homebrew). It is a good idea to pay attention to the Make features that you use, understand which features were added in recent versions, and be aware of which features are specific to GNU Make. In my projects I recommend that users make sure that they are in fact using GNU Make. Some systems might not support the `-p` flag in `mkdir -p`, or the `-rf` flags in `rm -rf`. There are scripts distributed on NPM called `mkdirp` and `rimraf` to work around such issues.
- wbkang 9y agoBtw Windows has supported slashes forever. Just don't mix the two.
- dblotsky 9y agoMake works on Windows. You can get it standalone, or as part of MinGW (and then even other Unix tools will work).
- habosa 9y agoYes! I recently used Make on some JS projects and my coworkers looked at me like I was insane. Even if you don't know advanced Make-fu it's a really good way to run all of your build steps in the right order without some crazy JSON config format.
- ziikutv 9y agoWish this article was about just make rather than JavaScript and using it in tandem
- theothershoe 9y agoNoted! I wanted to provide concrete examples, and I did not want the post to become too long. So I focused on one kind of project.
- dblotsky 9y agoIMO there's a particularly dire need to free the JS world from the tyranny of the ever-shifting Build System of the Day(TM).
- athenot 9y agoAfter going through a few build systems for Javascript, I realized they were all reinventing the wheel in one way or the other, and pulled out venerable Make from the closet. It turned out to be way more expressive and easy to read. One target to build (prod), another to run with fsevents doing auto-rebuild when a file is saved (instant gratification during dev), then a few targets for cleaup & housekeeping. All said, the file is 1/4 the size of any other JS-based build systems.
- IshKebab 9y agoWow if you consider Makefiles easy to read...
- gnclmorais 9y agoI’ve written about Makefiles for the web before, you can’t say they can’t be readable: http://blog.gnclmorais.com/makefiles-are-for-the-web http://blog.gnclmorais.com/makefiles-are-for-the-web
- jorams 9y agoSomething about the Makefile in your post is a bit weird though: You only declare "test" as a PHONY target, but every other target in the file is just as PHONY. And since you don't even explain that line, it could be a bit confusing.
- bpicolo 9y agoSimple makefiles couldn't be more simple. task: dependency list of commands That's about as easy as it gets.
- bitwize 9y agoUntil a stray space finds its way into your command list indentation...
- 9y ago
- metalliqaz 9y agoI'm not a web dev, but this article has uncovered yet another thing in the js ecosystem that just seems crazy to me. This makefile snippet: lib/index.js: src/index.js mkdir -p $(dir $@) babel $< --out-file $@ --source-maps The source and the output are both called index.js? Why, God, WHY???
- an_ko 9y agoWhy not? They're both entry points (hence 'index'), both JavaScript (hence '.js') but in different directories. Do you have difficulty distinguishing between /home/me/.vimrc and /home/somebodyelse/.vimrc too?
- eropple 9y agoBecause `require` and `import` look at your package's `main`, which (if it's a directory) implies `dirname/index.js`. Building to an `index.js` entry file is, then, the most standard name that allows `require 'modulename'` to work. The capitalized rending-of-garments is silly. This is transpiling; file names should remain the same from input to output.
- bitpow 9y agoIt's because there is always lag between the latest .js spec and what is supported by browsers. So transpilers (like babel) have to dumb it down from fancyNew.js to somethingIE6MightRun.js It is not realistic/optimal to try to write your javascript to be supported by all browsers or runtime clients. It's better to write using the latest spec, and just have it dumbed down for you by transpilers at build time Some more explanation here: https://www.excella.com/insights/typescript-vs-es6-vs-es2015 https://www.excella.com/insights/typescript-vs-es6-vs-es2015
- flukus 9y agoBecause babel compiles javascript to javascript, so you'd expect the input to be a javascript file and the output to be a javascript file. Of course that sentence contains it's own level of craziness, but the problem does not lie in the build step.
- crescentfresh 9y agoTangential, but I cringe everytime I see the word "transpiler". A compiler is a compiler is a compiler. Previous discussion on this: https://news.ycombinator.com/item?id=15154994 https://news.ycombinator.com/item?id=15154994
- bringtheaction 9y agoI think it’s useful to distinguish compilation whose target is another language that was originally intended to be human-readable (transpilation) from compilation to a form intended exclusively for machines (compilation to machine code or bytecode).
- masklinn 9y ago> I think it’s useful to distinguish How and why? And what do you do of compilers which can do either based simply on the backend you select?
- drabiega 9y agoPersonally, I think of transpilation as a subset of compilation. So a transpiler is also a compiler, and a compiler that has a readable language backend can do transpilation, which is a type of compilation.
- crescentfresh 9y agou/masklinn still asks a good question though: there are tools that act on the source code for both "compilation" and "transpilation" (eg Kotlin), depending on the target platform. They do not distinguish, why should we?
- drabiega 9y agoFor the same reasons you might ever want a more specific term? What about assemblers or disassemblers? Given a suitably broad definition of compiler that includes transpilers, are they not also included? Wouldn't the same arguments apply?
- jaxtellerSoA 9y agoAs a non-programer the only experience I have with makefiles are unpleasant ones of running ./configure then ./make only to go down an endless rabbit hole of missing dependencies. I am very grateful that yum/apt-get, etc. have come such a long way, they grab all your dependencies, you don't have to wait long periods of time for the code to compile. I am sure Make still has it's uses, but I am sure glad package managers of have made makefiles irrelevant to me.
- yoz-y 9y agoThis is not really a fair comparison though. Makefiles and package managers are orthogonal and the latter has not really replaced the former. Makefiles are like a recipe, package managers are food delivery. Somebody has still to cook the food.
- digi_owl 9y agoAnd the dependency tree (kudzu?) can be blamed on the "chef" preparing said recipe.
- MaulingMonkey 9y ago> This is not really a fair comparison though. I'd argue it's entirely fair with other examples (e.g. compare and contrast to, say, Rust's cargo build.) You can write a Makefile which fetches and builds your dependencies. Makefiles might be like a recipe - but these days we're building recipes for building entire OS images, including grabbing the dependencies in the first place. A single software project by comparison is trivial. The problem is Makefiles are a jack of all trades, and master of none. You have to write or copy a distressing number of rules yourself, per project, per subproject, and know the underlying build chain in relative depth to do even some rather basic things. I'd argue makefile authors not automating their dependency fetching is a symptom of this. As a programmer, I avoid them, because I'll end up stuck maintaining them and end up lowering the build system's bus factor. With perhaps the exception of a couple of simple rules that forward to a "proper" build system, because I've written enough of them in the past that "make" still feels like the right default action that should generally work. But if it all possible, never for the meat of the build system.
- dmitriid 9y agolib/%: src/% mkdir -p $(dir $@) babel $< --out-file $@ --source-maps Just look at all those magic things. The percent signs! $<! $@! Well, I know they are not magic ;). But why would I want them when I can actually use normal names like "deps"/"entries" and "target"? It gets substantially worse as we go down the rabbit whole. Where webpack can easily walk the entire dependency tree by itself, we have to invoke src_files := $(shell find src/ -name '*.js') Where we can use same webpack to seamlessly output the resulting file into an output directory, we need to do the (very unintuitive) pattern substitution: transpiled_files := $(patsubst src/%,lib/%,$(src_files)) or even flow_files := $(patsubst %.js,%.js.flow,$(transpiled_files)) And when we want to watch for changes? Well, we need an external program anyway. $ yarn global add watch $ watch make src/ The art of Makefiles is often lost for good reasons: because Makefile don't really cut it anymore.
- dblotsky 9y ago"Doesn't cut it anymore" isn't the same as "has a different way of doing it". Make has many other (necessary) features that Webpack doesn't.
- bryanlarsen 9y agoMake works great for JavaScript but it seems very few people do so. https://github.com/webpack/webpack-cli/issues/152 https://github.com/webpack/webpack-cli/issues/152
- toast0 9y agoWorking somewhere that really embraced Makefiles is actually very nice. If you keep your dependencies simple, the Makefiles to build stuff are pretty simple too, and it works for all the languages you might write software in. You can use it to deploy to servers too.
- jgh 9y agoCMake is so nice compared to vanilla makefiles. I wonder if it can be used this way with Javascript.
- josteink 9y agoMaybe I'm wrong, but I always assumed CMake was optimized for the C language (thus the name)? That's at least what I've always seen it used for. What would you gain if you're using it for other, less supported languages, like Javascript?
- jgh 9y agoIt lets you generate makefiles in a less verbose way. Like if you have a lot of files in a project or a bunch of targets Makefiles can get a bit unwieldy by themselves. I've only ever used it for C++, but I don't see why it (or something like it) couldn't be used for other languages too.
- isaachier 9y agoCMake is mostly dedicated to C/C++ projects, but also has built-in support for assembly, Fortran, and Java. CMake has templates for adding a new language as well. The benefits are: cross-platform "shell" commands (you can copy files without using an explicit cp), standard lookup for programs, and easy target generation from a collection of files. Most languages are pretty similar to C/C++ when it comes to the build cycle. Portability (i.e. testing for existence of headers) is less of a concern for something like Javascript, but everything else still applies.
- digi_owl 9y agoGotta love all caps options with a prefix(?) that only shows up on the command line...
- ethagnawl 9y agoI'll second this. I had to use CMake for the first time recently and was pleasantly surprised by the experience. This tutorial was making the rounds (on HN and elsewhere) last week, but in case anyone missed it, here's a link: https://github.com/pyk/cmake-tutorial https://github.com/pyk/cmake-tutorial I found it to be a great primer/refresher.
- fuball63 9y agoWe use make for standardizing the way docker containers are built, pushed, tested, and run (debug and production modes). I even prefer it to docker-compose at this point, because it is more programmable.
- ethagnawl 9y agoIf you're able, I'd be very interested in seeing some examples.
- mauvehaus 9y agoNot the OP, doing a bit less that it sounds like the OP is doing, but we built out a relatively handy make-based build system for building a set of images in correct dependency order. Another member of the team subsequently taught make about the reverse dependencies so that you can split jobs across Travis nodes by the top-ish level image they depend on. My favorite addition was the ability to generate a dependency graph using graphviz straight from the Dockerfiles. N.B. Project is now moribund, the team was disbanded. May not build at all. Don't know if any of the forks are active.
- ethagnawl 9y agoThanks for chiming in. That all sounds very interesting and this thread has got my gears turning. I regret not considering Make for Docker administration months/years ago. I've taken to using bash scripts or, worse, tagged bash comments to recall commonly used complex commands.
- fuball63 9y agoThat's pretty interesting about Travis. Make is great because you can do as much or as little with it as you want, but it generally always improves organization.
- fuball63 9y agoSHELL=/bin/bash VERSION=1.0 build: clean docker build -t webservice:$(VERSION).$$(date +"%y-%m-%d") . shell: docker run -it -v $$(pwd)/src:/opt/app \ -p 8888:8888 \ --name webservice \ -e SECRET1=$$SECRET1 \ -e SECRET2=$$SECRET2 \ webservice:$(VERSION).$$(date +"%y-%m-%d") \ /bin/bash run: docker run -it \ -p 8888:8888 \ --name webservice \ -e SECRET1=$$SECRET1 \ -e SECRET2=$$SECRET2 \ webservice:$(VERSION).$$(date +"%y-%m-%d") tag: docker tag webservice:$(VERSION).$$(date +"%y-%m-%d") webservice:latest push: tag docker push webservice:$(VERSION).$$(date +"%y-%m-%d") docker push webservice:latest clean: -docker kill webservice -docker rm --force webservice test: docker run -it \ --name webservice \ webservice:$(VERSION).$$(date +"%y-%m-%d") \ python3 tests.py Couple of notes: - I do major.minor.yy-mm-dd versioning, so this handles that automatically - shell is for dropping you into a prompt with your present directory mapped to the working directory. I find this super helpful for debugging and testing containers - run is for testing your CMD and entrypoint scripts
- rectang 9y agoMake's interface is horrible. Significant tabs. Syntax which relies on bizarre punctuation... If only whoever authored Make 40 years ago had had the design acumen of a Ken Thompson or a Dennis Ritchie! We're stuck with Make because of network effects. I wish that it could just become "lost" forever and a different dependency-based-programming build tool could replace it... but that's just wishful thinking. The pace of our progress is doomed to be held back by the legacy of those poor design decisions for a long time to come.
- AnIdiotOnTheNet 9y agoMake is such a horrifically awful thing to work with that I just end up using a regular scripting language for building. Why learn another language with all its eccentricities and footguns when I already know several others?
- deleted 9y ago[deleted]
- rectang 9y agoAnother advantage of using a scripting language is that the hard work of portability will already have been done for you by the authors of the scripting language. Make, in contrast, works within a shell and invokes programs which may be either wildly or subtly incompatible across platforms. Add in the lacking support for conditionals in POSIX make and portability is a nightmare.
- sneak 9y agoit is possible that if you need to do that much in a makefile that you are running into shell incompatibilities then perhaps you are attempting to cram too much complexity into your build system and perhaps should be using something like Docker to decrease incidences of “works on my machine/os/distro/et c”. (I am aware that this advice does not hold true in all cases; just that for many of them overly complicated build systems is a code smell.)
- 9y ago
- benwaffle 9y agoI believe $< is only the first dependency and $^ is all of them
- gsaga 9y agoAnyone here uses makefiles for anything other than compilation and build? One can use it to add some level of concurrency to shell scripts.
- Posibyte 9y agoI use it for programming microcontrollers, FPGAs, and doing additional signal testing on those devices. I also use it to control some processes that keep some hobby IoT devices in sync. It's just a really handy way to do parallel jobs like that.
- isaachier 9y agoOnly really makes sense when you need to generate targets from a series of inputs. The targets don't have to be files, but it helps if they are to preserve the timestamp.
- mturmon 9y agoYou can look at data reduction tasks as dependency networks. Generate/retrieve data, reduce data, plot data. If the intermediate artifacts are files, you can use make to run the data pipeline. If part of the data changes, or new data arrives, you just run make again, and the whole pipeline re-does whatever is new. Very slick. It has free concurrency (make -j N). I've used this effectively several times for medium-scale (~GBs) science data processing.
- hooya 9y agoI use it for almost everything. Take ETL type tasks. It's almost impossible to remember where I downloaded certain data files six months after initially creating a project. I put that into the Makefile. Everything I do on the command line, I put into a Makefile. That way, 6 months later when I need to download new data, do some transformation on that data and load it into the database, 'make' re-traces my steps from 6 months ago. Broadly, my ETL makefiles look like this: all: data.loaded data2.loaded data.csv: wget 'some url' %.sql: %.csv sed/awk/custom-python-script $< > $@ %.loaded: %.sql psql < $< && touch $@
- pjmlp 9y agoA few decades ago, while at the university, I used it for automating generation from LaTeX documents.
- rcarmo 9y agoI use Makefiles extensively for Docker, all sorts of individual projects (it's much easier to "make serve" than remember the specific invocation for getting a dev server up when you use multiple programming languages) and, of late, for Azure infrastructure deployments: - https://github.com/rcarmo/azure-docker-swarm-cluster/blob/master/Makefile https://github.com/rcarmo/azure-docker-swarm-cluster/blob/ma... - https://github.com/rcarmo/azure-acme-foundation/blob/master/Makefile https://github.com/rcarmo/azure-acme-foundation/blob/master/...
- fernandotakai 9y agoi (and people at work) do the same thing! i find it really easy to work with docker/k8s/helm/compose with Makefiles. one tip -- remember to use .PHONY on your targets -- https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html https://www.gnu.org/software/make/manual/html_node/Phony-Tar...
- isaachier 9y agoI started my career with C++ development and never used a direct makefile in any of my projects. When I write C/C++, I use CMake. My current job has me programming in Go where people seem to love makefiles, but I consistently find bugs in the implementation (usually has too many phony targets, etc.), Why don't people use makefile generators outside of the C/C++ community?
- jschwartzi 9y agoI don't use CMake for embedded systems because the syntax and options are even more obtuse for what I need to do with it. When I get down to it, every make-based build system I've ever used boils down to using the macro language to generate all the targets, and then building your output board image by dependencies. But it's the details of how to do this that vary widely depending on your application for the board. CMake does a great job of compiling executable code and linking it using your compiler of choice, but where it falls flat is in giving me a convenient mechanism for fitting that executable into the system image.
- isaachier 9y agoI'd need to know more about the details to answer completely. I think CMake does have a complicated syntax, yet I think it is worth the nuisance in most cases. Many tools can use CMake's compilation database for configuration, such as clang-format and clang-tidy.
- pknopf 9y agoIt sounds like you are looking for something like Yocto/OE, which you can bake pretty much any build script into, cross compile and deploy. What exactly are you looking for with regards to deployment, and what tool do use, instead of CMake, to give you that ability?
- jschwartzi 9y agoCan Yocto or CMake build QNX systems or bare-metal binaries with TI's compiler? The tool I'm looking for is Make because Make gives me a ton of flexibility to build whatever freaky combination of binaries might go into whatever product I'm working on, and then combine those binaries into a system image. The point I'm trying to make is that every build system except Make solves a really specific class of build problem(building applications, or building Linux systems using GCC) and then pretentiously claims to support everything that matters. What you're actually getting is a small sliver of what you might need in my world. This article is another example of how Make can do something really unexpected by providing really simple features and letting you decide what matters to you. I've yet to see another build system that is as generally useful.
- bitwize 9y agoIf you need to write in C or C++, use CMake. Otherwise, use whatever modern build tool your language provides. It's 2018, and Make should have died in the 70s,
- peterwwillis 9y agoA lot of "modern" build tools lack necessary features.
- jayshua 9y agoThe concepts behind make are quite good, but the interface it provides is not decidedly not. It reminds me of Git in that respect. I'd think replacing the opaque symbols used everywhere with more descriptive words would be helpful. I don't suppose anyone knows if modern Make versions support alternatives to $@, $%, $?, etc. that can be read rather than memorized?
- xaedes 9y agoYou _could_ do something like this: make -f- << sed 's/MAKE_TARGET/\$@/' Makefile.descriptive But for the sake of compatibility I wouldn't.
- JetSpiegel 9y agoNo need for ugly sed error-prone trickery. Use on the Makefile: MAKE_TARGET := /some/path And invoke $ make MAKE_TARGET=/other/path
- lolikoisuru 9y agoHis point was that all of $@, $%, $? have more descriptive names as well, you don't need to use these single character macros. Also you probably meant ?= instead of := as the command you gave would still use /some/path instead of /other/path if you use :=.
- bsenftner 9y agoA long time ago, in a developer's paradise called the 1970's there was an automated build tool called "make". It had this and only this syntax: If a line begins at character 0, that is a list of files whose timestamps should be checked, if any are 'old', then execute the series of command lines beneath, identifying them as starting with a tab character. That was it, the entire syntax of "make", and it was complete. Then some smart people fucked it up and we have that piece of shit we call "make" now.
- Sir_Cmpwn 9y agoI did not use Make at this time (I wasn't alive!), but it seems that you'd have to declare dependencies too. How did you determine if it was "old"?
- brilee 9y ago"If a line begins at character 0, that is a list of files whose timestamps should be checked" The list of files would be the declared dependencies.
- Sir_Cmpwn 9y agoAh I see.
- deleted 9y ago[deleted]
- deleted 9y ago[deleted]
- bsenftner 9y agothe first file in the list is the one whose timestamp is compared against all the other files in the list after it. If the timestamp of any file is newer than that first file, the following lines starting with a tab are executed.
- cat199 9y ago> Then some smart people ... not sure which make you are criticizing here.. BSD Make (aka PMake) is imho light years beyond GnuMake in terms of coherence of the extensions to the base language and usability.. unfortunately most people in linux land think make==gnumake, and so it is hardly used outside of the base build system of BSD systems..
- nzoschke 9y agoI’ve had a lot of fun recently writing a Makefile for a Go and Lambda app: https://github.com/nzoschke/gofaas/blob/master/Makefile https://github.com/nzoschke/gofaas/blob/master/Makefile It started very verbose, one target for every Go program, until I figured out target patterns. I’m also enjoying the -j flag to do things in parallel. Now it’s 3 lines of Make to build 10 go programs in parallel in seconds. Parallel is also enough job control to run the development server and to watchexec rebuilding all go programs on code change.
- wbkang 9y agoLooks good, I think you need to add PHONY targets
- rschloming 9y agoI think the reason make is both so controversial and also long-lived is that despite how everyone thinks of it, it isn't really a build tool. It actually doesn't know anything at all about how to build C, C++, or any other kind of code. (I know this is obvious to those of us that know make, but I often get the impression that a lot of people think of make as gradle or maven for C, which it really isn't.) It's really a workflow automation tool, and the UX for that is actually pretty close to what you would want. You can pretty trivially just copy tiresome sequences of shell commands that you started out typing manually into a Makefile and automate your workflow really easily without thinking too much. Of course that's what shell scripts are for too, but make has an understanding of file based dependencies that lets you much more naturally express the automated steps in a way that's a lot more efficient to run. A lot of more modern build tools mix up the workflow element with the build element (and in some cases with packaging and distribution as well), and so they are "better than make", but only for a specific language and a specific workflow.
- sebcat 9y ago> It actually doesn't know anything at all about how to build C, C++, or any other kind of code. I guess it depends on how you define "know", but there are implicit rules. $ cat foo.c #include <stdio.h> int main() { printf("Hello\n"); return 0; } $ cat Makefile foo: foo.c $ make cc -O2 -pipe foo.c -o foo $ ./foo Hello
- peterwwillis 9y agoYeah. There is a metric crap-ton of the design of Make that is solely for the purpose of compiling and linking and document processing. That's actually part of what makes it annoying to use it for projects other than C or C++, when you don't need to compile or transform or depend on different formats.
- rschloming 9y agoThe core of make is really just a control flow model that understands file dependencies as a first class thing, and permits arbitrary user supplied actions to be specified to update those files. All those default rules around how to handle C files are really more like a standard library and can be easily overridden as desired. IMHO what makes it annoying for projects other than C or C++ is that there isn't an equivalent portion of makes "standard library" that applies to e.g. java, but this is largely because java went down a different path to develop its build ecosystem. In an alternate reality java tooling might have been designed to work well with make, and then make would have a substantial builtin knowledge base around how to work with java artifacts as well as having a really nice UX for automating custom workflows, but instead java went down the road of creating monolithic build tooling and for a long time java build tooling really sucked at being extensible for custom workflows.
- solomatov 9y agoThere's actually a much better general purpose build tool: https://bazel.build/ https://bazel.build/ I consider it Make 2.0.
- afranchuk 9y agoI have used make for years and am very familiar with it. My two major complaints are: 1. The assumptions that it makes. Everything in and out are files (phony files notwithstanding). It is hard and painful if you want outputs to rely on and rebuild from configuration in the makefile itself. It's not impossible to implement, but it's difficult to precisely implement it: often times I've seen systems that just rebuild everything after configuration changes. 2. The mix of declarative and imperative styles, while useful for quickly throwing a build together, gets difficult to deal with as things scale up. The make language itself is pretty restricted, too (without using $(eval)). I know that recent versions support guile extensions and even C(/C++?) extensions, but at that point it's not giving you all that much. I have often wished the make functionality was exposed in some "libmake" for me to extend. For this reason (and others), I've recently refactored a huge build system to use shake[1] instead. Now builds are precise and correct, and properly depend on configuration and build environment. [1]: https://shakebuild.com/ https://shakebuild.com/
- jlg23 9y agoThe author forgot some great features of make: * Parallel execution of build rules comes for free in a lot of implementations. This is really noticeable when you do heavy asset pre-processing. * Cleanly written build rules are re-usable across projects as long as those projects have the same structure (directory layout). * Cleanly written build rules provide incremental compilation/assembly for free: You express intermediate steps as targets and those are "cached". I put the "cached" in quotes here, because you essentially define a target file which is regenerated when it's dependencies are updated. Additional benefit: Inspection of intermediate results is easy - they are sitting there as files right in your build's output tree.
- theothershoe 9y agoThank you for these points! I think that parallel execution is especially appealing. I edited the article to mention that.
- lowbloodsugar 9y agoThe problem with make is that people build makefiles such that it is later referred to as a Lost Art.
- dblotsky 9y agoPeople do this with all build systems. The difference is that Grunt/Gulp/Broccoli files are a Lost Art in 3 years, and Makefiles have been around for decades.
- neonscribe 9y agoI used make heavily in the 80s and 90s, but haven't much since then. Recently I started a project that had source files getting processed into PDF files, for use by humans. Since this is the 21st century, those files have spaces in their names. At a certain point, I realized that I should be managing this processing somehow, so I thought of using a simple Makefile. A little searching reveals that the consensus on using make with files with spaces in their names is simply "don't even try." In the 21st century, this is not an acceptable answer.
- hzhou321 9y agoDemanding the support of spaces in filenames significantly complicates code as simple space delimination no longer works and other delimination schemes are much more error prone -- forgetting balancing quotes, any one? While you are allowing spaces, you probabaly are allowing all possible code points or maybe even a null byte? Thinking about it gives me headaches. I hate hearing people using 21st century or modern as reasons for inflating complexities. Without rein on complexity (whether it is hidden or not), the future is doomed, whatever you are building. While I am not saying we should avoid complexity at all cost, I am insisting that all complexity should be balanced with merits. The merits of filenames with spaces is they read better in a GUI explorer. Whether that merit balances out all the complexity it brings is individual dependent. For me, that merit ranks very low and I avoid spaces in my filenames at all opportunities. For some, they need those filenames to be readable. And there are solutions. One solution, from those who don't code, seems to demand ("developers", paid or not) that every tool that deal with files should handle this additional complexity, regardless of their context and what they think. Another solution would be to add an additional pre-step of copying/renaming/linking/aliasing. With the latter solution, the complexity is confined. I guess for some, it only matters with "I do work" or "they do work" rather than the big picture. That is fine. However given the context of you are working with Makefiles, then you are a developer at some level, you are supposed to do some work.
- andrew_wc_brown 9y agoget out of here spaces.
- titanomachy 9y ago> The target name `all` is special: When you run make with no target specified it will evaluate the `all` target by default. This doesn't appear to be true, at least on GNU Make 3.81 (MacOS). Rather, the first target listed is the one that gets built on `make` with no arguments.
- deleted 9y ago[deleted]
- fiatjaf 9y agomake is scary because people use autogenerated Makefiles. After you've tried to naïvely read a Makefile for a medium-sized C project you'll never want to write a Makefile yourself. That said, there's no tool that works so simply and so beautifully as make when you have a lot of build steps that generate lots of intermediate files with complex dependency links between them. That situation may happen everywhere, even if you're generating a bunch of PDFs or rendering HTML templates or making images from .dot files or whatever. Use make. Or is there an alternative tool for these situations also?
- platz 9y agoThe only build systems that I'm aware of that are monadic are redo, SCons and Shake-inspired build systems (including Shake itself, Jenga in OCaml, and several Haskell alternatives). One realistic example (from the original Shake paper), is building a .tar file from the list of files contained in a file. Using Shake we can write the Action: contents <- readFileLines "list.txt" need contents cmd "tar -cf" [out] contents There are at least two aspects I'm aware of that increase the power of Make: - Using `$(shell cat list.txt)` I can splice the contents of list.txt into the Makefile, reading the contents of list.txt before the dependencies are parsed. - Using `-include file.d` I can include additional rules that are themselves produced by the build system. It seems every "applicative" build system contains some mechanism for extending its power. I believe some are strictly less powerful than monadic systems, while others may turn out to be an encoding of monadic rules. However, I think that an explicitly monadic definition provides a clearer foundation. http://neilmitchell.blogspot.com/2014/07/applicative-vs-monadic-build-systems.html http://neilmitchell.blogspot.com/2014/07/applicative-vs-mona...
- nickwanninger 9y agoI actually usually have a general-use Makefile that I work from as a starting point [1]. It takes all c files from a src/ folder and builds their objects to build/ and then links them all in one go. No need for me to specify the files. It also works recursively. [1]: https://pastebin.com/b1tr9th3 https://pastebin.com/b1tr9th3
- DanHulton 9y agoA tiny improvement that could be added - instead of locating Babel by adding your project's `node_modules/.bin` to your path or directly linking to it, you can always write: `npx babel` This will use any installed version of babel in your node_modules, or, if not installed, will temporarily install it for the duration of the command.
- cesarb 9y ago> or, if not installed, will temporarily install it for the duration of the command. Wait... doesn't that make typosquatting even more of a danger? People get used to typing "npx <command>", they mistype the command once in a while, an attacker uploads packages named after the most likely typos, and done - the attacker wins. I question the wisdom of that shortcut.
- dblotsky 9y agoThank you. It's nice to know that I'm not alone in this dark, dark world. It's so depressing when people use arguments like "it's old", "it uses tabs", and "it's hard to learn". As described by one Peter Miller, "Make is an expert system". If a tool is the most powerful, standard, and expressive among its peers, its age or the fact that it uses tabs should be inconsequential. If anything, the fact that it's decades old and used in every major software project is a testament to its effectiveness, not a drawback. And if "learning Make" is a barrier, that to me is a sign that someone cares more about complaining than about their project. The same way people learn Git when it's clear that it's the best tool, people learn Make. It really isn't that hard. Even the basics are enough to reap huge benefits immediately.
- hungerstrike 9y agoThe tools are not the same on every platform. That’s reason enough for me to not use it with my JavaScript projects. The bigger reason though is that it’s not very idiomatic for JavaScript projects to use Make. It sounds like the only reason that some people go out of their way to use it is because they actually don’t want to learn something.
- dblotsky 9y ago> "The tools are not the same on every platform." Any common examples? > "It’s not very idiomatic for JavaScript projects to use Make." While I agree that popularity is a factor in picking a tool, it shouldn't be a deciding factor. Going by popularity is precisely how we end up with a new Build System of the Year(TM) every few years. The fact that we've gone through 4 fairly prominent tools (Gulp, Grunt, Broccoli, Webpack), all of which contending to "fix" the previous, and none of which have proper DAG or incremental builds (which Make has had for decades) is damning evidence. In other words, I think Make could be (and I wish it was) idiomatic for JS.
- hungerstrike 9y agoThis comment points out the kind of problems that can occur just on Unix systems - https://news.ycombinator.com/item?id=16485637 https://news.ycombinator.com/item?id=16485637 And then there’s Windows... Anyway, the fact that things change quickly in JS-land is more of a testament to how popular it is than anything else IMO. If C were used in the same environments as JS, I’m sure that you'd see just as much churn.
- lykahb 9y agoMake has dated syntax and conventions. When developers use emojis in command line, support for the spaces and other quirks look worse than a decade ago. Despite all of its expressive power and speed, Make is not going to attract many frontend developers. If the concepts behind Make are repackaged in a more hipster way, the resulting tool may get far more appeal. Shake https://shakebuild.com https://shakebuild.com is a build system library that can naturally express even the dependencies that require Makefiles go meta and generate new Makefiles. It can be a robust backend for any build system DSL.
- monsieurbanana 9y agoI like functional programming languages and Haskell is something that interests me. But you can't be serious when you say that make is out-of-touch with the average frontend developer, and then link to this: https://shakebuild.com/manual https://shakebuild.com/manual
- lykahb 9y agoI suggested making new build system that has the power of Make or Shake and is still oriented toward frontend development. You are right that Shake and most general purpose build tools are out-of-touch with frontend. Even for people who are comfortable with these tools, they are not necessarily better than Webpack for the typical frontend tasks. Shake place in this hypothetical tool will be at its backend - like LLVM is the backend of many compilers.
- drablyechoes 9y agoI have used Makefiles for a lot of little things over the years. One of the latest things I have found it useful for is automating deployment of websites via Jenkins jobs. It is a lot easier and more manageable if your Jenkins job is set up to just run a series of generic Make commands for a project, where any specific steps for a particular project are defined in the Makefile. This way I do not need to know or care about how any particular project or site is built when configuring the job to deploy it. The Makefile takes care of all that.
- benkbit 9y agoThe thing I like about Makefiles is the declarative structure you get by defining the targets. It really can serve as a form of documentation about your different stages of development.
- mikegerwitz 9y agoI use Automake and Autoconf (which generates the Makefile) for GNU ease.js: https://git.savannah.gnu.org/cgit/easejs.git/tree/Makefile.am https://git.savannah.gnu.org/cgit/easejs.git/tree/Makefile.a... https://git.savannah.gnu.org/cgit/easejs.git/tree/configure.ac https://git.savannah.gnu.org/cgit/easejs.git/tree/configure.... The nice thing with using Automake is that it gives all the standard build targets with little additional effort (for example, `make dist` for producing the distribution tarball, and `make distcheck` for verifying that it's good). I use a much simpler one for a project at work: https://gitlab.com/lovullo/liza/blob/master/Makefile.am https://gitlab.com/lovullo/liza/blob/master/Makefile.am https://gitlab.com/lovullo/liza/blob/master/configure.ac https://gitlab.com/lovullo/liza/blob/master/configure.ac
- balls187 9y agoUsed make for building javascript bundles back in 2013. Worked incredibly well.
- tutuca 9y agoI find the editorialized title a little bit harsh on author's intentions...
- kraig911 9y agoA lot of good arguments about using and not using make. Count me in the not using make camp. IMO it's just simply overkill. JS work nowadays is so modular if we were talking about configuring a monolith service at build time... sure yeah. Meanwhile I just wanna make this div purple.
- codazoda 9y agoI presume you're running simple small js files. This post is about larger projects that need to transpile newer js code down to browser compatible code, combine multiple files into 2 or 3 http requests, and pack every possible byte out of the js resources we end up sending to clients.
- kraig911 9y agoYup I'm a JS Dev and I use webpack (3). I get the entire thing. However I think this is still all so complicated for no sake but for a small benefit. I'm currently looking for a tool to find out how much is seen/used vs how much is delivered.
- blt 9y agoI'm baffled at the amount of debate in this thread. Make is good for tasks that can be expressed as a directed acyclic graph of steps, where the steps' inputs and outputs are files, and steps can be expressed in a few lines of shell script. It works pretty well for such tasks in my opinion. Yes, it will look contorted for tasks that don't fit this model.
- jiaweihli 9y agoI went through a Makefile phase but ultimately setting on Jakefile[1] for more approachable syntax and type-checkability via TypeScript. [1] https://github.com/jakejs/jake https://github.com/jakejs/jake
- wruza 9y agoFor me, the problem with all make replacements is that they don't just solve makefile's issues in knowledge-compatible way, but reinvent their own cryptic syntax and structure from scratch. Minor issues that you know about (and know how to avoid) are never worth fixing in this way, since most people don't have time to learn infinite variations of superior tool #1 that has its own flaws. They are fine with #2 that works for them. When someone says "there are numerous alternatives", I just look out the window and smile. Almost all issues mentioned itt can be solved in barely-compatible, but easily transition-able way. If this tool exists, its name is welcome.
- pankajdoharey 9y agoI find NPM script parameter as the most reasonable build tool. You can write any kind of shell commands or invoke shell or other scripts in javascript script into it without learning the strange syntax of Make.
- deadcoder0904 9y agoMake is awesome. I often did things with it earlier however now if I want to do something with NodeJS I generally use npm scripts tag. And sometime it gets tedious to do so then I use nps [0]. If I need something big then I go with Webpack or Parcel. [0]: https://github.com/kentcdodds/nps https://github.com/kentcdodds/nps
- piano 9y agoWhy is it that each time a JS dev discovers something most other fields have been using for decades, it has to be "The Lost Art", "Superpower" (https://medium.com/@wesharehoodies/typescript-javascript-with-super-powers-a333b0fcabc9 https://medium.com/@wesharehoodies/typescript-javascript-wit...) or something similarly tacky? There's no Lost Art, no superpowers. It's just the JS scene _finally_ slowly getting up to speed.
- Klathmon 9y agoWhy is it that some commenters can't understand that all of humanity isn't at the exact same level of knowledge on everything? People learn things every day, acting like it's "slow" or you are better than them is a very toxic elitist point of view that is better off not said. You think your way of doing things is better, then you should encourage others to do it that way, don't put them down when they just start using it! I'm glad the ALGOL programmers of the 60's and 70's didn't spend their time laughing and putting down that new-fangled C language when it inevitably made some of the same mistakes. And besides, very rarely is something in life a complete upgrade. Make is nice, but it has some very real pain-points (as evidenced by the handful of utilities that are makefile-generators, because getting make to do certain things or work on all platforms is so difficult). Gulp is great too, but it also has some very big issues in some areas. There is no universal "right" answer to any of this, and assuming that everyone that's not doing it your way just doesn't know any better isn't just naive, it's also wrong.
- piano 9y ago> People learn things every day, acting like it's "slow" or you are better than them is a very toxic elitist point of view that is better off not said. You must've misunderstood me. I don't have any problem at all with people discovering things late. I am often a slow learner myself. What irritates me is when people make spectacular "discoveries" with tacky headlines. If the article were written in a bit more casual and technical tone, I'd be happy, much more so than with this "let me re-introduce you this amazing but forgotten lore you don't know about" nonsense... > And besides, very rarely is something in life a complete upgrade. Make is nice, but it has some very real pain-points I agree, but that's all the more reason to not make such "discoveries" ...
- Wintamute 9y agoHowever expressive or standard on other platforms, Make is not the correct tool for building web projects. Putting aside fundamental technical differences between Make and say, Webpack (of which there are many) there needs only one argument: Make is not idiomatic on web projects. Most web developers are not going to be productive authoring or maintaining a Make build process. If this guy wrote a Make build process while working for me, I'd ask him to rewrite it using Webpack.
- commandlinefan 9y agoI like this a lot. We preach the mantra of reuse all the time, but we practice it so rarely - writing everything from the ground up every few years rather than trying to fit the existing tools to the new(er) processes.
- s_chaudhary 9y agoI searched and didn't find a single soul using Makefile to orchestrate a set of build steps. I have been doing that for a long time: `make test`, `make build_docker`, `make push_docker`, `make deploy`. Now suddenly everyone shows up in one place here. Long live HN.
- dblotsky 9y agoApache Cordova's site and docs, although currently using Gulp, have a Makefile that mirrors the Gulpfile, and which nobody uses. :(
- grimgrin 9y agoI learned a lot from this, and whether or not one should be doing this, I simplified: https://github.com/shmup/react-makefile/blob/master/Makefile https://github.com/shmup/react-makefile/blob/master/Makefile I opted out of checking for modification dates on node_modules and yarn.lock, because that seems like exactly what Yarn itself is for. I let it manage itself. I also let Webpack do the heavy lifting. So in short: I don't really need the Makefile at all and could just add the clean and dev-server commands to a script block in package.json I still like it though