Categories
Computers and IT

Faster Command-Line Coding with Bakefile

A while ago I was using a wrapper for gtk called gtkmm. I liked it and the program I created using it held up very well. The gtkmm wrapper provides a convenient way to use gtk itself. This sped up my development and use of gtk and helped me focus on the structure of my program.

Later on, I switched from gtkmm to wxWidgets. I was still using GTK underneath when on Linux, but now structured through wxWidgets. The reason for that switch was to gain the ability to make the program for Windows where GTK is primarily Linux and UNIX oriented. The wxWidgets project is setup in a way where I can compile the same code for Windows. For the longest time, I was interested in having the program I was working on run on Windows, Apple, UNIX, and Linux. The saw the wxWidgets project was the most straightforward way for me to achieve that.

After I successfully produced a Windows version of my program, I marinated on the accomplishment. After a few months, I decided I did not want to support Windows since the process is not trivial. After doing it once and knowing that I can do it if needed, I decided to concentrate efforts on Linux and BSD UNIX. This helps me optimize my efforts and tools.

I decided to look further into GTK. Between the years 2012 and 2019 I learned a valuable lesson about mainstream native code GUI libraries. The vast majority are written in C. I include many fundamental video game libraries in that group. I have written several GUIs in C++. Some of them used C++ as the language but the library functions I called into were written in C. Sometimes that caused problems but I always worked around those issues.

I realized that gtkmm, although really good, is not the type of project that will cleanly abstract the entirety of GTK. Bits will be missing from the abstraction. That is okay but in this case, the more I read about GTK, the more I realized what I was missing. The absence of certain peices meant I would inevitably recreate something GTK already had available but not visible in the abstraction layer. That is not a case against gtkmm, I think it is a valuable project, but there are many programs written directly in GTK and they work out very well.

I will write more about that later.

Preparing for GTK 4

The strongest GUI foundation in the Linux/UNIX world other than KDE is GTK. Since Linux is my primary environment with BSD as my secondary, it makes sense for me to consolidate on GTK. Sometime in the year 2020, version GTK 4 will be released. You will not see GTK 4 in wide use until about 2022. However, the earlier I get started with more direct access to GTK, not through a wrapper, I will have an easier time adopting the advances coming in GTK 4.

I decided to do different things this time.

Consistent Ingredients

I decided to add a few fundamental tools. They include:

  • Bakefile
  • Apache Portable Runtime

I was using a few tools in earlier versions of my project that included SQLite, cURL, and XML2. I tried C++ tools like POCO, Xerces, and SFML but I usually encountered some deficiency that led me to alternatives such as cURL or XML2. The code examples for those latter tools simply worked better and more reliably. Ironically, those tools are all C rather than C++ libraries.

Although I was using C++ for its language features and structuring capabilities, my best third-party code libraries choices were often written in C. Sticking with a third-party library because it was C++ when there was a better choice in C seemed too obstinate. Although I went to great lengths to wrap a lot of C in a C++ shell, whenever I looked back on the finished result, I got a sense of code in multiple dialects. New school, middle school, and old school. Eventually, I realized some advanced features or best practices of C++ were incompatible with the way some C libraries are defined or intended to be used. This often led to workarounds which I think is fine. Workarounds is part of the process but I do seek to minimize them for a cleaner result.

I think 7 years is long enough to experiment with C++ vs C. When it comes down to fundamental third-party libraries (code you didn’t write but that you use) typical in GUI programs written in native code focused on Linux and UNIX environments, I think C actually wins hands down. Qt/KDE are a close second but I am not a fan of KDE. GTK seems more efficient in general and it is spirit of economy that goes into Linux and UNIX itself.

I am no longer using astyle code formatter. I switched to indent with just the default settings.

My final set of ingredients may eventually consist of the following:

A Better Build

One of the steps I have taken to prepare for this new wave of development is to change the way I compile and link application level executables and libraries. The previous projects used either Bash scripts or hand crafted make files. I read that wxWidgets use Bakefile and I decided to investigate. I decided I like Bakefile. The advantage of Bakefile is I will personally spend far less time stitching together command-line compile instructions. Bakefile automates this in a clean way.

I have one word of caution about a tool like this. Learning Bakefile does not eliminate the need to know how to compile code manually. Bakefile is a reliable shortcut, but best use comes from those who know the manual way of compiling and linking code.

