pcb-rnd knowledge pool
why glib is a bad idea
glib by Tibor 'Igor2' Palinkas on 2015-10-28 | Tags: dev, rant, glib, megalib, minilib, hash, list, genht, genlist |
Abstract: A short rant about why glib is bad: it causes more problems than it solves. Also explain why glib is not a lib, but a programming environment. A solution is proposed and demosntrated on pcb-rnd.
The problem
Levente tried to compile pcb-rnd on bsd and used a different c compiler than gcc. For this in the first step I fixed the build system so that it doesn't have gcc --std=gnu99 but gcc --std=c99.
And then everything broke. A minilib I use for hashing, genht , failed to link against hid/common/action.c. I first thought it was a bug in genht: genht was compiled without --std while the rest of the code compiled with --std=gnu99 or --std=c99. Genht heavily depends on static inline functions for performance, maybe that's why.
So I tried to reproduce the situation in a hello-world like program and tried all combination of --std, -DNDEBUG, -rdynamic and all build flags used in pcb-rnd for the genht lib and the test program, but all combination worked. It looked like it broke only in pcb-rnd.
I gave up on the minimal test case and went back to pcb-rnd. I realized if the build is the same, the only way it may break is that some header included before genht's headers change some global state. I started to shuffle the #includes. Long story short, it turned out if <glib.h> is included before genht's headers, it breaks.
Some more tracing showed it was because glib over-#defines the keyword inline in a public header that gets included from glib.h. It's all wrapped in a complicated tree of #ifdefs, so it behaves differently depending on the --std setting.
The morale of the story is... Well, I have multiple conclusions.
- glib is not a lib that tries to solve something, it is a programming environment that tries to supersede C.
- As such, it feels free to mess with the environment, redefine C keywords as it sees fit, because once you use glib, why would you use anything else? And once you use glib, you are programming in glib, not in "plain C".
- Grepping through the pcb-rnd code, I see that pcb-rnd does not try to use glib as a programming environment, but needs only 2 and a half features: hash, list and rarely dynamic strings. Any other glib call is just a must that had to be done that way to get hashes and lists working.
- genht is 510 sloc. I have a generic list implementation (which, by the way, is more efficient than glib's). It costs 256 sloc. So having type-independent hashes and lists in C89 costs less than 800 lines of code if you pick the right libs. Glib's include/ alone is over 24000 sloc! And in return glib breaks inline...
In a nutshell this is why I don't believe in glib-like solve-all megalibs. I don't say size alone determines this, but size is a good indication of potential problems.
If I need hash and lists and the offer is longer than 5k sloc, I know it will bring a lot of unneeded bloat that likely to break things.
The solution - unglib
As described above, glib is sometimes dangerous. Even if it was not, it's still huge and contradicts the UNIX philosophy: Do One Thing and Do It Well . Glib tries to do a lot of things. I do not doubt it is trying to do each of these things well, but as a combination it's pretty much impossible to Keep It Simple, Stupid . While glib is modular in design, from the viewpoint of an application it is not modular: it's highly unlikely that the application can replace a part of glib while keeping the rest.
The source of these problems is that glib is a "megalib" that tries to solve a host of problems as a package.
The solution is to replace the megalib with a set of independent minilibs. Each minilib:
- tries to do one thing - e.g. linked lists, without coupling it with a custom memory allocator
- is simple - the API is so small that it's easy to learn it in minutes
- is small - so that if anything breaks it's very easy to find and fix the bug (when did you last debug internals of glib?)
- is replaceable - since they are independent, if one doesn't work up to expectations, it's real easy to replace it without affecting any other part; e.g. replacing linked lists without replacing hash tables
The minilibs are imported as svn externals in trunk/src_3rd. They are small enough so that they can be distributed together with pcb sources.
Current state
The "unglib" patch is mostly done. All references of glib are removed from the core and the lesstif hid. There are a three components that still depend on glib, but they each can be disabled:
- the GTK HID: because gtk is already coupled with glib, it doesn't make much sense to remove glib from the gtk HID code
- the toporouter plugin: the code is huge and will be potentially deprecated anyway (lack of developer resources/user interest)
- the puller: glib should be removed from the puller long term but the code is big and there's no much user need for it in pcb-rnd
This means pcb-rnd can be compiled with lesstif (or a compatible motif) on a UNIX box without depending on glib. Together with the earlier effort that removed autotools, it means a UNIX box without any "GNU infection" should be able to compile and run pcb-rnd.
More reading
I have longer essay about minilibs hosted in another repo.