A C++ wrapper for Python story on Haiku

While I don’t use Haiku on a daily basis, mostly because I can’t do the things that I do on Linux, I still keep some kind of regular relationship with it. For the past two years it has been already installed onto its own disk, multibooting my box. It doesn’t really get much time share compared to Silverblue, which is my dev system os, but certainly gets more share than Windows.

Thanks to Haiku I met Godot, and now I’m using it on Silverblue to try to develop some games. Thanks to Haiku I met LMMS, and now I’m using it on Silverblue to try to create some sound FX and soundtracks for the games I try to make. On the other hand, while Godot supports C# to code games, and even I used Unity before, which uses C#, I decided to go with GDScript in Godot, mostly because two reasons: first, it’s similar to Python (I had done a simple python app a while ago), and second, there is no C# support in Haiku. I was thinking that when Godot would be available and functional (it’s available now, though non fuctional in my case) on Haiku, I could still keep using Godot, then on Haiku, just as I use it now on Silverblue, theoretically.

Haiku uses C++. I don’t know any C++. I tried a couple of times to do anything with C++ and, basically, it seemed too complicated. Then I thought I could try Python because it seemed simple enough, and quite straightforward to create simple apps using Glade and Gnome-Builder, exporting them as Flatpaks. I did try it, and with less effort than expected, I had a simple utility completed, let’s not talk about its quality now. After that Python looked even more appealing.

On Gnome, Python flatpaked apps integrate with the rest of the environment, they have their icons, and they act as any other regular apps. On Haiku, this is a little different, at least for what I know. A Python script can be executed, of course, but the only way I know of is by calling it with the interpreter: $>python script.py.

Img. 1 – Generic icon of Python Script on Haiku’s Deskbar

When calling the script like that, the icon that appears on the Deskbar is a generic icon, and the name of the Software is not there, it’s the whole name of the script with the extension. Does not look good. Does not look Haikuy.

The Goal

The idea is to do something that allows software made with Python to look like software made with i.e. C++ on Haiku. Look like. That is, double click launch, integration into the Deskbar with its own icon, and a proper name instead of a generic icon and the script name with extension, and to be listed in the Applications list, and be installed as a regular application.

This goal might sound way too easy to some, agreed, though with my little knowledge of both Python and Haiku, it ended up being way harder than expected. So I decided to write everything down here. That way I have a backup of the process, and it may serve some other to avoid the trouble.

The tools

For this small project the first thing needed is a computer running Haiku, everything was done on Haiku, of course, and used the following software:

  • Icon-O-Matic. The default icon editor that generates vector icons in a specific format HVIF that takes less space than regular SVG and supports different LOD, so only need to do the icon for 64x64bit size and the system scales down altering the LOD (level of detail) adapting it to the size.
  • Koder. A code editor available on Haiku that uses Scintilla, and understands a lot of different coding languages.
  • Paladin. The “default” development environment on Haiku, and only (please correct me if I’m wrong) works with C++ projects (for now).
  • Terminal. Well, the terminal. On Haiku, the Terminal comes with bash as default. Haiku has some degree of POSIX compliance, though that does not mean that all bash commands will be available.

Besides the software, I needed access to the Haiku API in Python, in order to create the interface, and the software in Python and then integrate it inside Haiku. Fortunately, there are Haiku API bindings for Python, and also Perl, though have to dig deep inside internet search to get there, so here is the link: Haiku API bindings for Python.

This post is structured in the following parts:

  • The Python Code (extremely simple application written in Python, using the Python bindings for the Haiku API)
  • The Icon (creating an Icon for our application, and converting it into something Haiku can use)
  • The Paladin (the default IDE, that we will be using to generate our final project)
  • The C++ wrapper (first approach at executing Python inside C++)
  • The embedded Python inside C++ (embedding the Python interpreter, the easiest, and simplest way possible, inside C++ code)
  • The package (making an installable package for our application)
  • The first install (installing the ready made package, issues)
  • The final install (redoing the package and final successful installation of our application)
  • Conclusions