I did read the GNU Automake manual and decided that Autotools is a great solution for deployment but not development. I think Bakefile is the right tool for faster iterative development that takes advantage of a GNU Make but does not force you into extensive deployment level build system setup before you even create your first executable.

I also looked into Meson. GTK and many projects related to GTK have switched to Meson. I think that is great for GTK but I put Meson on the same level as Autotools. Meson is top heavy for a smaller GUI project.

I will not go into more depth about SQLite, cURL, or XML2 because I’ve covered those in detail in my other posts. I’ve written many pages about them. Instead, I am going to present Bakefile.

GTK 3 Manual

The GTK manual has a hello world example. You will not find many good PDF versions of the GTK manual and so I created one using pandoc. The pandoc program, which is written in Haskell, can convert from one document format to another. After many, many, many hours of experimentation due to the size of the GTK information, I settled upon converting from HTML to ODT. The ODT format is what is used in LibreOffice. The advantage of NOT converting straight to PDF is I can edit the combined HTML in LibreOffice and the use LibreOffice to export to PDF.

That is what these files represent. Each one I made by hand and cleaned up the formatting/layout just a bit. I made them for personal use but am sharing them here. I say it that way because I have not fully automated the process of creating these and due to time, I do not promise I will have updates for subsequent releases of GTK.

Previously, I used HTMLDoc to create a GTK manual but that no longer work quite as well. That is when I explored Pandoc. I still use HTMLDoc for simple source documents but Pandoc is more robust, industrial grade, and flexible.

A pandoc invocation will look like this:

pandoc –from=html –to=odt –standalone –file-scope -o /tmp/gtk_part1.odt gtk.html gtk-getting-started.html ch01s02.html ch01s03.html ch01s04.html ch01s05.html gtk-resources.html gtk-question-index.html chap-drawing-model.html chap-input-handling.html

That will create a LibreOffice readable odt file based on part 1 of the GTK website. I went in, cleaned it up a bit and then exported to PDF from within LibreOffice.

Hello World GTK

After I made these manuals, I then read through each of them. Part 2 is the largest and so I skimmed through it for the parts that interested me but Part 1 has the example code I am about to show.

Many programming tools use the hello world concept. GTK demostrates basic capability in the hello world example. In using hello world GTK, I am able to make a solid hello world Bakefile. My real objective in the beginning is to make sure the foundation of Bakefile will meet the objective of faster C code iterations.

Hello World Bakefile

The steps to quickly create a program file are as follows:

  • Create main.c
  • Put the hello world example from GTK manual in main.c
  • Save the file, main.c
  • Create gtk_hello_world.bkl
  • Put the hello world example from the Bakefile manual in gtk_hello_world.bkl
  • Create a script called create_make.sh
  • Create a script called build.sh

I made a custom version of the Bakefile manual using pandoc.

Bakefile.pdf

The bakefile named, gtk_hello_world.bkl looks like this.

The important parts if you are coming from the experience of command-line compile are cflags and ldflags. That bridges the gap between a high-level XML description like you have in Bakefile and the actual invocation you’d do on the command-line.

The next part is the create_make.sh which uses the bakefile to produce an actual makefile. You only have to run create_make.sh anytime dependency configuration changes. An example is adding a new file to the project or changing the version of a library that is referenced.

This is the actual script we are working towards. The build.sh script is very simple and it just invokes make using the makefile produced by the create_make script. It is the script that will be ran each time the code has to be compiled following a source code update.

Run the file, create_make.sh and this is what you get.

Notice that it is a full makefile. You do not have to hand craft make files anymore nor custom compile scripts. This simplifies the process. You end up with a makefile which is better than a custom compile script because make will compile what needs to compile and exclude that which is still up-to-date so your code/compile/link/debug cycle is faster and more productive.

I’ve pushed the code to a remote server (actually a local build server-ish virtual machine) via SSH using an SSH key authentication (instructions at Digital Ocean’s website). All the initial pieces are in place.

All I have to do now once I’ve made edits to code is run build.sh which will trigger GNU Make which will use the makefile.

I get the file gtk_hello_world as an executable file I can run. Through Bakefile, I now have graphical IDE level productivity on the compile/link cycle available without the IDE.

You can find the full example project on github at the following website address:

https://github.com/michaelgautier/gtk_with_bakefile

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.