Meta(
    title: "Workflows, Tooling and Bloat",
    summary: Some("Some thoughts on why newer developers are doomed to be working uphill."),
    published: Some(Time(
        year: 2022,
        month: 7,
        day: 21,
        hour: 22,
        minute: 24,
        second: 39,
    )),
    tags: [
        "software",
        "gnome",
        "tooling",
    ],
)
---
I like to try out languages from time to time. I've dabbled in a lot of different ones, some modern and some very old, and find it fascinating how after the first few experiments each succeeding language becomes easier to learn. That's not the point of this post, although it's always a fascinating subject. Rather, it's merely what got me thinking about tooling today.

I've got a bit of a history with Gtk+. My first graphical programs were written back when I was running Puppy Linux and contributing to it regularly. Back then, we used gtkdialog and abused shell scripting to the extreme. I consider that path a bit of a dead end, but it made the concepts familiar when I revisited writing graphical applications later on, this time in compiled languages. I've played around with Gtk+ in Python, C, Go, Fortran, Zig and most commonly in Rust. But recently I thought that I would try out Vala, as it seems to be almost purpose built for the task (being based around Glib and GObject). It's actually quite a nice language for the task, although I wouldn't reach for it in any other context. Having actual namespaces makes the code more readable than C, and the amount of boilerplate is also reduced.

That is, until I decided to try out Gnome Builder again...

## A typical project skeleton
I'm sure that most people have their own opinions on what a nice minimal project skeleton is. It's also kind of domain specific, as a desktop application will have need of files that a command line utility won't. For my Rust and Gtk+ projects, a minimalist project tree would look like this.
```
.
├── Cargo.toml        The Cargo manifest, for the build
├── data
│   ├── app.svg       An application icon
│   └── app.desktop   The freedesktop.org .desktop file, for WM menus
├── LICENSE.md        The project license
├── README.md         Brief description of the application
├── src
│   └── main.rs       The program entry point
└── xtask             This subdirectory is used in packaging, and is
    ├── Cargo.toml    entirely optional (see below)
    └── src
        └── main.rs
```
The xtask subdirectory contains the source for a separate binary which is used to perform packaging tasks. It wasn't my idea originally, but one that I've adopted for all of my Rust projects. This binary copies all of the required files into a staging directory, generates smaller png icons from the original svg, generates shell completions and Unix man pages, etc. It automates those things that Cargo itself doesn't do natively. I could use instead make, or meson, or any number of other build tools. The advantage of the xtask binary is that it doesn't fall down in the event that some tool that existed on the developer's machine isn's available on the packager's machine. The xtask binary knows how to read svg and write a png, and how to create shell completions from the CLI definitions, etc. It's a nice system, I think.

## Gnome Builder's project skeleton
Starting a new Gtk+ project written in Vala from Gnome Builder creates this tree.
```
.
├── COPYING
├── data
│   ├── icons
│   │   ├── hicolor
│   │   │   ├── scalable
│   │   │   │   └── apps
│   │   │   │       └── org.hitchhiker_linux.app.svg
│   │   │   └── symbolic
│   │   │       └── apps
│   │   │           └── org.hitchhiker_linux.app-symbolic.svg
│   │   └── meson.build
│   ├── meson.build
│   ├── org.hitchhiker_linux.app.appdata.xml.in
│   ├── org.hitchhiker_linux.app.desktop.in
│   └── org.hitchhiker_linux.app.gschema.xml
├── meson.build
├── org.hitchhiker_linux.app.json
├── po
│   ├── LINGUAS
│   ├── meson.build
│   └── POTFILES
└── src
    ├── application.vala
    ├── gtk
    │   └── help-overlay.ui
    ├── main.vala
    ├── meson.build
    ├── app.gresource.xml
    ├── window.ui
    └── window.vala
```
Ok then, uh, that's a lot. And tokei counts 407 lines of code. Doing the same but for a Rust Gtk+ project results in a further 162 lines of code and 4 more files. Some things I find interesting:
* There is not only an application icon but a symbolic icon. Why?
* The appdata.xml, gresource.xml and gscheme.xml files are pretty well Gnome specific.
* There are four meson.build files, when it's not really required to use Meson at all. Builder assumes you want to use Meson. Maybe you don't.
* Builder assumes that you want to use ui definition files and not just code your interface in Rust.
* Builder assumes that you would subclass gtk::Application and gtk::Window. Eva uses some subclassing, but not for it's main window or application. OxTerm subclasses it's main window, but not it's application. Gfret doesn't use subclassing at all.
* Builder makes another assumption that you want to have a help window, which just displays the application shortcuts. Since these shortcuts are displyed next to their corresponding menu entries, that's of dubious utility.
* Builder assumes that we want to distribute this application as a Flatpak and includes the tooling to do so.

A lot of this comes down to preference, and I do realize that I'm picking on Gnome Builder here when they've obviously designed it around creating applications specifically for Gnome. You get the same sort of boilerplate heavy project template out of, say, QT Designer, but optimised for a different workflow. That said, Gtk+ is pitched as a general purpose, platform independent toolkit. It can be used outside of the context of Gnome, and in fact is used that way a lot. Builder actually gives you a choice of several types of project to create, one of which is plain Gtk+ and one of which is Gnome. And the examples I already gave are the plain Gtk+ variety, not Gnome. So why all the Gnome-ey boilerplate and Gnome-ey assumptions about what to include and how to build it?

## Beyond skeletons
Great tooling can do a lot to make a development experience smoother and more productive. That said, always abstracting away to a higher level comes with tradeoffs, and in particular if you don't learn how to use the underlying tools in the first place. I learned to use Git on the command line before encountering any kind of IDE integration. I've written Makefiles by hand and know how to invoke Gcc directly. When learning Rust I learned how to use Rustc before learning Cargo. But that's because I came up in the days when we had to write an Xorg config file by hand and often had to intervene when the boot process didn't load all necessary modules. Younger folks haven't had those experiences. The most used and recommended editor is VScode, not Vim. Linux is pretty easy to use now, too. Generally, you install it and everything works on first boot, or at least close enough. It's been years since I had to, say, use ndiswrapper to attempt to get a USB network interface working that doesn't yet have a native driver.

I think that anyone who wants to use their computer in anger owes it to themselves to dig beyond the numerous outer layers that we keep erecting to make things "simpler". I'm not against automation. In fact, my description of how I use xtask in my Rust workflow shows how committed I am to automating packaging. But I don't think it's a good idea for young programmers to start their journey with an IDE. I'd rather see them start with Vim or Emacs in their plain vanilla configuration, and then over time build up a personalized workflow that automates those things that they feel are a waste of their time. If they instead start out with someone else's idea of a good starting point it is destined to be bloated, and will only acquire even more cruft as time goes by and developers add even more "good ideas".

I love everything that the Rust ecosystem gives in the way of tooling, but at the same time I kind of miss writing C and the only documentation being manual pages. You had to learn how to use the man command in order to find the info that you needed, but it was there in the terminal, and you were already in the terminal running your editor and compiler. I still think that Make gets a bad rap, because frankly it can do just about anything and it's pretty easy to learn. Note that I'm referring to Make, not to Gnu Autotools. Autotools was the worst kind of abuse of shell scripting imaginable. I really strongly dislike that modern IDE's abstract away the actual commands used to invoke the compiler. I'd even go so far as to recommend that new developers learn how to manually invoke the linker, as there is going to come a time when you run into an incorrect linker command being your build system's failure and you need to be able to troubleshoot it.

Could this all be filed under "old man yells at clouds"? Well I suppose that it could. But this is, like, my own space to do with as I want...