Bootstrapped Software Development (+OSes +languages +rambling) 2025-08-17
Occasionally someone complains about the state of computer software and it causes a discussion, some of the most common topics are slowness and bloat. Another one in the same series of related issues, and the one that spurred this diary due to something from a few days ago, is about how people just keep stacking layers of software on top of layers of software.
As far as I understand, the TL;DR of what happened there that is that a new web browser that is currently in development is using SLD to handle keyboard/gamepad input. SDL is an unnecessary and huge layer and liability being added into that browser, thus contributing to software bloat. The alternative is to use the operating system's input API directly, removing SDL from the middle. You'd have to implement a different API on different operating systems, but maybe it's still better than gluing a monstrosity like SDL in there and being dependent on it's whims, especially for a project as "important" as a web browser.
However, the actual crux of the complaint is deeper than that, it's that we shouldn't have to do this. Every developer is still stuck wrangling with this kind of basic crap and gluing together these monstrosities because it's all such a tangled mess, how come "we" (developers as a collective, or society) still haven't gotten past that? Why don't we still have solutions for this kind of stuff that just work so we wouldn't have to even consider gluing these monster frameworks together to get things done?
The obvious answer is that nobody wants to subscribe to someone else's way of doing things. A lot of these problems, especially input handling, have their roots in the operating system which you can't just change. If you want your program to work on all platforms, you will necessarily have to inherit all the problems of all the platforms. You can glue 20 megabytes of SDL in there and pretend the problem doesn't exist, but the problem is still there, you've just stuck another layer in the middle and created a new dependency.
Most operating systems are owned by some kind of corporations, were established in a time before we knew what we wanted to do with computers and how we wanted to do anything, when people were inventing new programming paradigms and nobody knew which one would be the future, in a time where hardware and software innovations were in a completely different state, and have carried all kinds of mistakes along the way for the sake of backwards compatibility or whatever reason. The result is that all current operating systems and their APIs are very convoluted and poorly designed from a current day viewpoint. You can't blame them for getting there because of the journey they've had, you can maybe blame them for not trying harder to fix it, but in any case the end result is very bad for everyone.
I think we're currently at an extremely precious time, we have an opportunity that probably won't come again after it passes. Since all the operating systems are crap, and Microsoft has been repeatedly stabbing itself into the liver and lungs and heart and brain for the past several years, it has never been a more appropriate time for someone to make a new operating system. The publicly shared daydream of this happening seems to be growing too.
I believe you would end up absorbing all the users of all operating systems just by making a good OS. The reason is that a well designed new OS could be so much better in every way that nobody would want to use the ones we have today for any other reason than software compatibility. Things like hardware support and software compatibility can be addressed over time and a lot of the solutions can be ported over from Linux to the new OS, users and developers will start dripping in and it will keep cascading until big software developers also port their software over, and it'll be easier than ever to port things over to a new OS because the new OS would have well designed APIs that are easy and pleasant to work with instead of the nightmarish clusterfuck that are our current operating systems. The reason this cascade of users and developers doesn't happen with Linux is because Linux is a fucking atrocious piece of shit operating system for both users and software developers. Windows has become a dystopian nightmare but people still prefer it over Linux, and the reason can only partially be blamed on software compatibility or familiarity or those kinds of things, the lion's share of the blame is on Linux itself.
I'm not concerned about whether a new OS is possible or practical or whether it would succeed. The only question in my mind is "who will do it", or to be more specific, "who would I trust to do it right and not waste this opportunity by creating another depressing pile of crap". I have very low faith in most developers, especially for something as important as this. In current society everyone's trying to find a way to get ahead in the cheapest and easiest way possible, so everyone would jump at this opportunity if they could, even if they had no idea what they're doing.
I don't think we'll actually get a new awesome OS despite having this opportunity.
This diary isn't about operating systems
I got derailed. Unless you become a dictator and mandate that everyone use your OS, or you get exactly the right person to make the perfect OS that everyone switches to, the problem I started with will never be solved. As I said earlier: if you want your program to work on all platforms, you will necessarily have to inherit the problems of all the platforms, including the fact that you need multiple solutions instead of just one.
One approach could be to get OS developers to agree to a common standard and implement it, similar to how CPU vendors have agreed to share instruction sets so you don't need to create 2 separate programs for Intel and AMD CPUs. But let's be realistic here, the chance of Microsoft and Apple shaking hands and implementing a shared API is lower than someone making an epic new OS that crushes both of them.
So if the OS problem can never be fixed, what CAN be done? Creating yet another layer of software that "everyone should totally use" doesn't work, if it did then all software would be built on top of SDL right now and libraries like Raylib would have never been made. A library will never be able to solve everyone's problem perfectly because, due to differences (and awkward problems) in operating systems, it has to make a bunch of decisions and compromises, and it's users are then forced to live with them even if they disagree with them.
That leads me to the actual point of this diary: I think we've been thinking of programming libraries a little bit wrong the whole time, and ironically the name itself, "library", is how. Real libraries are not for getting products that solve your problems, they're for learning things, programming libraries are more like hardware stores in that sense. What if instead of a premade library that you're meant to glue in, we had something more like a wiki website full of bootstrap code that you can take into your project and then modify to your preference? Rather than gluing SDL into your project, you copy paste the bootstrap code for handing input on your target operating system, and then tweak it according to your needs, and optionally read the wiki page for more info about it and click links to related systems and other operating systems. Programs developed this way would be more optimized for your needs, your codebase, and your style, and it would be much more educational.
You might think that this is the same as "copy pasting from stack overflow", but I'm thinking of a more perfected solution, not just an explanation or an example, but something that is more complete and meant to be used directly just like libraries are. People could discuss solutions and optimize them to be as straightforward and to-the-point as possible.
We use tutorials and things like that for learning and teaching, but in most cases they're very inefficient, and that's partly why people prefer to just glue in a premade library. It's almost impossible to go backwards from a library and learn how to implement some part of it yourself because libraries are rarely designed to be simple, to-the-point, easy to read, or easy to learn from. If the library isn't working for you, the solution is almost always to find a new library, not to change the code in it. For that reason the focus should be on providing the code that does what's necessary for a specific goal, that way you can get going almost immediately similar to using a library, you can adjust it to your preference, and can also learn from it. One of the best ways to learn something is to directly see what you're supposed to do.
I recently had the opportunity to experiment on a computer with 2 high-DPI monitors, and managed to come up with the process to make my program window scale properly for high-DPI monitor setups. However getting everything right took me all day because of all kinds of weird complications (mostly because the window border is automatically rendered and resized by the OS and it affects the size of the window's inner contents), and I'm still not entirely sure how I'm supposed to handle certain things. This is exactly what the original problem was: it's too much effort to do something this basic, and it's only one operating system. I would have had a much easier time if there was a place where I could get some bootstrap code to implement high-DPI windows, but instead I had to dig through Windows documentation pages and piece it together myself and discover and fix weird edge cases. Or alternatively, I would have had an easy time if the OS window API wasn't such a mess. Linux can't have a moral victory here either because they don't have a window API, that's the level they're playing at.
This wouldn't be a full replacement to libraries though, libraries are useful if they solve some complex problem, or something that can't be separated into many small solutions. This is just for solving the problem of us being stuck forever wrangling the same basic crap and being incentivized to glue bloated frameworks together just to do the most basic things.
The solution to the problem is not to try to solve it, but to provide an answer to it.
Programming languages
On a completely detached but related topic, part of what's contributing to the (bad) state of software are programming languages. C and C++ are still some of the best languages, but they make it really annoying to compile programs made up of multiple files and they encourage people to create a huge entangled mess and add dependencies to third party build tools, and the languages carry a lot of weird old issues with them. C# seems to be on a railroad of Microsoft's bloat frameworks and massive game engines. Some languages create really bloated programs, some require you to use a separate huge framework like Node.js and can't be compiled into a simple executable. For some reason many compilers require you to install a ridiculous Microsoft Bloat Package in order to work, except for MingW and TCC which are for... C and C++. I find the irony of some of this stuff so ridiculous I don't know whether I should laugh or to cry.

Why don't we have a sane language and compiler that has the capabilities of C++, but is cleaner and easier to use, doesn't reduce capabilities nor make things less convenient, and doesn't make some stupid decisions that completely kill it (especially when compared to the language it purports to compete with)? The good thing about languages is that it's relatively easy to make a new one, but then where is the good language?
Maybe what I think to be obvious is just not as obvious as I think it is, I don't want to believe that my views on languages are uncommon because it seems like an obvious viewpoint. I think the language should make it as easy as possible to create a program according to your own vision. Almost all languages make a bunch of decisions for you and/or prevent you from doing certain things. For example adding a garbage collector, or making it really inconvenient/impossible to do things that the language author thinks are "dangerous" or "wrong" (note how I said "the language author thinks", not "I the programmer of my programs think"). The language should be a tool that helps me do what I want. It shouldn't be a thing, it shouldn't be an idea, it shouldn't be a community, it should be a tool in the same way that a hammer is a tool. Just an object that helps me create what I want.
The reason I call C and C++ some of the best languages is largely because of this reason; they don't make many decisions for you, they were made in a time when doing crazy and dangerous things was just the way things were and so they won't get in your way when you want to do them, and the macro system allows you to bend the rules a bit in order to do what you want. I think these are the true reasons that allow the languages to be so immortal, not just because of the momentum they have, but because no other language since has been so closely focused on base truthfulness and programmer empowerment, and these mostly manage to do it with very minimal amount of syntax (C++ goes off the rails in many places though).
I'd like to go more into that direction because there's many ways in which you could, and fix all the issues with those languages along the way. But newer languages are all some combination of "fix a few (not all) of the problems, carry over some obvious problems that should have obviously been fixed but weren't fixed, make certain things that used to be convenient be less convenient, enforce specific ways of doing things, add a whole lot of symbols into the syntax and add more annoying keywords that conflict with your own names".
I view standard libraries the same way as normal libraries: it's just someone else's code. I don't consider them as part of the language when judging the language, I'm only considering the syntax and core behavior and error messages and other things that the user cannot implement.
My own language
I keep flip flopping back and forth between deciding to make my own language, and deciding that it's too much work. I am currently in the "I'm going to do it" phase. The biggest problem is that I don't know what to output.
Transpiling from my language into C code would help me in a lot of ways: it's easy to do because I just have to write a text file and hand it off to a C compiler that handles all the complicated stuff, compatibility because it's just C code, ability to use C libraries as-is, compilation speed because you can use TCC, optimizations/performance because it can be compiled by proper C compilers.
However it's difficult, after parsing the intent of the code, to then convert it to C code that has the same intent. I want to be very specific about what I want, but I'm not 100% sure how to mirror it all in C. For example I want structs and unions to be mostly the same thing, so I need to be able to set specific offsets to struct members and give structs a specific size. Relatedly, it's easier to parse an expression if you just figure out what the offset and type of a value is, but it's clumsy to convert it back into C unless you use something like ((type*)(((void*)&var)+offset))
for everything. Another big problem is that you can't use a debugger because there's a disconnect between what code the debugger sees and what code you see.
Interestingly, it might be easier to output Assembly since Assembly is all just memory offsets and instructions. In some situations C is "too high level" compared to how I want to think. For example I want an operator like &+
which would let you get a pointer offset in bytes (basically ignoring the type of the pointer) without having to do the incredibly verbose casting thing from the previous paragraph. Assembly also doesn't have types in the same way, it's mostly the operators that have types, for example mul
for unsigned ints vs imul
for signed ints. I want more control about how/where data is stored, for example maybe I want all strings to be aligned and padded to 8 bytes, maybe I want the string data to be writeable. Although I'm not super knowledgeable about this, I am interested in managing my own data sections so I can decide for example which global variables are grouped together, for cache optimization reasons or whatever.
I kinda want to learn Assembly enough to output my language into it, but it would mostly be a vanity project because you can't optimize it, it doesn't help with the debugging problem, and it would not be possible to use C libraries the same way. Advantages are very fast compilation times, allows compilation without a C compiler, gives knowledge/experience for myself (which to be fair would be useful if I want to make a language). I'd probably still need an assembler to actually produce an executable though, I don't know how large the difference between Assembly and machine code is but it might be possible to compile without an assembler.
One caveat is that you wouldn't be able to compile to non-x86 platforms. Custom compilers become a bit of a rabbit hole when you start digging into the details, which is mostly what causes me to conclude that it's too much work.
A "proper" language would use LLVM, but I've heard nightmare stories about what a huge chore it is to work with that. I tend to have very low tolerance for dumb inconveniences, but I'd probably have to use it if I wanted to take this seriously. I don't know how debugging works, does LLVM produce debug info or would I have to do it separately?
Rather than going deeper, I could also go simpler. I originally tried making a simple C pre-processor that only does a couple of the easiest fixes, but I can't seem to find a balance that is worth using, mostly because macros and #ifs screw everything up, and because you have to preserve line numbers or else the C compiler gives you the wrong location for errors.
I've even considered paying someone else to make the language, but I have no idea how to find someone to do it. A bonus advantage of paying someone is that I could potentially get features that I'm not confident I could do myself, mostly compile-time scripting.