The Python Code

  • Write the Python code script
  • Test the code in the Terminal
Img.2 – Python code in Koder

I called this Awesome, just because I thought that it would be awesome to achieve this goal, very simple, though for me a bit overwhelming, and just integrate Python software in Haiku. We should take into account that the approach presented here is only valid in certain situations. Others may vary and I’ll talk about them later.

First of all, the Python code:

from HaikuR1.ApplicationKit import Application
from HaikuR1.InterfaceKit import Window, TextView, B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE

app = Application("applicaton/x-vnd.Awesome")

class AppWindow(Window):
    def __init__(self, *args, **kwargs):
        self.textview = TextView(
              frame = [50, 50, 250, 140],
              textRect = [0, 0, 190, 90],
              name = "Aweview",
              color = "#000000",
        )
        self.textview.DoesWordWrap()
        self.AddChild(self.textview)

window = AppWindow(
    frame = [350, 350, 800, 600],
    title = "Awesome",
    type = B_TITLED_WINDOW,
    flags = B_QUIT_ON_WINDOW_CLOSE,
)

window.Show()
app.Run()

Once downloaded the Haiku API Bindings from Healynet, we need to install it onto our box in order to use it in our software, for that we have to unpack the ZIP/tarball file, open the unpacked folder, open a Terminal inside that folder and run ./build_python.sh. Once completed, the API is ready to be used in our code. In order to get the ZIP/tarball file, which is not as direct as it seems, we need to go to the Download Page. There we pick if we want a tarball or a ZIP, and we will be prompted to type a number before downloading. Not ideal, but doable.

After completion of the API installation, we will have a new Python module to use, the HaikuR1, which holds the bindings to 5 kits of the Haiku API, Application, Interface, Kernel, Storage and Support. More than enough for our purposes here, as we will only use the Application and the Interface kits. More on the Kits can be found in the Haiku Documentation.

This simple application will only have one window, and inside that Window a TextView. A TextView is an entry field that can be multiline. In the previous Python code we import the needed elements, Application, Window and TextView, and the type of window B_TITLED_WINDOW, and the flag B_QUIT_ON_WINDOW_CLOSE.

After the modules import, we define our application, app which is an Application, defined in the ApplicationKit module, from where we got it, with a MIME type of application/x-vnd.Awesome.

Then we state the application window’s class, we call it AppWindow, and it will need a Window (from the InterfaceKit) to be passed to. As this is a simple example, in the initialization, __init__ ,of the class we only add a TextView to the window, with the frame dimensions inside the window [xleft, ytop, xright, ybottom], so it will be 50 pixels away from the left and top border of the window and will extend 200 pixels wide and 90 pixels tall.

