My fifth day with Haiku — let’s port some apps

probono
20 min readJul 14, 2019

--

TL:DR; Noob seeing Haiku for the first time; trying to port over some applications from the Linux world.

My first application ported to Haiku and packaged in its hpkg format

Recently, I discovered Haiku, a “shockingly good” desktop operating system. Today, I will investigate how to bring new applications to that platform. The point here is to describe from the perspective of someone who has compiled applications for Linux before, the first-time experience of coming to Haiku. So forgive me all the stupid mistakes I am going to make in the process, after all, it’s not even been a week yet since I first booted Haiku…

I want to do three things:

  • Port a simple command line tool
  • Port a graphical Qt-based application
  • Package them in the hpkg format (although I am still thinking about bringing AppDirs and AppImages to Haiku…)

So, let’s begin. The Documents and Development sections on the website and the HaikuPorts wiki should hopefully point me in the right direction. There is even a book available online (PDF), BeOS: Porting UNIX Applications. That it is 467 pages and that it is from 1997 is hopefully not a bad omen. I hear from a Haiku developer that “it is so long because BeOS was not POSIX compliant”, but since Haiku “largely” is, I hope that things won’t be that difficult.

Porting a simple command line tool

My first idea was to port avrdude but it turns out someone has already done that. Long time ago.

First try: nothing to see here

What one doesn’t realize (given that the OS has not even seen 1.0 yet) is that there is already a 10+ years history of porting software to Haiku.

Second try: would have to rewrite

So I am going for ptouch-770, a command line tool to operate my Brother P-Touch 770 label printer. I print the labels with it you may have seen in the previous episode of this article series on Haiku. Some time ago, I wrote a little GUI for it in Python (but since it uses Gtk+ which is not available on Haiku, I assume that I will have to rewrite it, which will be a good learning opportunity).

Brother P-Touch 770 label printer. Can I make it work in Haiku?

I am told that the Haiku package manager is aware of libraries and commands. So if I get a “can’t find libintl!” from configure, I can do a “pkgman install devel:libintl” and it will find the appropriate package. Similarly, “pkgman install cmd:rsync”, etc.

Except when it doesn’t:

/Haiku/home> git clone https://github.com/probonopd/ptouch-770
Cloning into 'ptouch-770'...
remote: Enumerating objects: 134, done.
remote: Total 134 (delta 0), reused 0 (delta 0), pack-reused 134
Receiving objects: 100% (134/134), 98.91 KiB | 637.00 KiB/s, done.
Resolving deltas: 100% (71/71), done.
/Haiku/home> cd ptouch-770//Haiku/home/ptouch-770> make
gcc -Wall -O2 -c -o ptouch-770-write.o ptouch-770-write.c
ptouch-770-write.c:28:10: fatal error: libudev.h: No such file or directory
#include <libudev.h>
^~~~~~~~~~~
compilation terminated.
Makefile:16: recipe for target 'ptouch-770-write.o' failed
make: *** [ptouch-770-write.o] Error 1
/Haiku/home/ptouch-770> pkgman install devel:libudev
100% repochecksum-1 [65 bytes]
Validating checksum for Haiku...done.
100% repochecksum-1 [64 bytes]
Validating checksum for HaikuPorts...done.
*** Failed to find a match for "devel:libudev": Name not found
/Haiku/home/ptouch-770> pkgman install devel:udev
100% repochecksum-1 [65 bytes]
Validating checksum for Haiku...done.
100% repochecksum-1 [64 bytes]
Validating checksum for HaikuPorts...done.
*** Failed to find a match for "devel:udev": Name not found

Probably udev is too Linux-y, and hence does not exist on Haiku. Which means that we need to patch the source code that we are trying to compile here.

Uh, this is way over my head. I would not know where to even start.

Third try

I think it would be useful to have tmate available on Haiku, so that I could let Haiku developers have a terminal session into my machine in case things go wrong. Instructions say it’s a matter of

./autogen.sh
./configure
make
make install

Doesn’t look too bad, so why not give it a try on Haiku, shall we?

