Hi Chris, I know you're an advocate of Make, but I'm curious if you've had a look at Meson/Ninja and, if so, if you had a "review" of them? --Harris
Interesting question, Harris. Since Make has served me well enough all these years, I haven't had much reason to look at Meson or Ninja. I don't like dependencies, even build dependencies, that don't bring something substantial to the table. Make is a standard development tool with multiple, independent implementations, and so, in practice, it's not really a dependency. Like, say, a text editor, it's safe to simply assume it's present alongside a compiler, even on Windows. I include Make in w64devkit after all, so there's really no excuse not to have it on hand when building my software. I was aware of Ninja due to it being an output option for CMake, though I've never used that feature. It's written in C++, which is reasonable enough for me to consider it. Though Ninja is low level in the same way Make is low level, so it's not bringing anything new to the table. It claims to be faster, though that won't apply to the way I build software, where Make already consumes less than 0.01% of the total build time (full build), and only a couple of milliseconds when there's nothing to do. The website says you're not really supposed to write Ninja build files by hand, and it's intended to be generated by yet another build dependency (CMake, Meson, etc.). So I see no benefits versus Make, just the cost of an extra dependency and an unconventional build interface. When I've run into projects using Meson, my reaction has always been to roll my eyes and bypass Meson, manually invoking the compiler on the source files. These projects have always been simple enough that they don't even need much of a build system, let alone an esoteric one. Looking more closely at Meson now, I see its written in Python. This is an inappropriate implementation language for a build system, and more than enough reason enough for me to never touch it. A build system ought to be written in a systems language. If I depend on Meson, then I also transitively depend on a full Python interpreter and package system (to install Meson) since the Python community has yet to solve distribution / delivery. Fortunately Meson doesn't have further Python dependencies of its own, so at least it's not nearly as bad as it could be. Trying it out some existing Meson builds listed on their site, I see it makes a common mistake with CMake: The output build scripts contains absolute paths to the project itself. A consequence is that I can't mix tools with different views of the file system. For example, tools running in Cygwin or Msys2 see different paths than native Windows tools, so they may be confused when invoked by Meson or CMake builds from the other system. This was at one point a deal-breaker for me with CMake. Though it seems Meson uses relative paths more than CMake, so maybe in practice it's not an issue. The only build system I've ever liked more than plain old Makefiles is "go build". Unfortunately it's too late for C and C++ to have something like that — the ecosystem has been fragmented into incompatible ways of doing things for far too long.
> Looking more closely at Meson now, I see its written in Python. This > is an inappropriate implementation language for a build system, and > more than enough reason enough for me to never touch it. For what it's worth you're not the only one to feel that way. There is a C implementation of meson on sourcehut that seems to be actively developed: https://sr.ht/~lattis/muon/ Obviously that doesn't change the value proposition of why you'd use meson instead of make, but it does help cut an unnecessary python dependency. Harry
Good review. I hadn't realized that Meson was written in Python. I generally agree with the points you make in your email, but I also feel that Make has a few deficiencies... having a separate build directory and source directory, for example, is more difficult than it should be, and supporting the cross platform use case more or less requires you to have more than one makefile (in fact if memory serves, you made the same point in one of your articles on makefiles). ... I'm not sure I'm bothered enough by Make's deficiencies to write my own build system, though :) Harris
> There is a C implementation on sourcehut
Thanks, Harry, I wasn't aware of this. That's more reasonable, and it's
healthier in the long term for Meson to have multiple implementations.
> having a separate build directory and source directory Yup, Make is far from perfect, and it doesn't make this easy. As is the case for most GNU Make extensions, its VPATH extension is too poorly designed to improve this situation even for GNU Make. When I've had projects grow large enough enough that maintaining a Makefile becomes difficult, and I still care about incremental builds, I hand-write a shell script to drive GCC -MM -MT over the source files, automatically handling the header dependencies, and covering cases like out-of-source builds since I can brute force the rules (vs. relying on Make's limited inference rule matching). That script is essentially doing the same work as CMake or Meson, but at a fraction of the cost and with more flexibility. None of my open source projects have ever become complex enough to warrant that treatment, so I can't point to any of my real world examples, but I put together an example for Enchive just now: https://gist.github.com/skeeto/b07bbfbf8ec7d4075685e8e9f0a7a888 I check in the generated Makefile so that the actual build doesn't depend on the script or GCC in particular. (Also, running "gcc -MM" on Windows is painfully slow due to Windows' poor file system performance, so I like to avoid it.) > supporting the cross platform use case more or less requires you to have > more than one makefile Sticking to GCC or Clang, I can cover all platforms with a single Makefile since the compiler interface is essentially the same across all supported platforms. A past obstacle has been relying on unix utilities (esp. rm), which may not be present on Windows even alongside GCC and Make. This was a major part of my motivation for w64devkit, serving as a reliable, standard build environment on Windows without lugging Cygwin or Msys2. In my w64devkit guide from March, I mentioned my convention of using an EXE Make variable to automatically append an extension to the linked targets. This covers both the cross-compilation and w64devkit cases. I *do* use a separate "NMakefile" for interfacing with MSVC tooling, where I follow cl's unconventional (even for Windows) interface and only use Windows utilities (as painful as that is). See my "asteroids-demo" for an example. This is where something like CMake or Meson might have an advantage, covering both GCC/Clang and MSVC/clang-cl from a single build configuration. However, like before, I know how to use MSVC, and I'd rather do it myself and have full control even if I have to maintain a separate Makefile. My best solution for dealing with arbitrary, weird platforms is having an amalgamation build that concatenates all source files into a single source file / translation unit. Then, just as with SQLite, you don't need any build system: Simply invoke the compiler directly on the single source file. Enchive works like this, which is how I support all platforms and compilers from a single build definition. This is also a major feature of unity builds, though those have the additional cost of lacking fast incremental builds during development. Amalgamation is the subject of a whole new article I've been intending to write for awhile, but haven't gotten around to it yet.