Chronicles of XMonad and xmobar

The user, the status bar, and the window manager

This is a story about how the Haskell toolset, Arch Linux package maintainers, and font rendering engines made me lose a few hours of my life. Of course, I consider myself equally guilty, for my choices and stubbornness inevitably led to the happenings I am about to relay onto you.

Chapter 1: First Mistakes

It was a dark and stormy night somewhere in the world. I was sitting in front of my laptop, speaking to a couple of friends over Mumble, when I accidentally knocked over the glass of soda I’d just fetched from the kitchen. It would have been a minor inconvenience, had I not spilled it directly onto my laptop. In a panic, I told my friends I’d be back later and immediately shut the system down to avoid any short circuits.

Though I was able to clean up most of the mess, and properly avoided turning the machine on in case there was still liquid inside, the keyboard would remain sticky for the rest of that laptop’s life. A keyboard replacement cost too much money to justify the purchase, and I was due for an upgrade anyway.

When I got a new laptop, I decided this time around I wasn’t going to waste time customizing Windows. Instead I’d make the switch to GNU/Linux completely, and use all the cool tools I’d heard being talked about on IRC for years. Rather than ask anybody what I should use, I went with a Debian netinst, and used the only window manager the name of which I could remember: XMonad.

Chapter 2: Growing Pains

XMonad is a great window manager for the Haskell programmer. In a way it isn’t a window manager unto itself, but rather a library for building your own window manager in Haskell, with the configuration data type containing functions for hooks that allow you to alter window managing behavior. Should you ever wish to fully control how your windows are managed on X11, and you’re either a Haskell programmer or someone who truly wishes to become one, I highly recommend XMonad.

You see, I didn’t fit into either of those categories when I started using it, and for a couple months I was completely oblivious to the fact I was using a programming language, not what I imagined to be XMonad’s configuration syntax. When I realized what it was, I was amazed, but at the same time completely lost: I didn’t know Haskell, and I had never come across functional programming.

At some point, I decided I was going to learn it, and fell in love with the language. It allowed me to make my window manager do exactly what I wanted, provided I could figure out its internal machinations. Erstwhile an advocate of C as an end all be all language due to its simplicity, I might’ve abandoned XMonad altogether had I been introduced to dwm sooner.

It was during this time of learning more about XMonad, window managers, and Haskell that I found xmobar. It’s an uncomplicated program that serves as a status bar. Since it’s written — and can be extended — in Haskell, it’s a common option for XMonad users.

My “Haskell studies” went well enough I was soon making changes to the modules on the xmonad-contrib package. Some of those changes were submitted and even merged upstream! Locally I started using xmonad-git and xmonad-contrib-git: packages in the AUR that build the latest version of these two packages from the master branch of their respective repositories. I just needed to point them to my local work trees for testing.

Chapter 3: Arch Linux and the Winds of Progress

One day I boot up my laptop as usual and try to startx, only to get a mysterious error about missing shared library files. Recompilation of my XMonad configuration wasn’t working, as I knew how to do it only through xmonad --recompile, and the xmonad binary was giving me the same linker error. I turned to the #xmonad channel on IRC, then on Freenode. Turns out I wasn’t the only one that day inquiring about the same error messages!

Turns out the maintainers of Haskell packages on Arch Linux got tired of using up obnoxious amounts of disk space by shipping static library files. At some point they decided from GHC to Pandoc and XMonad, every Haskell binary would be dynamically linked against its dependencies, and every library package would ship only the .so shared object files.

I shall take no part in the debate about whether dynamic linking is worse or better than static linking. However, Haskell makes dynamic linking a little… problematic. When packages are registered with GHC, their library files get this seemingly random string of characters just before the .so extension — e.g. libHSlibyaml-0.1.2-EKt9DNz2mMV6vcYqiiizdE-ghc9.0.2.so. Maybe this is done to ensure a specific build, or maybe it’s just a way to make sure the GHC ABI is what you’d expect. Whatever it is, I don’t like it.

The reason XMonad broke for so many users at the same time was because the binary was dynamically linked against files that were no longer present: the haskell-* packages that it depends on were updated, receiving completely new set of random characters at the end, but the xmonad binary hadn’t yet been linked against them and pushed to the official repositories. This was resolved and now packages like xmonad are properly rebuilt on a timely manner. However, I said I started using xmonad-git! Rebuilding the package then became my responsibility, and whenever dependencies were updated, XMonad would stop working and I’d have to rebuild the whole package.

Eventually I started using Stack. It’s a tool for managing GHC installations and Haskell projects, and it’s one of the choices to pick from when installing XMonad. My XMonad configuration became a Stack package and it just worked! I could abandon the xmonad package from the official repositories and instead rely on Stack to make a symlink in my ~/.local/bin directory. By default, everything was statically linked.

Chapter 4: Font Rendering

Though I jumped off the Pacman train for XMonad, I had no reason to switch away from the official package for my status bar, xmobar. It worked fine, with linker errors seldom occurring. However, just a few days ago, the official package was updated to version 0.46.0, which brought with it the switch from Xft to Pango as the font rendering engine — a change merged upstream in version 0.45.0, previously not packaged. Obviously, that couldn’t have been transparent.

No matter what font size I tried using, DejaVu Sans Mono looked off, either blurry or too big, completely different from how it looks on my terminal emulator. Downgrading the package doesn’t fix the issue, because then you have to downgrade all of its dependencies as well because of the dynamic linking issue. If any of those dependencies are used by other packages, you’ll have to downgrade those as well. It’s a mess.

So instead I went with stack install xmobar-0.44.2 and called it a day. For now I’m staying on that version, willing to backport bug fixes from upstream if necessary. There’s mention of pangoxft in an issue opened on the xmobar issue tracker, so maybe there is an upgrade path for me!

Chapter 5: The Future

For the time being, using Stack to manage my Haskell projects is working out okay, but I might switch to a distribution that still ships static library files in their Haskell packages. Maybe Nix? Not sure.