/Haiku/home> git clone https://github.com/tmate-io/tmate/Haiku/home> cd tmate//Haiku/home/tmate> ./autogen.sh
(...)
/Haiku/home/tmate> ./configure
(...)
checking for libevent... no
checking for library containing event_init... no
configure: error: "libevent not found"
/Haiku/home/tmate> pkgman install devel:libevent
(...)
The following changes will be made:
in system:
install package libevent21-2.1.8-2 from repository HaikuPorts
install package libevent21_devel-2.1.8-2 from repository HaikuPorts
Continue? [yes/no] (yes) :
100% libevent21-2.1.8-2-x86_64.hpkg [965.22 KiB]
(...)
[system] Done.
checking for ncurses... no
checking for library containing setupterm... no
configure: error: "curses not found"
/Haiku/home/tmate> pkgman install devel:libcurses
(...)
*** Failed to find a match for "devel:libcurses": Name not found
/Haiku/home/tmate> pkgman install devel:curses
(...)
*** Failed to find a match for "devel:curses": Name not found

At this point I am opening the HaikuDepot GUI and search for “curses”. Sure enough, something shows up which gives me a clue for en educated guess:

/Haiku/home/tmate> pkgman install devel:libncurses
(...)
100% ncurses6_devel-6.1-1-x86_64.hpkg [835.62 KiB]
(...)
./configure
(...)
checking for msgpack >= 1.1.0... no
configure: error: "msgpack >= 1.1.0 not found"
/Haiku/home/tmate> pkgman install devel:msgpack
(...)
*** Failed to find a match for "devel:msgpack": Name not found
/Haiku/home/tmate> pkgman install devel:libmsgpack
(...)
*** Failed to find a match for "devel:libmsgpack": Name not found

Again, I resort to the the HaikuDepot GUI, and indeed, I find something: “devel:msgpack_c_cpp_devel”. Why are the names so weird?

