Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Make is a great tool for automating simple things, but if you use a programming language you should probably use native automation tools for common tasks. If you have any non-trivial logic or want to enable code-reuse make doesn't seem like the right choice either.


I hate this. Every programming language that bolts on its own build environment. Make is language agnostic and that's a huge benefit, it means you have to learn about just one build tool and its peculiarities and that will allow you to build many different projects in different languages.

All these languages with their half-baked build tools that won't accept that they may have to play nice with other languages and their build tools are not helping.

Of course it is great when you write a language to also throw in a build tool, but in the end if the build tool re-implements 30% or so of make in a broken way I don't see the point.

Make does have its limitations, but most ordinary projects get nowhere close to reaching those.


> Of course it is great when you write a language to also throw in a build tool, but in the end if the build tool re-implements 30% or so of make in a broken way I don't see the point.

Well, other build tools sometimes also do a lot more than make ever did. (And in some areas, perhaps less.)

Example: Cabal/cabal-install (for Haskell) can automatically fetch all your project's dependencies and automatically compile them for you.

> Make does have its limitations, but most ordinary projects get nowhere close to reaching those.

I suppose it depends on what you mean by "ordinary", but IME this Makefiles by virtue of being purely file-based is useless for most of my projects. There are a many langauges (e.g. Java/Scala, Haskell) where it just doesn't fit for normal development. As an example: Tracking intra-file dependencies for proper recompilation is really difficult to for Scala code without reimplementing a huge chunk of a Scala compiler. (I'd venture to suggest that you'd be foolish to even try doing this in Make.)


> Tracking intra-file dependencies for proper recompilation is really difficult to for Scala code without reimplementing a huge chunk of a Scala compiler.

tup (http://gittup.org/tup) has a really nice way of handling interdependencies. They set up some filesystem magic to figure out which files were read while compiling a certain target, and record these files as dependencies for the target.

Another instance of a hard problem ("reimplementing [...] a Scala compiler") that turns into a very easy problem once you look at it from the right angle.


I love tup so much. It's a "functional reactive" build tool that practically nobody's heard of, so I'd argue that it's even more "hipster" than make (whatever that means).

When I decided I needed a single build system to replace a hodgepodge of stuff, I looked at make because that was apparently the go-to thing.

It took me about 2 minutes to decide that I wanted no part of make. I'd assumed it was basically what Tup is. I'm lucky that I learned about Tup from a thread on this site, because it's made me so happy (especially once the initial pain was over... and yeah, you have to change).

So whenever I see these posts, I make sure that someone is mentioning Tup as a clean alternative.

edit: to be explicit, Tup is obsessed with speed and correctness, and handles incremental builds optimally (see Mike Shal's whitepaper on this). The "price" is that you can't modify files during a build. A file is either "regular" (not touched by build) or "generated" (produced wholly from one build rule). You have to describe the complete DAG up front. Because of all this, Tup will actually remove build targets when they're not needed, which I believe no other build system does. I could never go back.


The only practical problem with tup is that it's not make, which creates friction for packagers. And since I'm doing some packaging work myself, I'm heavily optimizing for packager happiness.


Sure, tup is very nice, but it doesn't solve the problem in a way that leads to anywhere near efficient re-compilation on small changes (for Scala, at least -- it might be workable for Java). For that you need something like zinc[1]. This is because the dependency units in Scala don't map cleanly to files.

> Another instance of a hard problem ("reimplementing [...] a Scala compiler") that turns into a very easy problem once you look at it from the right angle.

Only if you don't solve the problem fully. TBH, not even zinc solves the problem 100% and sometimes does a little bit of unnecessary re-compilation. It is very good, though.

[1] https://github.com/typesafehub/zinc


> Make is language agnostic and that's a huge benefit, it means you have to learn about just one build tool and its peculiarities and that will allow you to build many different projects in different languages.

You need to learn the Make build tool (easy) and then you need to learn bash scripting to get anywhere (argh!).

The OP has linked an example Makefile and I wouldn't be able to maintain/debug it without reading plenty of manpages:

https://github.com/Financial-Times/n-makefile/blob/master/Ma...


I am not sure if you can get rid of some those commands with any other build tool. There is simply no build tool that includes everything, so sometimes some scripting will be required. Then, why not go with bash that you hopefully already know?

Also, a lot of the complexity is due to him being new to make:

    asset%:
    	@if [ -e webpack.config.js ]; then ... fi


... which is of course addressing make as merely a "build tool" for "projects".

One of the normal conventions for Daniel J. Bernstein's tinydns is to use make. No "projects" or "builds" are involved. The goal is not to create a program. Rather, make is used to ensure that the binary form of the DNS database is re-built whenever the system administrator has edited the text form. The administrator simply has to remember to run "make", and the Makefile re-builds, and atomically publishes, the new DNS database.

The simplest makefiles are of the scale exhibited at http://cr.yp.to/djbdns/run-server.html

But one can create significantly more ambitious makefiles than those. (-:


Notice how in the article nothing is "built", all that happens is an npm install. It sounds like make is used to manage a project and perhaps do things like running unit tests, pushing code to stage/qa/prod, fetch data from remote hosts to test locally, running linters and code analysis tools, generating assets, and many more.

Is make the right tool for executing such tasks? Well, it's not bad for some I guess, and ok if this one project is all you have.


That's true, but it also leads to bloated special purpose tools that take minutes to run, as described in the introduction of the article.

Sometimes you've better off having something that does exactly what you need, regardless of speed. Sometimes you need something fast, lightweight, ubiquitous, and reliable despite its quirks.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: