Diving Into Vala: Project Lovey v0.1.1
Refactor the source & setup a Meson build system.
Posted by David Rodriguez
Something to think about
So, here we are. Back at Project Lovey (if you haven’t read part one, be sure to check it out) and I still have no idea what I want her to do! But I do know that there are certain things I want this app to have.
I want this app to have:
- A Custom HeaderBar
- Settings/Menu Button
- Popover Menu
- Info/About Button
- An About App Dialog
- App Licensing Info
- Contributor Info
- Settings/Menu Button
- A Welcome Page
- Action items?
This can be a good start to a template for future apps. Since I have no idea what I want the app to do, but I do know that it will just be a simple single windowed app, I will basically build a template for now.
Before we get started
Vala does not enforce a certain source code structure in which to place your files in. There is no recommended software architecture / design pattern. To paraphrase the Vala Tutorial, you are free to structure your source code in whatever way suites you and/or your projects needs.
“Vala code is written in files with .vala extensions. Vala does not enforce as much structure as a language like Java - there are no concepts of packages or class files in the same way. Instead structure is defined by text inside each file, describing the logical location of the code with constructs such as namespaces. When you want to compile Vala code, you give the compiler a list of the files required, and Vala will work out how they fit together.”
This can be both a good thing, and a bad thing! This means you can do something lazy like, placing all of your source files into a single directory and compile them. Because, believe it or not, that is a valid project structure!
For ‘small projects’ – I would consider <=5
files to be a small project – bunching your source files into the root of a
project folder shouldn’t be too much of an issue. As far as myself, no matter
how big or small the project may be, I like to structure the source code into a
logical folder hierarchy. The only time that I do not do this is when the
project meets the ‘small project’ requirements, as stated above.
What we will cover in this article
Part one got us set up with a basic Vala & GTK+ 3 GUI window. In this second part of the series, we will refactor this code and prepare it for further development. As it stands, we can write the entire application in one huge file. Nothing is stopping us from doing this. Except the fact that the source code would get unwieldy large and overly cumbersome (to say the least) to manage.
So for this reason, we’re going to break our project’s source code down into
logical and manageable chunks. Each in their own separate
.vala files. After
the refactoring is finished, we will focus on setting up Meson for
Later on in this series we will cover adding custom widgets to the window and buttons to the header bar. But for now, let’s just try refactoring the code and setting up a build system for our project.
Getting started (Project Prepping).
The current state of the
project-lovey directory should look like so:
project-lovey/ ├── CHANGELOG.md ├── LICENSE.md ├── Lovey.vala └── README.md 0 directories, 4 files
Let’s switch this up a little. We’re going to create a
src directory inside of
project-lovey directory that will contain all of our source code from
$ mkdir src $ cd src/
Refactoring the Project Lovey code structure
In order to refactor the
Lovey.vala code, I am going to create 3 new files in
$ touch Application.vala Main.vala Window.vala
project-lovey directory should look similar to this:
$ tree ~/Projects/project-lovey/ project-lovey/ ├── CHANGELOG.md ├── LICENSE.md ├── Lovey.vala ├── README.md └── src ├── Application.vala ├── Main.vala └── Window.vala 1 directory, 7 files
Namespaces in Vala, are named scopes. To quote the Vala Reference Manual directly,
“Definitions in different namespaces can use the same names without causing conflicts. A namespace can be declared across any number of Vala source files, and there can be multiple namespaces defined in a single Vala source file. Namespaces can be nested to any depth. When code needs to access definitions from other namespaces, it must either refer to them using a fully qualified name, or be written in a file with an appropriate using statement.” - Vala Reference Manual
Although we will be touching on Namespaces within our code. We will be using an alternative syntax, as compared to the default syntax.
The default namespace syntax:
I will be using the dot notation syntax, refering to the fully qualified name when needed, like so:
I personally find it to be much neater and cleaner than wrapping the code in a namespace scope. So I will be using the alternative syntax. You can use whatever syntax you'd like for the namespace. This is solely a personal choice.
Let's begin refactoring
When we're done, nothing about the app should change (okay, I am going to change the App's title and the message in the center of the screen). The only thing that you should focus on is how the code is structured and broken down into seperate files.
We can actually copy and paste a lot of the code from
Lovey.vala to avoid
rewriting things. Not much changes, except for a few lines. So let’s start with
the easiest change, the
Main.vala file. All we have to do is take the main
function from the
Lovey.vala file and place it here, and wrap it in the
That's it. Save the file and close it. Let's move on to the
Now, open up the
Window.vala file and type in the following code
(don't forget to wrap the Window class into the
Lovey namespace). We're also
going to change the title of the application to “Lovey Refactored” and the
label's text in the middle of the window, to “Hello Again, I’m refactored!” (this is optional).
For now, the
Window.vala is all set. You can save it and now open the
Application.vala file and type (or copy and paste) the following code in it:
Compiling the code.
Now we can head into the
src directory and run the following command:
$ valac -o Lovey --pkg=gtk+-3.0 Application.vala Main.vala Window.vala
If everything compiles correctly you can now run this application with the following command:
And there you have it! Your app has been refactored and should now look like:
Note: You can now delete the
Lovey.vala file that we began with, in the project’s
It’s time for a build system!
So, why do we need a build system? A build system is going to make things really easy for us! It’s going to save us a lot of time from typing in repeated commands and adding new files to the compile command every time we modify, or add a new source file.
The new Meson build system.
As far as build systems go, we will be using the Meson build system. It is far easier to configure than Make, and far less error prone. Not to mention, it comes with support for Vala out of the box.
If you don’t have Meson installed, you can so do with the following command for Debian/Ubuntu based systems:
$ sudo apt install meson
Setup and configure Meson for our project.
At the root of the
project-lovey directory create a
meson.build file which
should then make your project’s root directory look like so:
$ tree ../project-lovey ../project-lovey/ ├── CHANGELOG.md ├── LICENSE.md ├── meson.build ├── README.md └── src ├── Application.vala ├── Main.vala └── Window.vala 1 directory, 7 files
and open up that
meson.build file and input (or copy and paste) the following:
Let’s give Meson a try!
Now that we have our
meson.build file all setup. Let’s compile our project
using Meson. From the root directory of the project, run the following command
(which should also produce the similar output):
$ meson build --prefix=/usr The Meson build system Version: 0.49.2 Source dir: /home/drodriguez/Projects/project-lovey Build dir: /home/drodriguez/Projects/project-lovey/build Build type: native build Project name: dev.vala.lovey Project version: undefined Native C compiler: cc (gcc 7.4.0 "cc (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0") Native Vala compiler: valac (valac 0.40.15) Build machine cpu family: x86_64 Build machine cpu: x86_64 Found pkg-config: /usr/bin/pkg-config (0.29.1) Dependency gtk+-3.0 found: YES 3.22.30 Build targets in project: 1 Found ninja-1.8.2 at /usr/bin/ninja
meson build command is complete, you should now have a
folder in your projects root directory. Now change into that directory and run
$ cd build/ $ pwd ~/Projects/project-lovey/build $ ninja [5/5] Linking target dev.vala.vala-dive. $
ninja command will make an executable file for you, with the same name as
your project’s name inside of your
meson.build file. Now you can run the
dev.vala.lovey using this command:
Later in this series, I will show you how to expand on Meson to include
sub-directories and other things such as post install scripts and whatnot. But
for now, this
meson.build file should do just fine for our purposes.
And there you have it! Our very own Project Lovey (v0.1.1) update is complete.
The code has been refactored and our meson build system is all setup and working.
Now when we make any changes to the code, we only need to run
ninja again from
build/ folder to recompile our project.