/Haiku/home/tmate> pkgman install devel:msgpack_c_cpp_devel
100% repochecksum-1 [65 bytes]
Validating checksum for Haiku...done.
100% repochecksum-1 [64 bytes]
Validating checksum for HaikuPorts...done.
*** Failed to find a match for "devel:msgpack_c_cpp_devel": Name not found
# Why is it not finding it? To hell with the "devel:".../Haiku/home/tmate> pkgman install msgpack_c_cpp_devel
(...)
The following changes will be made:
in system:
install package msgpack_c_cpp-3.1.1-1 from repository HaikuPorts
install package msgpack_c_cpp_devel-3.1.1-1 from repository HaikuPorts
Continue? [yes/no] (yes) :
(...)
/Haiku/home/tmate> ./configure
(...)
checking for libssh >= 0.8.4... no
configure: error: "libssh >= 0.8.4 not found"
/Haiku/home/tmate> pkgman install devel:libssh/Haiku/home/tmate> make
(...)
In file included from /boot/system/develop/headers/msgpack.h:22,
from tmate.h:5,
from cfg.c:29:
/boot/system/develop/headers/msgpack/vrefbuffer.h:19:8: error: redefinition of struct iovec'
struct iovec {
^~~~~
In file included from tmux.h:27,
from cfg.c:28:
/boot/system/develop/headers/posix/sys/uio.h:12:16: note: originally defined here
typedef struct iovec {
^~~~~
Makefile:969: recipe for target 'cfg.o' failed
make: *** [cfg.o] Error 1

At this point I have to assume that porting software to Haiku involves significantly more knowledge than just recompiling.

A chat with the friendly Haiku developers reveals that this is actually a bug in msgpack, and minutes later a patch lands in haikuports. I can watch live as the patched package is built on https://build.haiku-os.org/buildmaster/master/x86_64/ (its buildslaves are VMs).

https://build.haiku-os.org/buildmaster/master/x86_64/ building the fixed msgpack library

In the meantime, I go ahead and send a patch upstream to add Haiku support to msgpack, https://github.com/msgpack/msgpack-c/pull/797.

Five minutes later updated msgpack is available in Haiku:

/Haiku/home/tmate> pkgman update
(...)
The following changes will be made:
in system:
upgrade package msgpack_c_cpp-3.1.1-1 to 3.2.0-2 from repository HaikuPorts
upgrade package msgpack_c_cpp_devel-3.1.1-1 to 3.2.0-2 from repository HaikuPorts
Continue? [yes/no] (yes) : y
100% msgpack_c_cpp-3.2.0-2-x86_64.hpkg [13.43 KiB]
(...)
[system] Done.

Shockingly good. Did I say “shockingly good”?

Back to my task:

/Haiku/home/tmate> make
(...)
In file included from tmux.h:40,
from tty.c:32:
compat.h:266: warning: "AT_FDCWD" redefined
#define AT_FDCWD -100

In file included from tty.c:25:
/boot/system/develop/headers/posix/fcntl.h:62: note: this is the location of the previous definition
#define AT_FDCWD (-1) /* CWD FD for the *at() functions */

tty.c: In function 'tty_init_termios':
tty.c:278:48: error: 'IMAXBEL' undeclared (first use in this function); did you mean 'MAXLABEL'?
tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
^~~~~~~
MAXLABEL
tty.c:278:48: note: each undeclared identifier is reported only once for each function it appears in
Makefile:969: recipe for target 'tty.o' failed
make: *** [tty.o] Error 1

This time, msgpack seems no longer to be the culprit. Commenting IMAXBEL out in tty.c like this

tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|/*IMAXBEL|*/ISTRIP);

results in

osdep-unknown.c: In function 'osdep_get_cwd':
osdep-unknown.c:32:19: warning: unused parameter 'fd' [-Wunused-parameter]
osdep_get_cwd(int fd)
~~~~^~
make: *** No rule to make target 'compat/forkpty-unknown.c', needed by 'compat/forkpty-unknown.o'. Stop.

I am lost again. By the way:

/Haiku/home/tmate> ./configure | grep -i OPENAT
checking for openat... no

Once more, mr. waddlesplash hints me in the right direction:

/Haiku/home/tmate> ./configure LDFLAGS="-lbsd"
(...)
/Haiku/home/tmate> make
(...)
In file included from tmux.h:40,
from window.c:31:
compat.h:266: warning: "AT_FDCWD" redefined
#define AT_FDCWD -100

In file included from window.c:22:
/boot/system/develop/headers/posix/fcntl.h:62: note: this is the location of the previous definition
#define AT_FDCWD (-1) /* CWD FD for the *at() functions */

make: *** No rule to make target 'compat/forkpty-unknown.c', needed by 'compat/forkpty-unknown.o'. Stop.

Here is my config.log. https://paste.debian.net/plain/1091523

It is explained to me that what elsewhere is in libresolv is in libnetwork on Haiku. Which probably means that the source code needs to be further patched. Let me see…

find . -type f -exec sed -i -e 's|lresolv|lnetwork|g'  {} \;

Seems to be taking forever, I wonder what is going on. (Note: this system is running off SATA.)

/Haiku/home/tmate> ./configure LDFLAGS="-lbsd"
(...)
/Haiku/home/tmate> make
(...)
# Success!
# Let's run it:/Haiku/home/tmate> ./tmate
runtime_loader: /boot/system/lib/libssh.so.4.7.2: Could not resolve symbol '__stack_chk_guard'
resolve symbol "__stack_chk_guard" returned: -2147478780
runtime_loader: /boot/system/lib/libssh.so.4.7.2: Troubles relocating: Symbol not found

Again, I am entirely lost here. Googling gets me https://discuss.haiku-os.org/t/libssh-could-not-resolve-symbol/8670. I hear that -lssp “sometimes” helps. So,

/Haiku/home/tmate> ./configure LDFLAGS="-lbsd -lssp"
(...)
/Haiku/home/tmate> make
(...)
/Haiku/home/tmate> ./tmate

Yay! it launches! But

[tmate] ssh.tmate.io lookup failure. Retrying in 2 seconds (non-recoverable failure in name resolution)

Let’s strace it:

/Haiku/home/tmate> strace -f ./tmate >log 2>&1

The result: https://paste.debian.net/plain/1091528

“Bad port ID” sounds like a Haiku thing. Maybe someone has a clue on what may be going wrong here and how to fix it. I will update the article accordingly. GitHub issue:

Porting a graphical Qt-based application

Let’s pick a simple QML application.

/> cd /Haiku/home//Haiku/home> git clone https://github.com/probonopd/QtQuickApp/Haiku/home/QtQuickApp> qmake ./Haiku/home/QtQuickApp> make/Haiku/home/QtQuickApp> ./QtQuickApp # Works! 

That was really straightforward indeed. Under one minute!

Packaging applications in the hpkg format using haikuporter and haikuports

Where to even begin? I can’t find straightforward “hello world” documentation, so I ask in #haiku on irc.freenode.net and hear that

I don’t really know what to do, I guess I really need a “hello world” tutorial, ideally a video. A Gentle Introduction to HaikuPorter comes in handy, and so does the GNU hello recipe.

I learn that

haikuporter is a tool which enables you to build common packaged projects for Haiku. It uses the haikuports repository as a base for all packages. Recipes are used by haikuporter to build packages.

However, I also learn that

there is no requirement that recipes be in the haikuports repository. You could make another repository and put recipes in it and point haikuporter at that.

Makes sense to me. Unless you are looking for a way to do upstream packaging, but I guess that topic is for another day.

Get haikuporter and haikuports

cd /boot/home/
git clone https://github.com/haikuports/haikuporter --depth=50
git clone https://github.com/haikuports/haikuports --depth=50
ln -s /boot/home/haikuporter/haikuporter /boot/home/config/non-packaged/bin/ # make it runnable from anywhere
cd haikuporter
cp haikuports-sample.conf /boot/home/config/settings/haikuports.conf
sed -i -e 's|/mydisk/haikuports|/boot/home/haikuports|g' /boot/home/config/settings/haikuports.conf

Writing a recipe

SUMMARY="Demo QtQuick application"
DESCRIPTION="QtQuickApp is a demo QtQuick application for testing Haiku porting and packaging"
HOMEPAGE="https://github.com/probonopd/QtQuickApp"
COPYRIGHT="None"
LICENSE="MIT"
REVISION="1"
SOURCE_URI="https://github.com/probonopd/QtQuickApp.git"
#PATCHES=""
ARCHITECTURES="x86_64"
PROVIDES="
QtQuickApp = $portVersion
"
REQUIRES="
haiku
"
BUILD_REQUIRES="
haiku_devel
cmd:qmake
"
BUILD()
{
qmake .
make $jobArgs
}
INSTALL()
{
make install
}

Building the recipe

Save this file under QtQuickApp-1.0.recipe, then run haikuporter -S ./QuickApp-1.0.recipe. It is checking dependency infos for all packages in the haikuports repository, which takes quite a while, so a good time to grab a coffee.

I wonder why this checking needs to be done locally on my machine rather than once and for everyone on some central server.

Says mr. waddlesplash,

Because you could have rewritten every file in the repository ;)