Inside that frame, we are going to define an input textRect which is as tall as the frame, but is a bit less wide (10 pixels). We call that TextView "Aweview", to differentiate it from other elements, and we set the color of the text that is going to be typed inside the TextView to black (#000000). I did this because by default the text was in some color I couldn’t really see because with a grey background color set for the document background in the system the text was barely visible.

Next we define our window which is an AppWindow that is going to be placed at x=350 and y=350 pixels from the top and left sides of the display. It’s going to be 450 pixels wide and 250 pixels tall. This window is going to have a name, Awesome, and is going to be Titled, so it is going to have the typical tab with the name at the top of the window. The last line, the flag, tells the system to quit the program when we click on the close button of the window.

In the last two lines, we just show the window, let it be visible, and tell the app to run.

Img.3 – The Python script called from the terminal

When running the script from the terminal, the window is created and we have a new entry in the Deskbar, Awesome.py, with its icon, which is a generic icon that we have not designed nor have anything to do with it.

The Icon

  • Design an icon in Icon-O-Matic
  • Save the icon as HVIF
  • Export the icon as RDEF

In order to create an awesome icon for our awesome script, we are going to use Icon-O-Matic, the default software used to create icons in Haiku, that produces HVIF (Haiku Vector Icon Format). It takes some time to get a hold on how to use it (I’m still newbie at it), though is not that hard to do things once you know some basics.

Img.4 – Icon-O-Matic 64×64 pixels blank slate

Our awesome icon is going to be a simple Piramid that we’ll pimp to resemble sort of an A, so we start adding Shapes. With the knowledge I have now, which is quite scarce, I just add ‘shape with path and style‘ in the Shape section. On the top-left part of the Icon-O-Matic window we see the different sizes of the Icon where we can check if our LOD settings match our needs/requirements when the icon is smaller. At all time, while we design our icon, we can see how it will be shown by the system in 32 and 16 pixels besides the design size we pick, 64×64 pixels.

Img.5- Icon-O-Matic with the Awesome Icon finished
Img.6 – Project files (python script and icon)

So now we have the icon finished, we have our Python script, now what? How can we bring them together so when we call Awesome.py, we get Awesome.hvif on the Deskbar? Well, first we need to do some processing to the icon, as HVIF file format seems can’t be used from applications to tell the system to use that icon instead of another.

Img.7 – Exporting Icon as RDEF file

In order for the icon to be used by our script, first we need to export it as RDEF, which is a resource file format, and which is what we are going to use later. Yes, we can’t use it like this just yet. We still need to go through another process.

Img.8 – Awesome.rdef, the file and its contents

As we see in the content of Awesome.rdef, we are presented with a lot of characters forming a resource block, but we still don’t know what to do with that, and within that gibberish there is nothing related to our Icon’s name, nor our Python script. Then, what’s next?

The Paladin

Definition of paladin
1 : a trusted military leader (as for a medieval prince)
2 : a leading champion of a cause

  • Create a project in Paladin
  • Add project files
  • Convert the RDEF file into RSRC

Maybe not the champion of a cause nor a military leader, though a big helper here, Paladin is the “default” IDE on Haiku, for developing C++ software, and its what we are going to use for the next step.

Upon launching Paladin, we are prompted with the project creation/selection window:

Img.9 – Paladin’s Start window

In our case, we are going to create a new project, so just click on the ‘Create a new project’ button and we will be facing the project type window below. We are going to call our project Awesome, the Target name is going to be Awesome too, the Project type will be an Empty Application, selected in the Project Type drop down menu. We are going to untick the Create project folder because we already have a folder where we stored our Awesome.py, Awesome.hvif and Awesome.rdef files, and this folder is the location we are going to choose for our New Project files. Last, we are not going to use Source Control. Then, just click on Create Project and we are good to go.

Img.10 – Our Awesome new Project type

Once the new project has been created, the only thing different from before is the new file, Awesome.pld that we can see in the Awesome folder. Paladin: Awesome window is absolutely empty. So, then again, what’s next?

Img.11 – Our Awesome project in Paladin

Until now, we have created a Python script, a vector icon, and a Resource file, but we don’t know, yet, what to do with them to have the icon shown on the Deskbar. We know that we need a resource file, a full resource file, not just the file we just created exporting the icon into an .rdef format file. So,we are going to change the name of Awesome.rdef into AwesomeIcon.rdef, and inside Paladin, we are going to add a new file to the project, and we are going to call this file Awesome.rdef. To create the file, we just click on the ‘Project‘ menu on the menu bar, and on the drop down menu, click on ‘Add New File (Alt+N)‘. A popup window appears to type the name of the file, just write Awesome.rdef in the text input field, and make sure that we don’t have the “create source and header file” checkbox ticked.

Img.12 – Our Awesome project (Paladin), our project files and Awesome.rdef file contents

If we open the newly created file, our Awesome.rdef we can see its contents inside a text editor (we are using Koder for this project as text editor) and we notice at the bottom of the window in the screen shot that it says resource large_icon array.... This is what we have to change into our AwesomeIcon.rdef contents.

Img.13 – Icon section in Awesome.rdef. Our AwesomeIcon.rdef file contents

So we are going to remove the whole resource large_icon and mini_icon, and paste there our AwesomeIcon.rdef contents.

Img.14 – The new Awesome.rdef file with our icon pasted

The new content of our resource file (Img.14) already includes our icon. Notice that the resource icon is “vector_icon“, not “large_icon” nor “mini_icon“, as stated in the default .rdef file, and we have removed the “(your resource id here) #VICN” that appeared in our AwesomeIcon.rdef file. Inside Haiku there are only vector icons now, no mini, no large, no bitmap, all are vector icons.

Besides adding our icon to the resource file, we are doing some retouching there. First we must change the resource app_signature, and we will change it to “application/x-vnd.Awesome”, which is what we stated inside the Python script Awesome.py, and we will change the short_info text to “An Awesome app”, and the long_info text to “An Awesome app that tries to integrate Python scripts into Haiku”. With that we have everything in the Awesome.rdef file ready for the next process.

Img.15 – Creating a RSRC file

Our RDEF file is of not much use as is, so we need to “compile” it in order to use it in our project. To do that, we have to launch a Terminal on our project folder, and call the command:

$>rc Awesome.rdef

After that, a new file appears in our project folder, Awesome.rsrc. We now need to add it to our project in Paladin, in order for Paladin to use it inside the project. To do that, we click on the Project menu, select Add files…, and pick the Awesome.rsrc file we just created, thus our project and project folder should look like what is shown in the next image:

Img.16 – Our Awesome project

With what we have now, we still can’t integrate anything into anything. Actually, right now, the only way to launch our Python script is still by typing:

$>python Awesome.py

in the Terminal, and we will still get the generic icon, not the awesome one we just designed with such effort. There is no way to double click on it, and there is no way to get our awesome Python app into the Application list. In order to achieve that, we are getting closer, we still have to go through some steps. The next one will be the C++ simple wrapper.

The C++ wrapper

  • Create a C++ file and add it to the Paladin project
  • Execute the Python script the simplest way possible
  • Launch from terminal and double click

With the project files we have until now, if we Run the project in Paladin we get errors:

Img.17 – Errors thrown when running our project as in Img.16

Paladin manages C++ projects, and we still don’t have any C++ file, no headers, nothing. Actually, I have no knowledge of C++, not that I know a lot about Python either, but we’ll try to get there with some reading the docs and searching, and searching.

At this point, we need a C++ file. It should be simple as we have our program written in Python, and we only want that C++ file to let our Python program to appear to the user as a Real, Regular Haiku software made in C++.

In the Paladin window, we click on the Project menu, then Add new file (Alt+N), and we call the file main.cpp. We won’t be needing a header file for this project, so just create the main.cpp file and nothing more.

Img.18 – Our first C++ file

Once created, we have an empty C++ file, and inside this file is where we have to manage to do the right things to get our python script up and running. And this is the tricky part, at least for someone who knows nothing about C++ and with limited knowledge of Python. The first thing that came to my mind at that stage was just find a way to call a Python script from with C++ just like it’s done in the Terminal:

#include <stdlib.h>

int
main(void)
{
    system("python Awesome.py");
}

Wow, now that is a pretty complex CPP code. And when we Run it from Paladin, we get this:

Img.19 – First run of our program from within Paladin

That’s it, we are done. We have the icon on the Deskbar, we have our awesome Python window there, and when we click the close button of the window, the program closes and the icon disappears from the Deskbar. Notice that the icon on the Deskbar says Awesome.py, mmmm… not there yet, though close.

Also, we see that there is a new icon in our Awesome folder, an icon named Awesome, this is our new program, our Awesome program, also in the Terminal we see the new Awesome executable file. Well, if we double click on the new Awesome icon (the executable) nothing happens, and if we type Awesome in the Terminal, yes, we can launch or Awesome app, though it has lost its wonderful and awesome icon on the Deskbar. So, no, we are not there yet. Getting closer.

Some people (@donn from the Haiku Community) told me that the double click issue might have something to do with the path to the Python script, so I changed the code a bit to this:

#include <stdlib.h>

int
main(void)
{
    //system("python Awesome.py");
    system("python /boot/home/Projects/Wordpress/Awesome/Awesome.py");
}

Rebuild the project, and there we have it. With the absolute path, we can double click on the Executable icon and launch our awesome software. When double clicking on the executable icon, we get our icon on the Deskbar, though still says Awesome.py, and when we call our executable from the terminal, we get the generic icon. So we are not there yet.

Something is missing here. Besides, an absolute path is of no use to install this on other systems, as each user will have a different path. We must think of a solution for that. Also, we don’t want the file extension to be shown on the Deskbar, we just want to see our program name, Awesome, shown by the icon, not the name of the Python script file. And we want consistency, whether we double click on the executable icon, or we call the program from the terminal, we want the same icon appearing on the Deskbar, and we are not getting that yet.

It couldn’t be that easy.

The Embedded Python inside C++

  • Integrate Python inside the C++ file with Python.h
  • Include the proper header
  • Add the proper library to the Paladin project
  • Verify in terminal and double click

The simple wrapper we made before has proven not enough for our purposes, so we need a different approach. I must tell that I didn’t know anything about this before facing this project. So when the system command proved itself not worth for our purpose I ended up searching and searching across the web, and found that we could embed Python inside another application.

At that time, another user of the Haiku Community (@aarroyoc) pointed out that PyBind11 could be used to gain access to the C++ Haiku API from Python. Wow. I had no idea that PyBind ever existed. I read his post with lots of interest, and it looks like the solution for another task I have waiting in the drawer, the piece of the puzzle that will allow me to complete that task. Though I presumed that his approach was different from what I set as goal for this simple project. After reviewing carefully what he wrote, I decided to go the way stated in the Python documentation.

So what we are going to do next is try to embed the Python interpreter inside our little C++ code. We will be making the smallest C++ app possible that includes a Python interpreter that will launch our awesome Python script.

That Python documentation page tells us about different levels of embedding, and for our little project we are going to go with the Very High Level of Embedding, we don’t need anything more complex for now. The example provided for this embedding type is the following:

#include <Python.h>

int
main(int argc, char *argv[])
{
  Py_SetProgramName(argv[0]);  /* optional but recommended */
  Py_Initialize();
  PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
  Py_Finalize();
  return 0;
}

Nonetheless, we are going to use a slightly different code for our testing purposes:

#include <Python.h>

int
main(void)
{
  Py_Initialize();
  PyRun_SimpleString("print('hello world from Python embedded')");
  Py_Finalize();
  return 0;
}

This very high level of embedding as it is said in the Python doc:

The simplest form of embedding Python is the use of the very high level interface. This interface is intended to execute a Python script without needing to interact with the application directly. This can for example be used to perform some operation on a file.

We don’t need to interact with anything, we just want to run our script, that is already an application, and let the Python application handle everything. Our wrapper will just read the script and execute it. Over. We don’t need API access, no need to pass information between the C++ and the Python files, nothing.

What this simple code does, theoretically, is:

  • Py_Initialize
    Initializes the Python interpreter,
  • PyRun_SimpleString
    Executes a symple Python string, in our case we just call a print(‘hello world”) type of command, just for testing purposes
  • Py_Finalize
    Once done, we close the interpreter so we can quit safely

If we run this code from our Paladin, we get this:

Img.20 – <Python.h> header does not exist error

I must say that this is the first time I use Paladin too. So this little project is a bunch of firsttimes, and in such situation, firsttime success is rare, to say the least. In this case, we need to change the include, adding where it is, which version of Python, the folder where that header is. After we search, we find that the Python.h file we need is in the python3.7m directory. Thus, we change the line to this:

#include <python2.7/Python.h>

Now we have the header found, but another issues come around, spitting at us that none of the commands are recognized, nor Py_Initialize, nor Py_Finalize, nor PyRun_SimpleString. Maybe we need to add something more to our project. Maybe the Python library. In Paladin we can select the libraries our project is going to use in the Project menu, Change system libraries… option:

Img.21 – Managing system libraries

Well, looks like nothing can be done here. There are no scroll bars, we can’t scroll down with the mouse scroll wheel, what we see now is what we get. There are plenty of libraries too, not just the ones we see in Img.21, just Paladin does not allow us to see more and select different ones. It seems to be a little bug, that needs a circumvent. And maybe we also need to add the paths.

Img.22 – Adding the libpython, and Standard output

We have to manually add the Python library, therefore we need to do a search in order to find it in our system. We’ll be using Python 2.7, because it is installed by default in Haiku, and besides, the Python bindings to the Haiku API only work on this version. At least they don’t work on Python 3.7. Once we found the libpython2.7.so, we just drag it and drop it in the Paladin project window, and there we have it, with Awesome.rdef, Awesome.rsrc and our main.cpp.

To test if what we have done is correct, we go to the menu, Build, and we select Run Logged (Shift+Alt+R) option, to get the Monitor window. That way we can see the output in the Starndard Our panel. As we can see. We did success with integrating the Python interpreter in our little awesome C++ file.

Img.23 – Launching Awesome from terminal

Still, double click doesn’t work. We just made a simple “Terminal” application. If we call Awesome from the terminal, we get the Python print command as expected. For what we have done until now, it seems to work fine. Then, we just need to try calling our awesome script instead of the print method, and if it works, we are almost done.

In order to do that, we are going to change our C++ code a bit:

#include <python2.7/Python.h>

int
main(void)
{
  Py_Initialize();
  //PyRun_SimpleString("print('hello world from Python embedded')");
  FILE *pyscript = fopen("/boot/home/Projects/Wordpress/Awesome/Awesome.py", "r");
  PyRun_SimpleFile(pyscript, "Awesome");
  Py_Finalize();
  return 0;
}

What we do here:

FILE *pyscript = fopen("/boot/home/Projects/Wordpress/Awesome/Awesome.py", "r");

is declare the variable pyscript which is going to hold or startup Python script, we pass the whole global path to the fopen command, therefore it will be found by the Tracker when we do double click on the application icon, and we open that script in Read Mode as we do not want to do anything with it but execute it.

Once we have our awesome script opened, we just execute it, with:

PyRun_SimpleFile(pyscript, "Awesome");

Now we just need to test it building it in Paladin,

Img.24 – Our Awesome application finally running

With what we have done, we already have our Awesome Python application integrating into the Haiku environment. We can launch it from the terminal too, and the result will be the same. We can now double click on the Awesome icon (the executable), and it will run. We have succeeded at integrating the Python interpreter into our little C++ wrapper to let our Awesome Python script to look like a full blown Haiku application.

But it will run as long as we have everything where it is now, that is, we have hardcoded the path to our Awesome.py Python script. If we change its location, our awesome application will fail to work. On the other hand, we can’t launch our Awesome application from the Deskbar, we haven’t installed it, and we haven’t got the application ready to distribute. If we stop here, we must tell other user where to put everything in order for our Awesome application to work. That means we are not through with this little project yet. It’s not so awesome yet.

The Package

  • Create package folder structure
  • Create file .PackageInfo
  • Add files to the package folder structure
  • Create the application package

While what we have achieved already is quite appealing, there is something else that needs to be done, in order for our Awesome application to be fully awesome, instead of awenone. We need to make a Haiku package, an HPKG to distribute and install our Awesome application in the right place of our system. How do we do that? Let’s find out.

For this purpose, we need to get into the Haiku packaging format and command, as documented here. We will build a package with the package command that will allow us to install our Awesome application and have it shown in the Deskbar Applications list.

In order to create a package, we need a package definition file, that is called .PackageInfo, as specified in the previous documentation link. But before we create this file, we need to create a folder structure for our package, thus, when we do create the package, everything is in its place, and we won’t have issues when installing our newly brewed Awesome application.

Img.25 – Our Awesome application packaging preparation folder

First of all, we create a new folder to prepare our Awesome application for packaging, and we call it Awesome-0.0.1 with the following elements inside:

/Awesome-0.0.1
              |_  .PackageInfo
              |_  /apps
              |_  /data
                       |_  /deskbar
                       |          |_  /menu
                       |                   |_  /Applications
                       |__  /Awesome

The text file .PackageInfo is empty for now. The name of the folders are not arbitrary, they should be those, and there is a reason for that. Only the Awesome directory is ours, as all the rest relate to Haiku system folder structure.

Img.26 – Haiku’s /system/apps and /system/data folders

On Img.26 we see the folders /boot/system/apps and /boot/system/data. New applications should be installed into /boot/system/apps, and application data should be stored in /boot/system/data. Inside /boot/system/data we have a folder called /deskbar which is an application too, and there are also folders for other applications, thus we should create a folder for our Awesome application there, and we decided to call it /Awesome. Inside the /deskbar folder, there is a /menu/Applications tree too. This folder structure is what we match in our package folder structure. We are arranging the package folders exactly how they are arranged in the system:

  • inside /apps we will place our Awesome executable file
  • inside /data/Awesome we will place our Python Awesome.py script
  • inside /date/deskbar/menu/Applications we will place a link to our executable

There is a little thing we need to retouch in our code in order for this folder structure to work:

#include <python2.7/Python.h>

int
main(void)
{
Py_Initialize();
//PyRun_SimpleString("print('hello world from Python embedded')");
FILE *pyscript = fopen("/boot/home/Projects/Wordpress/Awesome/Awesome.py", "r");
PyRun_SimpleFile(pyscript, "Awesome");
Py_Finalize();
return 0;
}

We must change the line where we pass the path to the Awesome.py script to this:

FILE *pyscript = fopen("/boot/system/data/Awesome/Awesome.py", "r");

We do like this because upon installation of the package, as we define it in our package folder structure, we will be saving our script in that path, not in our Projects folder. Besides, we don’t know what folders a user may have inside the home folder. By doing this we guarantee that our Awesome app will work everywhere.

If we change the line and we build the project, it won’t work, as there is no Awesome folder, nor an Awesome.py script inside it, both in the /boot/system/data folder. They will be there when installing, not just there yet.

Img.27 – Package folder contents

In the apps folder we placed the executable, the Python script inside the /data/Awesome, and the link to the Applications menu, we have it empty, because we don’t have our Awesome App, still installed in the system. Though there is a way to get the link there, I wasn’t able to get it, so I did it in a different way.

Now, according to the .PackageInfo documentation, we have the file already created, therefore we need to fill it with content. Be careful when filling this file, as some elements are a bit tricky. Better go through the documentation a few times and check the examples available.

Img.28 – Our .PackageInfo file filled with stuff

With the .PackageInfo file ready, we are ready to create the package. Yes, we still don’t have the link to place in the Applications folder. We will have it soon.

We first create an empty package, and to that package we will add our files, the executable as well as the script. In fact, we will add the folders we created. In order to do that, we open a terminal in the folder where we are preparing the package (Img.25):

Img.29 – Creation of an empty package

Creating the package is made from the terminal with the command:

$>package create -b Awesome-0.0.1.hpkg

That command creates an empty package in our packaging folder, where we have our .PackageInfo text file and the folders /apps and /data.

After that, we add those two folders to our package with

$>package add Awesome-0.0.1.hpkg apps data
Img.30 – Adding our files to the package

The First Install

  • Installing the package from the HPKG
  • Creating a proper symlink to add to the final package
  • Verify the installation works

With this step the package is “complete”, and “ready” to use. Let’s try to install it then with double click on our recently created package:

Img.31 – Installing the package locally

Once the installation procedure is over. For our little project it won’t take long, we can verify that our Awesome application is installed along the other applications, and that our Awesome.py Python script is inside the /boot/system/data/Awesome/ folder, and we can verify that everything works if we double click on the Awesome icon inside /boot/system/apps/. We can even launch our Awesome application from the terminal just by typing:

$>Awesome
Img.32 – First installation, working with an “issue”

There is one thing still missing, which is our Awesome application showing on the Applications list on the main menu. For that we created the path /data/deskbar/menu/Applications in our packaging folder (Awesome-0.0.1), but we left it empty. We should place there a link, a symlink to our Awesome application which is inside the /boot/system/apps folder, and now there it is.

The Final Install

  • Create the final package
  • Install the final package
  • Verify that the final package works, from Terminal, double click, and Applications menu
Img.33 – Grabbing the link for our package

Now that we have installed our Awesome application, it is already inside the /boot/system/apps folder, therefore, we can create a symlink inside our /data/deskbar/menu/Applications folder inside our packaging folder. To do that, we drag, with the right button of the mouse, our Awesome application from the /boot/system/apps/ folder into our packaging folder /data/deskbar/menu/Applications, on dropping the Awesome application there, we will be prompted to

  • Create link here
  • Move Here
  • Copy here

Just pick the “Create link here”, and then we will have our link to our Awesome application ready to be used. Now we have to redo the package again. But first, lets uninstall our Awesome package. We launch the HaikuDepot application and search for “awesome”, our Awesome package will appear on the list, ready to uninstall

Img.34 – Uninstalling the Awesome package in HaikuDepot

We will notice that once we uninstall our Awesome package, the link we’ve just created appears to be broken:

Img.35 – Broken link

Don’t panic. It’s normal, as the Awesome application has been uninstalled an is no longer available inside /boot/system/apps. It will be again when we install it, now with the link. Now we need to go back to redo the package. First we remove the old one, and then we redo the package as we did before:

$>package create -b Awesome-0.0.1.hpkg
$>package add Awesome-0.0.1.hpkg apps data

Remember to do this inside the packaging folder, which was /Awesome-0.0.1. Everything will look exactly the same as in Img.30. The difference is inside our new package.

Installing the new package, will finally give us the link to our Awesome application inside the Main menu, and with that we are finally done. We completed the whole process of bringing a standalone Python application to become a standalone Haiku application:

Img.36 – Finally, Awesome appears in the Applications menu

Conclusion

I did learn many stuff I had no idea about before attempting this little project, lots of things about the Haiku OS and also about Python. One of the reasons to write this down, the main one was for me to remember what I have done, so the next time I attempt something similar, I have a background page to take a look at that may help me then. Also, others might find this helpful, useful as a reference. I tried to be as clear as possible so anyone could understand what I was doing.

The goal was to make a simple wrapper to add the Icon and Menu integration for applications written in Python that were self-contained, that is, every interconnection with the system was done within the Python code, thus calling them by:

$>python application_name.py

would launch the standalone Python application. In such cases the small wrapper provided in here seems like a valid option to integrate such kind of applications inside Haiku. There might be better options, though I just wanted to find the simplest, easiest one that I could achieve with my little knowledge. I’m quite aware that lots of improvements can be done on this approach, though for now, let’s leave it like this. Different use cases will require different approaches, so the method presented here might not be suitable for such cases.

After finishing this little project, two more advanced ones are waiting in the queue. Both Haiku related, both Python related. Those two will also be explained here when I have time to face them.

You can get the whole project at Github.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s