The villagers cried as the warlord Cabal and his troops burned their homes.
Some of them were trying to quickly rebuild a small shelter to protect themselves from the bugs outside. It was such a simple piece of work, Cabal shouldn't need to know about it, they thought. But Cabal's troops found them and promptly knocked it down.
"No program is allowed to exist unless it was built by Cabal!" the warlord shouted. "Burn them all!"
"Build systems" shouldn't exist. A compiler should be able to compile the damn code.
There are three problems that need to be solved to build code: compiling the source, finding the source files, and package management. The first is clearly a compiler's job. The last is clearly a package manager's job. The middle problem is small and does not call for a separate tool with its own config files.
Here's how it ought to work:
Source files within a project reference each other by relative paths.
Dependencies on other packages use a different syntax, like how C include works. The compiler searches for these in standard directories. Sandbox environments can be handled with something akin to
But this isn't how it works. Few or no languages handle dependencies so elegantly. The C ecosystem revolves around
make, by which I mean the different GNU, BSD, and Microsoft
makes, each of which is basically a separate language, and
pkg-config, because what did you think you could just import an installed package and use it?
And you can't get far without running into the surreal mess called GNU autotools. Who doesn't like a bunch of 3000-line files with weird names involved in their build process? Who doesn't want to debug that?
And what's this CMake thing? Wait, it's not a dialect of
When I submitted my patch to GTK to fix a GObject Introspection annotation, I wanted to compile GTK after my change first, because I was terrified of how I'd feel if I submitted a patch that broke the build, as sure as I was that that was impossible. I spent about 12 hours trying to do so before giving up. The quest led me through installing Meson, Ninja, hunting down dependencies manually after each failed compilation informed me of another one, googling cryptic error messages and reading old mailing list archives, trying on an Ubuntu system after giving up on the FreeBSD one, and finally deciding I'd just submit the merge request and hope it worked (it did).
While GTK was the worst, most C projects I've worked with have given me huge trouble building them.
Python and Go are pretty straightforward; neither really has a "build system" (Python does have setuptools, but you don't need it just to run a project).
go build builds your project, even if it's complicated, or you just run the Python file (after fiddling with some
__main__.py crap for a multi-directory project).
Haskell and OCaml are even worse than C. With these ML family languages, it seems like the compiler was never meant to be usable on its own. So people wrote a dozen different tools to wrap the compiler so you can actually use it. All of said tools introduce their own problems, so you still can't actually build anything with them, and the solution is always to install and use another tool on top of it.
ocamlopt is the native code compiler (
ocamlc is a bytecode compiler and
ocaml is an interpreter).
dune is the "build system".
opam is the "package manager". Then what are
ocamlbuild, you ask? I don't know, but they're involved in some tangled way. All the documentation is out of date and nothing they say works.
Str module apparently requires explicit linking. If you're using
ocaml, you can load it with
#load "str.cma";;. But that directive is invalid syntax to
ocamlc, which want command-line arguments instead - different ones.
This is madness. We shouldn't need this much complexity just to write some code. Compilers should just work.
PS: If you're going to tell me my demands are unreasonable, include an explanation of why other languages can't do what Go does.