We probably could optimize this a bit and only compute this info when it is actually needed, since recent changes have made it such that it rarely is…

~/QtQuickApp> haikuporter  QtQuickApp-1.0.recipe 
Checking if any dependency-infos need to be updated ...
Looking for stale dependency-infos ...
Error: QtQuickApp not found in repository

Turns out that you can’t have the recipe file where the source code of your application lives (upstream), instead you need to have it in a “HaikuPorts format” repo, e.g., the one in which haikuports lives:

~/QtQuickApp> mv QtQuickApp-1.0.recipe ../haikuports/app-misc/QtQuickApp/
~/QtQuickApp> ../haikuport
~/QtQuickApp> haikuporter -S QtQuickApp-1.0.recipe

This is an aspect I don’t necessarily like since it makes upstream packaging more cumbersome, but hey, I guess the Haiku team wants all open source software to land in HaikuPorts eventually.

Now I get:

~/QtQuickApp> haikuporter -S QtQuickApp-1.0.recipe 
Checking if any dependency-infos need to be updated ...
updating dependency infos of QtQuickApp-1.0
Looking for stale dependency-infos ...
Error: QtQuickApp-1.0.recipe not found in tree.

What gives?

Haiku IRC logs point me to

~/QtQuickApp> haikuporter -S QtQuickApp
Checking if any dependency-infos need to be updated ...
updating dependency infos of QtQuickApp-1.0
Looking for stale dependency-infos ...
----------------------------------------------------------------------
app-misc::QtQuickApp-1.0
/boot/home/haikuports/app-misc/QtQuickApp/QtQuickApp-1.0.recipe
----------------------------------------------------------------------
Downloading: https://github.com/probonopd/QtQuickApp.git ...
--2019-07-14 16:12:44-- https://github.com/probonopd/QtQuickApp.git
Resolving github.com... 140.82.118.3
Connecting to github.com|140.82.118.3|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://github.com/probonopd/QtQuickApp [following]
--2019-07-14 16:12:45-- https://github.com/probonopd/QtQuickApp
Reusing existing connection to github.com:443.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘/boot/home/haikuports/app-misc/QtQuickApp/download/QtQuickApp.git’
0K . 1.34M=0.06s
2019-07-14 16:12:45 (1.34 MB/s) - ‘/boot/home/haikuports/app-misc/QtQuickApp/download/QtQuickApp.git’ saved [90094]
Validating checksum of QtQuickApp.git
Warning: ----- CHECKSUM TEMPLATE -----
Warning: CHECKSUM_SHA256="cf906a65442748c95df16730c66307a46d02ab3a12137f89076ec7018d8ce18c"
Warning: -----------------------------
Error: No checksum found in recipe!

