Developing for elementary OS the Hard Way
Posted on October 23, 2023 • 5 minutes • 898 words
Table of contents
I’m a Stan for elementary OS
. People say that it’s a macOS clone for Linux, and I’ll loudly tell them that they’re wrong–
it’s an OSX clone for Linux, and that is a different thing entirely. But while I love the look and feel of the Pantheon desktop environment,
and I was, for a decade and a half, a “.deb
or Die” Ubuntu-variant devotee, I ended up switching to Arch (+ Pantheon) on my main workstation about
a year ago.
Today I decided I’d like to try designing a GUI app for the first time since undergrad, and while, thanks to Flatpak, I could choose from one of dozens of toolkits, I’m going with Granite because I want this to be an elementary OS application first and foremost.
Obviously, the elementary OS developer guides
weren’t written for my particular setup, so this post is serving to
document what I did for anyone else who chooses insanity to walk down a similar path.
Of course there’s no elementary-sdk
package in the AUR
Though wouldn’t that have been nice!
Of course, elementary-sdk
is just a metapackage anyway,
and I could just hunt down each metapackage member, but hitting this barrier did make me stop and think: “Wait, why would I install an entire development environment onto my base system?” I wouldn’t do that for a Python project–I’d use a conda environment. So why wouldn’t I do that here?
Solution: Install Distrobox
Honestly, I’m more surprised that I’ve gone this long without using it.
There’s no base elementary OS container, but an Ubuntu 22.04 one should work fine with the added PPAs:
$ distrobox create -n elementary-dev -i ubuntu:22.04
$ distrobox enter elementary-dev
openbagtwo@elementary-dev $ sudo apt update && sudo apt dist-upgrade
openbagtwo@elementary-dev $ sudo apt install software-properties-common
openbagtwo@elementary-dev $ sudo add-apt-repository https://ppa.launchpadcontent.net/elementary-os/stable/ubuntu
openbagtwo@elementary-dev $ sudo apt update
openbagtwo@elementary-dev $ sudo apt install elementary-sdk
And that worked a charm!
Flatpak And Containers Don’t Mix
Following along in the developer guide , the next step was to install the elementary appcenter flatpak.
That failed spectacularly inside of my dev instance with the very unhelpful error:
error: No such file or directory
which took me a minute to track down to a known limitation of Flatpak : running them inside of containers is a little too meta for them.
Solution: Install appcenter on the system
And honestly, having the elementary Flathub repo available on my system is something I want regardless.
$ flatpak remote-add --if-not-exists --system appcenter https://flatpak.elementary.io/repo.flatpakrepo
$ flatpak install -y appcenter io.elementary.Platform io.elementary.Sdk
(I chose the newest available runtimes, which were one point release ahead of the current)
Hello World!
And now, finally, it was time to write my first Vala app .
Some notes:
- I thought for sure I’d need something like syncthing to make my files available inside the container, but nope–the container had access to the files in my current directory automagically!
- On the flip side, I needed to “enter” the container from the project directory (couldn’t
cd
there from~
), and I needed to havecd
’d to the absolute / resolved path (my “Workspaces” directory is actually a symlink pointing to a different drive, and distrobox didn’t know how to work with that). - While the container could be used to compile the project, the actual GUI application needed to be run from the host
For ease of copy-pasting, here’s the commands I used to compile and run my first Vala app:
$ cd /path/to/workspace/vala-project
$ mkdir -p build
$ distrobox enter elementary-dev
openbagtwo@elementary-dev $ valac --pkg gtk4 src/Application.vala -o build/Application
openbagtwo@elementary-dev $ logout
$ ./build/Application
Granite and Meson
So far my application has just been a bog-standard GTK4 app, but the whole point of this exercise was to build something
for elementary. Some of the high-level concepts are covered here
but at this point I was better served by just copying and modifying meson.build
files from
a template project
.
The big thing was switching over to using GObject-style construction so the top of my program now looks like:
public class EnderChest.Application : Gtk.Application {
construct {
application_id = "com.github.openbagtwo.babys-first-vala";
flags = ApplicationFlags.FLAGS_NONE;
}
...
I also copied over their startup() method which sets the application styling and registers Ctrl-Q as a keyboard shortcut to quit.
With those changes made and files in place, I hopped back into my distrobox container and ran:
$ cd /path/to/workspace/vala-project
$ distrobox enter elementary-dev
openbagtwo@elementary-dev $ meson build --prefix=/usr
openbagtwo@elementary-dev $ cd build
openbagtwo@elementary-dev $ ninja
openbagtwo@elementary-dev $ logout
$ ./build/src/com.github.openbagtwo.enderchest-gui
which looks the same as before, but now closes with Ctrl-Q.
Playing Around with Granite
Finally, to get a good sense of the widgets at my disposal, I cloned the Granite library itself so I could build and run their granite demo:
$ cd /path/to/workspace/granite
$ distrobox enter elementary-dev
openbagtwo@elementary-dev $ sudo apt install sassc
openbagtwo@elementary-dev $ meson build --preix=/usr
openbagtwo@elementary-dev $ cd build
openbagtwo@elementary-dev $ ninja
openbagtwo@elementary-dev $ logout
$ ./build/demo/granite-7-demo
So cool! This is going to be so much fun to play around with.
Next Steps
The project I’m working towards is a frontend for EnderChest and GSB , and there’s a lot I don’t know about how to integrate a Python backend with a GUI frontend written in a completely different language (without resorting to just calling the CLI in between). Ahead of me is a fun journey of learning about ABIs and GObject Introspection !