Knit: Making a Better Make
zyedidia.github.io
zyedidia.github.io
This:
> I have to use hacks like .PHONY to mark rules as virtual.
makes me think not (.PHONY is required because fundamentally Make uses the filesystem as the "Store", or cache, for what is built, and rules just define Store targets)
It's been 5 years since the paper, and I'm still hoping for a a production-ready project that leverages its lessons to create an agnostic, distributed build system.
Nevertheless, excellent work in Knit! I'm always happy to see interest in the build system space. I particularly appreciate the use of Lua as the scripting layer. Make's scripting layer is certainly... limited. Also, great to see consideration for generated dependencies (like extracted header files)!
[1] https://www.microsoft.com/en-us/research/uploads/prod/2018/0...
https://beebo.org/haycorn/2015-04-20_tabs-and-makefiles.html
> BUSY is a lean, statically typed, cross-platform, easily bootstrappable build system for GCC, CLANG and MSVC inspired by Google GN
It uses lua and config files that are mostly directories and filenames.
Ah, this package looks nice, I'll have a look. What's a Knitfile? Oh, that looks quite cool; oh, so I need to install knit of course. Prebuilt binaries from the internet? Ha ha, no, better to build it. Oh it's in Go, so I need to install Go? Ah, a different package that does the same thing ...
This is a useful vignette, but I wanna pick at it a bit because at least sometimes, I don't see things going this way with me.
> oh, so I need to install knit of course. Prebuilt binaries from the internet? Ha ha, no, better to build it
Do you really see most devs thinking this? I don't, even though I'm someone who would build it myself.
> Oh it's in Go, so I need to install Go? Ah, a different package that does the same thing ...
I don't understand what the problem would be here. I maintain several out-of-tree Go packages for Nix for private use and all of them are trivial because Go packages are super easy to build. Are there really many devs out there who are so hesitant to build Go projects, of packages in all languages?
With C and autotools you may already have the toolchain installed, but it's generally harder to build than Go packages.
That way, there's very few prerequisites for a new dev to install (plus you have consistent build/test/run targets for all projects).
If someone wants to manage tools themselves (e.g, the no prebuilt binaries example), they can do that, then skip the Makefile entirely.
* There are fully static prebuilt binaries for a wide variety of platforms (including Windows, where I think it is actually more complicated to install Make than Knit).
* Knit can generate a shell script or Makefile for the build, so these can be used for users who don't want to do development but just want to build from source.
* It is easy to build Knit from source (thanks to Go). Yes you need a Go toolchain, but once you have that it is just `go install github.com/zyedidia/knit/cmd/knit@latest`. Of all the languages that could have been used, I think Go is one that makes the "build from source" experience very straightforward.
what?
just what?
just
what?
Just, as far as I know, does not support incremental builds. Just is more intended to provide a set of project-specific scripts that are convenient to list and run. Make is sometimes used in that way with "phony" targets, but that is more of an evolved usage. Make's original purpose was to allow for defining builds in terms of dependency graphs.
and, it cannot have multiple wildcard-patterns, like %xyz%, only single %xyzabc or abcxyz%, and this brings much complicatedness into picture..
$ ($name-(.*)-(.*)):RB:
GOOS=$match2 GOARCH=$match3 go build -o $match1
which is a metarule that matches targets like `$name-linux-amd64` and can be used for easy cross compilation with Go. Of course since it allows full regular expressions, even more complicated rules are allowed.If you're going to require installing another tool why not use one that fixes the "macro" problems too? Notably hermetic builds and dynamic dependencies.
E.g. Ninja has dynamic dependencies (IIRC). Bazel et al, and possibly Landlock Make have hermetic builds.
The recently announced Buck 2 has both.
Premake is also Lua based and while it does slightly different thing (generates VS,Xcode,gmake solutions) it may benefit from having direct build path - without creating make files and intermediate solutions.
Rake is fully programmable in Ruby. Just is a bit less flexible, but it doesn't require learning Ruby, and it's quite pleasant to use.
There was an article specifically avout that on the interwebs but I can't find it anymore. These ones cover some bits as well, although they're a tad heavier on using Ruby code.
So when you run a command it runs the dependencies then the commands, in full, every time.
I very much prefer that usually, because either the underlying tooling handles checking if all’s right or there is no such checking to do and it would be a problem.
But if you expect just to build your C project and handle not touching stuff which doesn’t need to be, you’ll be disappointed.