Now, this poses an interesting question. If I add a checksum to the recipe, how can it ever match the latest git commit for continuous builds? (A Haiku developer confirms: “Indeed you can’t. HaikuPorts recipes are designed to be relatively stable…”)

Just for fun, I add to the recipe:

CHECKSUM_SHA256="cf906a65442748c95df16730c66307a46d02ab3a12137f89076ec7018d8ce18c"

It is still not sufficient.

~/QtQuickApp> haikuporter -S QtQuickApp
Checking if any dependency-infos need to be updated ...
updating dependency infos of QtQuickApp-1.0
Looking for stale dependency-infos ...
----------------------------------------------------------------------
app-misc::QtQuickApp-1.0
/boot/home/haikuports/app-misc/QtQuickApp/QtQuickApp-1.0.recipe
----------------------------------------------------------------------
Skipping download of source for QtQuickApp.git
Validating checksum of QtQuickApp.git
Unpacking source of QtQuickApp.git
Error: Unrecognized archive type in file /boot/home/haikuports/app-misc/QtQuickApp/download/QtQuickApp.git

Hello?! This is a git repository, the source code is right in there, there is nothing to “unpack”. In my opinion, the tool shuold be smart enough not to look for something to unpack if given a GitHub URL.

Probably I must use git://

SOURCE_URI="git://github.com/probonopd/QtQuickApp.git"

Now it says

Downloading: git://github.com/probonopd/QtQuickApp.git ...
Error: Downloading from unsafe sources is disabled in haikuports.conf!

Meh! Why must everything be so complicated, why can’t things “just work”. It can’t be that uncommon for something to compile something from GitHub, after all. I like tools that work out of the box without me having to configure, or as I like to call it, “fiddle around with”, stuff.

Maybe it works with

SOURCE_URI="git+https://github.com/probonopd/QtQuickApp.git"

Nope. I am still getting the dreaded error, as described in haikuports issue #1408.

So I do

sed -i -e 's|#ALLOW_UNSAFE_SOURCES|ALLOW_UNSAFE_SOURCES|g' /boot/home/config/settings/haikuports.conf

Indeed this gets me a little further, but why the heck does it SCREAM AT ME (GitHub is NOT THAT INSECURE!) and still want to untar something?

Says a mr. waddlesplash,

