Live data from Hacker News

The Language Agnostic, All-Purpose, Incredible, Makefile

blog.mindlessness.life

21–30 of 124 posts

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#21

I rely heavily on makefiles, but the gotchas lurking in make syntax are many and severe: http://www.conifersystems.com/whitepapers/gnu-make/

Note that the author of that paper (a friend of mine) wrote another build system, the dead-simple-but-awesome make.py. I have a mirror/fork of it[0], since it's been unmaintained for a while (but it mostly doesn't need any maintenance).

The entire build system is a single Python script that's less than 500 lines of code. Rather than trying to fit complicated rules into Make's arcane syntax, rules are specified with a Python script, a rules.py file (see [1]). But the script should be thought of more as a declarative specification: the rules.py file is executed once at startup to create the dependency graph of build outputs, and the commands to build them.

Yet, despite the small size, it's generally easier to specify the right dependencies, do code generation steps, and get full CPU utilization across many cores.

At some point I'd like to write more about make.py and try to get it used a bit more by the public...

[0]https://github.com/zwegner/make.py [1]https://github.com/zwegner/make.py/blob/master/example/rules...

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#22
post #18
post #17

Earlier quoted context omitted.

Not sure what you mean by "Make does not handle multiple targets". You can definitely do `make foo bar` and it will run the recipes for both foo and bar. You can also write a recipe with multiple prerequisites (which could be the result of a variable expansion). Curious about the limitation; could be there's a way around it or that I never ran into it.

The poster is talking about a single command that generates multiple outputs. e.g. a codegen tool that generates "foo.c" and "foo.h"

Isn't the solution to that problem simply to use stamp files

You declare foo-stamp as a dependency of both foo.c and foo.h. foo-stamp itself is dependent on the file used to generate those foo.* files. The recipe for foo-stamp invokes the code generator which updates the files, then you `touch foo-stamp`at the end of the recipe.

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#23
post #2

Make is great, and I wish more people would use it in place of whatever monstrosity is en vogue this week. However, there is one thing which Make absolutely cannot handle, and that is file names with spaces . If you have any risk of encountering these without any possibility of renaming them, you’ll sadly have to give up on using Make; it just won’t work.

Make is useful and the concept is sound.

However, the implementation is dated.

Just off the top of my head, it could be object oriented (rules could be subclassed), the language could have more sophisticated statements, it could have debugging, etc

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#24
post #19

Make is very programmable; here's something from our code base: # Yes I am aware that this looks like TECO and Prolog had a baby. $(foreach prog,${3P-nonboost-packages},$(patsubst %,3P-build-%/${prog},${MAKE_CONFIGURATIONS})): 3P-src/$${@F} $(patsubst %,toolchain-%/_env,${CONFIGURATIONS}) @echo Building ${@F} for $(subst 3P-build-,,${@D}) @mkdir -p $@ @if [ -f "$ This is after extensive simplification.

Make was what really drove home the concept of "developer time" for me, when after spending a quantity of time learning more Makefile tricks than I knew before and fixing the Makefile for our C/C++ code to handle header files correctly so that I would stop having to run make clean constantly, I realized that the Makefile cost the company ~$1000 for me to write. I'd like to think it saved the company more than that in future dev time, but it was still startling to me to realize that by deciding to rewrite the Makefile I had effectively decided that the company should spend $1000 on a build config.

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#26
post #20
post #18

Earlier quoted context omitted.

The poster is talking about a single command that generates multiple outputs. e.g. a codegen tool that generates "foo.c" and "foo.h"

I'm still not understanding the problem (sorry for being obtuse). If you have a program called `makes-two-files` you could have a recipe: foo.c foo.h: predecessor_of_foo @makes-two=files foo There are other ways to do this in Make as well. I use Make extensively to drive CMake which makes all sorts of products, so my confusion comes from thinking this works fine (works for my purpose, obviously, but I'm interested in…

Consider:

    foo.c foo.h: foo.in
            some-tool foo.in
If you have some targets that depend on foo.c and other targets that depend on foo.h and you build in parallel, some-tool will run twice, possibly at the same time as something is reading the output, possibly causing problems.

[edit]

The workaround I've used is something like:

    foo.c: foo.in
            some-tool foo.in

    foo.h: foo.c
            true
Note that the "true" command is important because GNU make will search a library of implicit rules if you have no recipes for a particular target.

In general multiple output files are even harder with some make replacements, because most make replacements try to be smarter about build outputs. redo, for example cannot handle this, but tup can.

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#27
post #7
post #2

Make is great, and I wish more people would use it in place of whatever monstrosity is en vogue this week. However, there is one thing which Make absolutely cannot handle, and that is file names with spaces . If you have any risk of encountering these without any possibility of renaming them, you’ll sadly have to give up on using Make; it just won’t work.

I agree, and the solution to this problem is to forbid filenames with spaces. The convenience of make and similar tools is much more important than spaces in filenames. File names with spaces should not be allowed in modern filesystems. When the user types a filename with spaces, the GUI should encode the space as a non-breaking space character, that does not cause havoc in scripts.

> the GUI should encode the space as a non-breaking space character

At this rate, why can't the tool itself escape the spaces from the filenames into non-breaking-spaces before processing?

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#28
post #26
post #20

Earlier quoted context omitted.

I'm still not understanding the problem (sorry for being obtuse). If you have a program called `makes-two-files` you could have a recipe: foo.c foo.h: predecessor_of_foo @makes-two=files foo There are other ways to do this in Make as well. I use Make extensively to drive CMake which makes all sorts of products, so my confusion comes from thinking this works fine (works for my purpose, obviously, but I'm interested in…

Consider: foo.c foo.h: foo.in some-tool foo.in If you have some targets that depend on foo.c and other targets that depend on foo.h and you build in parallel, some-tool will run twice, possibly at the same time as something is reading the output, possibly causing problems. [edit] The workaround I've used is something like: foo.c: foo.in some-tool foo.in foo.h: foo.c true Note that the "true" command is important beca…

Ah, now I understand the problem, thanks!

Indeed I've stayed away from -j because it's very hard to figure out how recipes may interact when you have a complex Makefile (and with a simple one -j rarely helps much).

I like your fix; even without -j, if some-tool is expensive to run you don't want it run redundantly.

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#29
post #9

Make is great as a dependency resolution engine. For everything else, it is absolutely horrible. What I typically do is use make only for what it is good: as a dependency resolution back-end. All the build logic for my projects is written in Python, in an executable file stored in the project root directory and called "make" (I have "." in my PATH). The Python script, when it runs, generates on the fly a clean, lean,…

Could you provide an example of this (or point me to a repo where you use it)? It sounds neat

Re: The Language Agnostic, All-Purpose, Incredible, Makefile

#30
post #21

I rely heavily on makefiles, but the gotchas lurking in make syntax are many and severe: http://www.conifersystems.com/whitepapers/gnu-make/

Note that the author of that paper (a friend of mine) wrote another build system, the dead-simple-but-awesome make.py. I have a mirror/fork of it[0], since it's been unmaintained for a while (but it mostly doesn't need any maintenance). The entire build system is a single Python script that's less than 500 lines of code. Rather than trying to fit complicated rules into Make's arcane syntax, rules are specified with a…

If you haven’t seen Bazel, you should take a look.

It’s definitely not as minimalist, but it has a very, very similar model for specifying the build. In me experience, it’s pretty easy to get going, and it makes it pretty hard to screw up any of the important features of the build.

Post reply on HN