Skip to content

Commit 138a450

Browse files
committed
Add new build system blog post.
1 parent db00200 commit 138a450

File tree

1 file changed

+130
-9
lines changed

1 file changed

+130
-9
lines changed

src/content/blog/2025-11-16-omg-what-a-mess.mdoc

Lines changed: 130 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,20 @@ author: Brian Shirai
44
date: 2025-11-16T12:01:00Z
55
---
66

7-
## D. R. A. F. T.
8-
97
*"Like fences make good neighbors, boundaries make good systems."*—Probably
108
Someone Famous
119

12-
If someone famous didn't say that, they probably should have, but I'll take
13-
credit so it's not just some anonymous thing floating out there like an orphan.
10+
If someone famous didn't say that, they probably should have.
1411

1512
But regardless of which precise words an LLM might use to construct such a
1613
sentence from the ruminations of billions of people, the idea is pretty simple,
1714
and profound.
1815

19-
I'd go so far as to say that without it, no life would exist. Because, in
20-
fact, this is precisely how life works. I learned that this probably has to do
21-
with how the ratio of surface area to volume of a cell changes as the dimenions
22-
of the cell grows and the need to transport energy materials and waste across
23-
that cell boundary.
16+
I'd go so far as to say that without it, no life would exist. Because, in fact,
17+
this is precisely how life works. I learned that this probably has to do with
18+
how the ratio of surface area to volume of a cell changes as the dimensions of
19+
the cell grows and the need to transport energy materials and waste across that
20+
cell boundary.
2421

2522
In the artificial (i.e. not living) things humans muster, there is not this
2623
obvious constraint, and so things like
@@ -31,4 +28,128 @@ this guy who told me, "I believe in monorepos' like they're some kind of
3128
middle-tier deity) long after they should be historical footnotes in obscure
3229
compsci trivia.
3330

31+
Alas, we soldier on...
32+
33+
## Building Complex Systems
34+
35+
Building complex software systems is hard, no question about that. How we
36+
choose to approach it offers quite a bit of latitude.
37+
38+
There are four audiences for a software component:
39+
40+
1. Core developers
41+
1. Contributors
42+
1. System maintainers / packagers
43+
1. End users
44+
45+
**Core developers** need sharp tools and use them often. They want quick
46+
development cycles, and they want to be able to merge contributions with
47+
confidence.
48+
49+
**Contributors** need an extremely smooth getting started experience and ease in
50+
adding their contributions.
51+
52+
Almost every flavor of Unix/Linux has its unique way of building and
53+
maintaining software packages for that system. System **package maintainers**
54+
want the least friction possible when packaging for their system. Usually, this
55+
means using as standard as possible build systems and parameterizing things so
56+
they can be customized to the system's approach without maintaining brittle
57+
patchsets.
58+
59+
**End users** want to install a package on their favorite system and get value from
60+
using a piece of software with as little effort as possible.
61+
62+
Among these four audiences, if anyone is going to suffer, it has to be the core
63+
developers. If the package managers have to deal with a lot of frustration,
64+
they will either hate you or just not support your package.
65+
66+
If contributors have to deal with a lot of confusing steps or cumbersome
67+
dependencies, they just won't waste their time.
68+
69+
If you don't have contributors and package maintainers, you will have very few
70+
users.
71+
72+
## Building Rubinius Before
73+
74+
Rubinius is not an easy project to build. It was entering an existing
75+
ecosystem, and some of the difficulty derived from that ecosystem.
76+
77+
For example, Ruby has an extremely complex encoding system that required a
78+
custom encoding engine that wasn't easily available as a system package or
79+
robust separate library. So, we had to maintain that.
80+
81+
These were all the "external" libraries that Rubinius vendored and maintained
82+
to make it as easy as possible for people to build the project:
83+
84+
* double-conversion
85+
* libffi
86+
* libsodium
87+
* libtommath
88+
* oniguruma
89+
* rapidjson
90+
* winpthreads
91+
* zlib
92+
93+
Since Rubinius started as an implementation of Ruby, and since Rake is a
94+
beloved tool used in the Ruby ecosystem, it made sense to implement the build
95+
system in Rake. We wanted the experience to be as simple as:
96+
97+
1. Clone [https://github.com/rubinius/rubinius](https://github.com/rubinius/rubinius)
98+
2. Run `rake`
99+
3. Enjoy!
100+
101+
Since Rubinius started using LLVM to implement the machine code JIT
102+
(just-in-time) compiler around LLVMv3 when there was very little system
103+
package support for LLVM, we also pre-built and hosted versions of the library
104+
for various operating systems.
105+
106+
These efforts were certainly not without merit, and Rubinius was pretty easy to
107+
work on. In fact, almost 400 people have contributed to the project.
108+
109+
But it was not pleasant for various package maintainers. Having Ruby as a build
110+
requirement caused a lot of problems. Vendoring libraries like zlib got us
111+
yelled at by maintainers, but for good reason. If projects like Rubinius vendor
112+
libraries like zlib, it makes it really hard for system maintainers to know
113+
that they've patched all the vulnerabilities in a specific library when they
114+
are discovered and fixed.
115+
116+
## A build2 Future
117+
118+
The [build2](https://www.build2.org) project "is a hierarchy of tools
119+
consisting of a general-purpose build system, package manager (for package
120+
consumption), and project manager (for project development)."
121+
122+
It's basically everything I wanted more than 15 years ago when I was wiring
123+
everything together with Rake and shell scripts, but they only started working
124+
on it about 10 years ago.
125+
126+
One of the most valuable aspects of build2 is that it implements a ["multi-repo
127+
first"](https://www.build2.org/faq.xhtml#what) approach.
128+
129+
The Rubinius language platform is made up of various components, some of which
130+
are maintained by other groups. The purpose of the new [build
131+
repository](https://github.com/rubinius/build) is to provide a way to build
132+
everything at once, while still maintaining the boundaries around the
133+
individual components.
134+
135+
The approach used here tries to strike a balance as follows:
136+
137+
* Keep boundaries as tight as possible: Don't vendor things that are separate
138+
components. Don't add significant build dependencies, like Ruby.
139+
* Keep build steps explicit and "accessible": Build steps are combined into
140+
build scripts invoked as make targets. They can be decomposed and recomposed
141+
in packaging systems without burdening the package managers with writing
142+
extra custom code. The more granular and standard, the more likely a system
143+
package manager can be easily configured for your project's "recipe".
144+
* Make it easy to clone and go, there should be no step 3. For example, clone
145+
the repo, type `make` or maybe `make help` and then `make`.
146+
147+
There's still work to do, but with the new approach, it's still as easy as:
148+
149+
1. Clone [https://github.com/rubinius/build](https://github.com/rubinius/build)
150+
2. Run `make`
151+
3. Enjoy!
34152

153+
Meanwhile, if you want to get Rubinius from a system package, the chances it'll
154+
be there are much greater because the experience for package maintainers will
155+
be nearly as smooth and simple.

0 commit comments

Comments
 (0)