Yes, the reason being that we want to verify the integrity of the data we are fetching and building. Computing the checksum of a tarball is one way to do that; alternatively we could hash every single file but of course that would take far longer and is not implemented. So Git and other VCS are still considered “unsafe” for now. And probably always will be, because using GitHub’s auto archive generation is just as easy and often faster. But we could probably tone down the error message… (We don’t allow merging such recipes into HaikuPorts anymore.)

~/QtQuickApp> haikuporter -S QtQuickApp
Checking if any dependency-infos need to be updated ...
Looking for stale dependency-infos ...
----------------------------------------------------------------------
app-misc::QtQuickApp-1.0
/boot/home/haikuports/app-misc/QtQuickApp/QtQuickApp-1.0.recipe
----------------------------------------------------------------------
Downloading: git+https://github.com/probonopd/QtQuickApp.git ...
Warning: UNSAFE SOURCES ARE BAD AND SHOULD NOT BE USED IN PRODUCTION
Warning: PLEASE MOVE TO A STATIC ARCHIVE DOWNLOAD WITH CHECKSUM ASAP!
Cloning into bare repository '/boot/home/haikuports/app-misc/QtQuickApp/download/QtQuickApp.git'...
Unpacking source of QtQuickApp.git
tar: /boot/home/haikuports/app-misc/QtQuickApp/work-1.0/sources/QtQuickApp-1.0: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
Command 'git archive HEAD | tar -x -C "/boot/home/haikuports/app-misc/QtQuickApp/work-1.0/sources/QtQuickApp-1.0"' returned non-zero exit status 2

As always when I don’t know any further, I ask the friendly folks in #haiku on irc.freenode.net. What would I do without them? I get the hint that I should use

srcGitRev="d0769f53639eaffdcd070bddfb7113c04f2a0de8"
SOURCE_URI="https://github.com/probonopd/QtQuickApp/archive/$srcGitRev.tar.gz"
SOURCE_DIR="QtQuickApp-$srcGitRev"
CHECKSUM_SHA256="db8ab861cfec0ca201e9c7b6c0c9e5e828cb4e9e69d98e3714ce0369ba9d9522"

OK, I see what this is doing — download a source tarball of a particular git commit. It’s rather kludgy and not what I really want — have it git pull from master, whatever the latest one is.

As a Haiku developer explains,

We have our own CI so anything you put on the haikuports repo will land in packages for all users and we can’t take the risk to build “whatever is in upstream” and ship it this way

Understood!

Anyhow, this leads me to

waiting for build package QtQuickApp-1.0-1 to be activated
waiting for build package QtQuickApp-1.0-1 to be activated
waiting for build package QtQuickApp-1.0-1 to be activated
waiting for build package QtQuickApp-1.0-1 to be activated
waiting for build package QtQuickApp-1.0-1 to be activated
(...)

Needless to say, this is repeating forever. Apparently a bug, waiting to be fixed. (Is there a ticket already? I could not find it.)

Withhaikuporter and the haikuports repository I don’t feel the same level of “it just works” yet on the developer side of things that I like so much about the Haiku desktop experience. This feels more like a Linux distribution building toolkit along the lines of the Open Build Service — extremely powerful, very systematic, but overkill for my little hello world application.

Says mr. waddlesplash:

Indeed, HaikuPorter is extremely strict by default (and has a further “lint mode” and then a “strict mode” that make it even more strict!) because it has an essential goal of making packages that actually work, not just making packages. So it has facilities to tell you about undeclared dependencies, libraries that were not imported properly, incorrect versioning and requirements, etc.

The goal is to catch any and all problems here before the user would see them, including future ones (for instance, you were unable to install avrdude because the recipe actually specifies a dependency).

libraries not just particular packages, and even certain SOVERSIONS. HaikuPorter enforces all of this in recipes themselves to avoid such runtime errors.

While I understand that this level of rigor is needed when building an operating system, it still feels like overkill for my “hello world” app (for now). So I decide to try something different.

Packaging applications in the hpkg format using “package create”

Maybe this is the straightforward way that suits my needs here better?

mkdir -p apps/
cp QtQuickApp apps/
cat > .PackageInfo <<\EOF
name QtQuickApp
version 1.0-1
architecture x86_64

