Ask HN: Am I a bad person for not using Make?

19 points by travisgriggs ↗ HN
I maintain a small handful of embedded C projects. Originally, I copied a Makefile from somewhere and did the standard thing with it. For basic dependency tracking, it's pretty straightforward of course. But every time I needed to do something "different" I had to go chase down how to do that (autogenerating a versions.c file for example).

I don't remember at what point I snapped, but on one of these sojourns, I thought to myself: "The basic problem I'm solving here is driving gcc compile/link phases. I know how that works well. I want to do as little as possible. I know Python really pretty well, and I can generally get it to do anything I want. Why not just write a python script to do this? I'm tired of trying to figure out how to make do one more thing with .phony or whatever. I've got enough languages/systems/frameworks in my head already."

So that's what I did. Took an hour or two to write it. It's ~200 lines long. It does fast threaded dependent builds. In addition to compiling, it does various other side related tasks. Peers have taken it and tweaked it multiple times to do interesting things. I just got tired of those Makefiles that evolve and over time, there's only one guy that understands it anymore. It's served us well for years.

Am I the only developer to ever take this road less traveled?

18 comments

[ 2.9 ms ] story [ 48.8 ms ] thread
It is called KUBERNETES!

Come get you some awesome k8ness in your soul. Come commit time and effort to helping us solve yesterday's problems, today... again!

Google 'maven for c++' and you'll find many others have gone down this road. I'd checkout some of the work that's been done in this matter just so you don't have to maintain your own make system. Good luck!
There are also other build alternatives. Cmake comes to mind.. There's a new(ish) one that the gnome project is using now (also written in python): m..something.

Anyway, rest easy. You aren't the first. You won't be the last. (my favorite: someone released a /bin/ls clone in go recently)

I've done it. I have a large project that involves generating .cc and .h files from other files. I wrote a custom script in Javascript (for node.js) that drives the build process, and it handles all the dependencies and parallel builds.

One tricky part was getting the header dependencies right. I run the compiler with -MD and it outputs a .d file listing dependencies, which my script parses.

I wish there were a simple library to build this kind of stuff on top of. Often you need a real programming language (which Make is not) and parallel dependency tracking (which is tricky to get 100% correct when you write it from scratch each time.)

You're a very long way from the only developer to take this road, and it's a road that's very well traveled indeed.

Writing your own build tools seems to be an attractor task for programmers. Every year there are a few more build systems made public by eager developers who started simply by solving their own problems; almost every one of them having started life as a lash-up of scripts by frustrated programmers just like you. I suspect the number of people who have ever traveled as far along this road as you have so far numbers in the millions.

Yes, I was attracted to it. If nothing else, it made my Python skills that much fuller.

Its never something I wanted to turn into a reusable solution though. I have 3 of these right now, each time, I took the old one as a starting point, and then changed to match the newer needs (and only those specific needs) and maybe whatever was my latest approach to solving.

For me, the utmost guiding principle has been to keep them simple so that someone can casually tweak/change it with not too much work.

I've worked in automation (food processing, nuclear manufacturing, and agriculture) for a lot of years. One thing I've discovered is that while you can automate everything in the real world, there really are some parts of the process where an adaptable human being is the best tool for that particular part of the process. I've viewed these efforts in a similar vein.

I don't blame you for not using Make (It's nice and easy only in cases that are too basic for real-world projects. Once you start supporting out-of-tree builds, configurable components, portability, etc. it grows into something tricky and fragile).

However, I'd suggest using another existing build system rather than inventing a millionth-first one. It's easy to make 95% sufficient build system, but the effort to reach 100% is asymptotic.

In one project I refused to touch autotools, and hand-crafted my own ./configure script. It seemed simple at first, and ended up being a time sink. I've been getting bizarre bug reports about broken platforms where /dev/null doesn't exist, grep doesn't understand basic flags, /tmp/ is read-only (why do you hurt yourself like that!?). If you make your own build system, all of it it becomes your problem that you'll reinvent it like everyone before you.

The only problem is that no matter which build system you choose, you'll find both people who think it's the only right choice, and people who insist it's total garbage and they will never touch it.

You should use the tools that work best for you. If your Python script is that, then I say that's excellent, run with it!

Myself, I've moved through trying several different make replacements (including custom-built ones) but moved back to make a couple of years ago. It offers benefits that matter in my situation that I've not been able to reasonably find elsewhere.

I did a similar thing with static site generators. They annoy the hell out of me and knocking something up in NodeJS, using libraries like fs-extra, marked, moustache etc. 100 lines JS is understandable and infinitely more flexible than whatever your static site generator has me locked into.
I recall a hearing a seminar a few years ago by a computer scientist, about getting physicists and other non-CS people to write better software. He mocked one physicist who had defined a shell file called "make" that simply contained the one line

  cc *.c
How clueless can one be?

Except... that's a perfectly reasonable approach to compiling your program if it's small enough that this takes only a few seconds - ie, if your program has no more than about 50,000 lines of code - and there's nothing more complex to be done than compile a bunch of C source files. Physicists have better things to do with their time than learn about "make" just so they don't get mocked by computer scientists.

Something I've done in the past is treated Make like a well-known API. Even if the logic is in separate scripts, I still implement a simple Makefile with common targets like "build", "clean" and sometimes "install". This allows people picking up your project to build it and work with it right away, without having to understand the details of the scripts.
I maybe a contrarian, but i really hate custom made build tools. They contain a lot of "black magic"(no documentation nor community help) and are difficult to debug and extend. I think it is much better to stay with standard build tools. Time spent in learning them is well worth it.

In your case i might have gone with SCons+distcc+ccache rather than a custom made one.

I hate having to use custom build tools made by others, and I agree with you if we're talking about code that is going to be distributed.

But for personal projects that aren't intended for use by the rest of the world, I don't see any problem with them. Back when I played with custom build tools, I split the difference and made sure to implement a means to export a makefile equivalent. (Since then, I've moved back to just using the standard tools).

I switched from make to mk and never looked back.

The syntax is saner. It took some time to learn it, but typing `mk` instead of `clang --many-flags-I-do-not-remember` is so much better.