summary "Demo QtQuick application"
description "QtQuickApp is a demo QtQuick application for testing Haiku porting and packaging"

packager "probono"
vendor "probono"

copyrights "probono"
licenses "MIT"

provides {
QtQuickApp = 1.0-1
}
requires {
qt5
}
EOF
package create -b QtQuickApp.hpkg
package add QtQuickApp.hpkg apps
# See below if you also want the application
# to appear in the menu

Shockingly fast, shockingly simple, shockingly effective. Exactly how I like it. Awesome!

Installing — where did it go?

Using the file manager, move QtQuickApp.hpkg to ~/config/packages, and QtQuickApp will magically appear under ~/config/apps/.

Again, shockingly fast, again, shockingly simple, again, shockingly effective. Awesome beyond belief!

But… (there is always a “but”, right?)

It is still missing from the Applications menu and from QuickLaunch. I think I already know how to fix this: Using the file manager, I move QtQuickApp.hpkg from ~/config/packages to /system/packages.

Nope, still missing from the Applications menu and from QuickLaunch. I (and the instructions) must be missing something.

By looking at the “contents” tab in HaikuDepot for some other applications, I can see that they contain things like /data/mimedb/application/x-vnd... and, most notably, /data/deskbar/menu/Applications/...

So, what do I need to put there? Let me try…

mkdir -p data/deskbar/menu/Applications/
( cd data/deskbar/menu/Applications ; ln -s ../../../../apps/QtQuickApp . )
package add QtQuickApp.hpkg apps data

Sure enough, this did the trick!

Which brings me to the question: Why is this necessary, what is this good for. Isn’t this taking away a bit from the perceived overall elegance of the system?

Explains mr. waddlesplash:

The reason is that sometimes there are apps that we want in apps but not in the menu. For instance, LegacyPackageInstaller in your screenshot, which handles BeOS-format .pkg archives. We want users to be able to install these, but having a menu entry would be confusing.

Somehow I feel like there must be an easier solution, like the Hidden=true entries in desktop Linux .desktop files. Why not make the “hidden” information a resource and a filesystem attribute?

What feels especially un-elegant to me is the fact that the name of the (one) application that shows the menu, deskbar, is hardcoded in the path.

Says mr. waddlesplash:

“Deskbar” can probably be used as a generic term (like “taskbar” which might refer to the Windows app and also the concept.) As this is deskbar and not “Deskbar”, that might be what this can be understood as too.

Two “almost identical” folders with applications in them

Why are there two folders with applications in them, and why does one have my QtQuickApplication while the other doesn’t? (It’s not one per-system a one per-user directory, which I would have understood.) I am genuinely confused and think this should be unified.

mr. waddlesplash:

The Apps directory has apps that we do not want in the menu. But we should improve the menu situation somewhat and make it more customizeable, indeed.

Ticket or it won’t happen ;-)

Which makes me wonder, why put apps into the /system/apps directory in the first place if you don’t want users to see them. Why not put them somewhere else, where the user doesn’t encounter them. Like on Mac OS X where all the .app bundles that the user should not see in /Applications hide in some crude /System/Library/... subdirectories.

What about dependencies?

I think I need to specify dependencies somehow, don’t I?

Can I assume Qt to be part of every Haiku default installation? Nope! There is no Qt installed by default at all.

Could the packge tool figure out dependencies automatically by inspecting the ELFs being packaged?

I am informed that HaikuPorter does this indeed. The package tool does not because it is more akin to an “archive creator” that just creates the actual .hpkg files themselves.

Would Haiku gain elegance by adding a policy that a package must not have dependencies on packages that are not in haikuports? (I would like this policy a tremendous lot, would make things much easier — the system would be able to resolve the dependencies of each package you download from somewhere automatically, without the user having to fiddle around with additional package sources.)

Says mr. waddlesplash,

We do not want to restrict developers’ freedom too much; obviously if CompanyX wants to maintain their own set of software with dependencies (and thus a package repository) they are perfectly free to do so.

Maybe one could give a recommendation that third-party packages should avoid depending on anything else than what is in haikuports by privately bundling it along with the application; well, I guess this will be a topic for a future article in this series.

Adding an application icon

Now, what if I want my shiny new application to have one of those neat built-in icon resources? Turns out this is such amazing a topic that it will be the subject of tomorrow’s article in this series.

How to do continuous upstream builds of applications?

Imagine a project like Inkscape (yes, I know, it is not available for Haiku yet but it makes for a good example). They have a source code repository at https://gitlab.com/inkscape/inkscape. Every time when someone pushes a commit to that repository, pipelines are running that and the commit automatically gets tested, compiled, and the application gets packaged in various formats, including an AppImage for Linux (a self-standing application bundle that one can download to test locally without interfering with whatever may or may not be already installed in the system). The same is true for each merge request, so one can download a version of the application that contains the changes proposed in the merge request, before the code in question is even merged.

Merge requests for Inkscape with their build status, and with the possibility to download the built binaries in case the build result was green. Source: https://gitlab.com/inkscape/inkscape/merge_requests

The builds run in Docker containers. GitLab provides free runners on Linux, and I think it is possible to connect own runners as well (also I don’t know how this would work for systems like Haiku which I think doesn’t have Docker — but then, FreeBSD does not have Docker either, so at least it’s not a problem unique to Haiku).

So, ideally, building an application for Haiku could be done inside a Linux Docker container. This way, building a Haiku build could be integrated into the pipelines. Are there crosscompilers? Or would one need to emulate a whole Haiku system inside a Docker container using something like QEMU/KVM (if it can even be made work inside Docker)?

By the way, many application projects are using a system like this. Scribus, for example, does too — and this application is available for Haiku already.

One day, I would like to be able to send upstream application projects pull requests like this one which builds and uploads the application, but for Haiku.

As a Haiku developer explains,

for upstream wanting to create packages themselves, the usual method in CMake/CPack is supported. Other build systems could get support as well (calling the package tool directly) and that’s fine if people are interested in maintaining their packages. From our experience until now there has not been much interest in that so haikuporter has been more convenient for us, but eventually both methods should work side by side.

We need to provide a cross toolchain to build things from Linux or another server-grade OS (Haiku is not meant to run on servers)

I appplaud them for that. On Linux, normal desktop users need to bear all that burden and extra baggage (like security and tight controls) a “server-grade OS” needs, but a personal computer doesn’t. So I fully agree, being able to build desktop applications for Haiku on Linux servers is the way to go.

Conclusions

Porting applications to Haiku from POSIX is possible, but may require more effort than just recompiling. I would have been entirely lost without the help of friendly people in #haiku on irc.freenode.net. And even for them it was not entirely straightforward to see what was going wrong.

Pure Qt applications are the easy exception, I was able to compile a simple example app without any issues whatsoever.

Packaging a simple application in the hpkg format may be easy, but only for “traditionally released” software that has versioned relases with source tarballs and is intended to be maintained in haikuports. If you want to do continuous builds (one build per git commit) for a GitHub repository, things are seemingly not that easy. Here, Haiku feels like a “Linux distribution” more than what you get on a Mac, where you press on the “compile” button in Xcode and out comes an .app bundle which I can easily throw into a .dmg disk image, ready to be served on my downloads page.

Continuous upstream builds of applications on a “server-grade OS” like Linux will eventually be possible if there is enough demand from application developers, but for now there are other, more pressing priorities in the Haiku project.

Try it out for yourself today! The Haiku project provides nightly images that can be booted from DVD or USB. Installation consists of downloading the nightly 64-bit image and writing it to a USB stick using Etcher.

probono is the founder and lead developer of the AppImage project, the founder of the PureDarwin project, and a contributor to various open source projects. Screenshots were made on a Haiku system. Grateful acknowledgment is made to the developers in #haiku on irc.freenode.net, particularly mr. waddlesplash, @PulkoMandy, @diver, @begasus, and @humdinger.

--

--

probono

Author of #AppImage and contributor to hundreds of open source projects. #LinuxUsability, digital privacy, typography, computer history, software conservation