I’m currently investigating the possibility of providing cross libc for Haiku in Zig, as we do for several other operating systems at the moment. A prerequisite for this is that we can easily build Haiku on Linux.
I’ve been following the build instructions to build @minimum-raw for Haiku’s various ports on master. This has worked well for arm, arm64, riscv64, and x86_64. (The m68k, powerpc, and sparc ports seem nonfunctional.) However, for x86 – without gcc2 because we will never support that in Zig anyway – I get:
❯ ../../jam/bin/jam -q -j1 @minimum-raw
warning: Invalid jamfile cache: Failed to read file info.
Starting build of type minimum ...
Building Haiku Minimum Target
AddHaikuImagePackages: package openssl3 not available!
build-feature packages unavailable on x86: ffmpeg gutenprint jpeg qrencode_kdl libavif
AddHaikuImagePackages: package bc not available!
AddHaikuImagePackages: package icu74 not available!
Asked for bios_ia32 target boot platform
Unknown path to handle adding to image
Asked for pxe_ia32 target boot platform
Unknown path to handle adding to image
...patience...
...patience...
...patience...
...patience...
...patience...
...patience...
...patience...
...found 69892 target(s)...
...updating 9248 target(s)...
InitScript1 haiku.image-init-vars
AddTargetVariableToScript1 <unique!target>_target_791
AddTargetVariableToScript1 <unique!target>_target_891
AddTargetVariableToScript1 <unique!target>_target_991
AddTargetVariableToScript1 <unique!target>_target_002
AddTargetVariableToScript1 <unique!target>_target_102
DownloadLocatedFile1 download/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg
--2026-05-21 19:28:32-- https://eu.hpkg.haiku-os.org/haikuports/master/build-packages/6efb4aa89c1ea031aaa55b6d9925f30d61ab1c94c1450660cbd3cb9aa78d57d1/packages/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg
Resolving eu.hpkg.haiku-os.org (eu.hpkg.haiku-os.org)... 206.189.242.242
Connecting to eu.hpkg.haiku-os.org (eu.hpkg.haiku-os.org)|206.189.242.242|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://haiku-buildpackages.cdn.haiku-os.org/packages/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg [following]
--2026-05-21 19:28:32-- https://haiku-buildpackages.cdn.haiku-os.org/packages/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg
Resolving haiku-buildpackages.cdn.haiku-os.org (haiku-buildpackages.cdn.haiku-os.org)... 95.217.35.232, 2a01:4f9:2b:2e04::2
Connecting to haiku-buildpackages.cdn.haiku-os.org (haiku-buildpackages.cdn.haiku-os.org)|95.217.35.232|:443... connected.
HTTP request sent, awaiting response... 404 Not Found
2026-05-21 19:28:32 ERROR 404: Not Found.
source="objects/haiku/x86/packaging/repositories/HaikuPorts-checksum"
wget --retry-connrefused --retry-on-host-error --timeout 30 -O "download/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg" https://eu.hpkg.haiku-os.org/haikuports/master/build-packages/`cat $source`/packages/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg || exit 1
touch "download/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg"
...failed DownloadLocatedFile1 download/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg ...
...removing download/gcc_syslibs_devel-5.4.0_2016_06_04-4-x86.hpkg
BUILD FAILURE:
...failed updating 1 target(s)...
...skipped 7 target(s)...
...updated 6 target(s)...
I’m not really sure if this is expected (maybe the x86 port can’t be cross-compiled from Linux?) or if I’m doing something wrong.
Let me know if I can provide any other information to diagnose this.
Someone correct me, but I think x86 is nowadays on a similar level to sparc and company. What is used is the hybrid x86_gcc2h. It’s not that programs have to run with the old gcc2 ABI there, it runs both legacy BeOS programs and modern Haiku ones, something like the multiarch distros: you have lib/libroot.so and lib/x86/libroot.so.
Hmm, I see. The problem then is that building x86_gcc2 cross tools seems to depend on gcc-multilib (due to gcc -m32), and I’m really not fond of the idea of installing that package; it’s mutually exclusive with a bunch of other multiarch cross-compiler packages that I actually use. Is there any way to avoid that dependency?
This is trying to download a GCC devel package that doesn’t exist, because we don’t provide binary packages at present for the x86 target (x86 with Itanium ABI as default), only the x86_gcc2h target (x86 hybrid: GCC2 ABI as default, Itanium ABI as secondary.)
That depends. You can do a “bootstrap” build of Haiku (totally-from-source, including all base packages like ICU and coreutils) for the x86 target, but this is annoying, fragile, and usually only useful for getting to a “non-bootstrap” build. And if you are trying to target x86_gcc2h it won’t help you especially much.
More to the point, what do you actually need here? Zig provides cross-libc support for Windows and macOS too, right? You obviously can’t “build” those on Linux, so how does Zig work there? Can you get by with just the binary packages? Would our prebuilt Docker images with cross-compilers help any?
For Windows, we ship the .def files from the MinGW-w64 project to build import libraries for system DLLs. Headers are likewise sourced from MinGW-w64.
For macOS, we ship Apple’s own libSystem.tbd to build a stub libSystem.dylib. Headers are also sourced from Apple.
Anyway, in theory, yes, we could get all of this from prebuilt packages. But as a general principle, we prefer to have a core team member build artifacts from source when updating these vendored bits.
The easiest way is probably going to be to just hack it in to the corresponding script:
I don’t know if there’s really a good way to specify this on the command line. Your usecase is niche enough that just having your own hack may be best. If there were a lot of people who wanted to do this for some reason, I guess we would find some more general solution…
All non-bootstrap builds will use our binary artifacts for the components like ICU, gcc_syslibs, etc. So you are only getting a from-source libroot.so and friends.
A build system hack is definitely acceptable as long as it’s not an excessively huge or fragile patch. We already do this for musl, NetBSD, and OpenBSD, for example. (I’d link to the relevant patches in our infra repo, but Discourse seems to be blocking Codeberg links all of a sudden…?)
I’ll give this a try and report back.
I think that’s okay; after all, libroot.so & co are the only artifacts we actually care about. We don’t insist on full toolchain bootstraps for the other libcs either.
This did the trick as far as building cross tools goes:
diff --git a/build/scripts/build_cross_tools b/build/scripts/build_cross_tools
index 737479e099..69c7e88685 100755
--- a/build/scripts/build_cross_tools
+++ b/build/scripts/build_cross_tools
@@ -172,7 +172,7 @@ copy_headers $haikuSourceDir/headers/posix $tmpIncludeDir/posix
# GCC 2 compiled for 64-bit on most systems is somewhat broken
# (e.g. "cast specifies signature type", spurious "maybe uninitialized" warnings)
-export CC="$CC -m32"
+export CC="i686-linux-gnu-gcc -fcommon -std=gnu89"
# configure gcc
cd $gccObjDir
A bit odd that adding the -fcommon -std=gnu89 here was necessary despite the script attempting to add them later. I suppose something’s messing up the compiler version check.
However, during the @release-anyboot build (or any other profile it seems), I now get:
mimeset: "/home/alexrp/haiku/generated.x86/objects/haiku/x86_gcc2/release/preferences/filetypes/FileTypes": No space left on device
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/home/alexrp/haiku/generated.x86/objects/linux/lib" \
objects/linux/x86_64/release/tools/mimeset -f --mimedb "objects/common/data/mime_db/mime_db" "objects/haiku/x86_gcc2/release/preferences/filetypes/FileTypes"
...failed MimeSet1 objects/haiku/x86_gcc2/release/preferences/filetypes/FileTypes ...
...removing objects/haiku/x86_gcc2/release/preferences/filetypes/FileTypes
BUILD FAILURE:
...failed updating 1 target(s)...
...skipped 7 target(s)...
...updated 288 target(s)...
Which is… confusing?
❯ df -h /dev/nvme0n1p3
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p3 7,3T 3,3T 3,6T 48% /
This probably means there’s no space left in that particular inode for more extended attributes. What filesystem are you using? The configure script is supposed to detect what kind of xattrs we can use on whatever filesystem the build is going to be run on (fully emulated with a shadow directory mapped to inode numbers, partially emulated with a shadow directory mapped to IDs set in real xattrs on the inode, and partially emulated with no shadow directory and all Be/Haiku-style extended attributes in the inodes themselves.) EXT2/3/4 have some arbitrary and low limits and can only handle the second kind at most. XFS, BTRFS, and others support attributes of any size.
I’m indeed using ext4. But I also have the ea_inode feature enabled on my file system, which is probably a very rare configuration. Perhaps that somehow confused the detection done by configure?
At any rate, with ../configure --no-full-xattr ..., it works. So that’s successful builds for all functional Haiku targets, meaning we can proceed with this Zig enhancement.
configure tests whether it can create files with some small and then some really huge attributes (larger than anything the build system tries to actually set, I think) and enables the corresponding feature if so. I guess it must’ve succeeded and assumed that would suffice, but then this file somehow failed despite that.
Actually, turns out I’ve got a few follow-up questions:
Which libraries would you say we should consider to be part of libc, or at least libc-adjacent? I use the latter term because, even though it’s not actually part of libc, we decided to include libexecinfo.so on the BSDs; a lot of software just kind of assumes it’s available. I’m personally inclined to say: libroot.so, libnetwork.so, libbsd.so, libgnu.so
I see that a subset of symbols in these libraries use GNU symbol versioning. Does this actually mean anything at the moment? In other words, should we expect symbol versioning to be used by the time Haiku R1 releases? (That’s the point where we’d start accurately tracking symbol additions/removals in libraries in each Haiku release, rather than just tracking a snapshot of Haiku master.) If yes, should we expect the current symbol versioning scheme (such as it is) to stay, or is the idea to start with a clean slate for R1?
Are you able to give any advice on which headers are safe to prune from develop/headers/ before we import Haiku headers? Some are obvious enough (alm/, GL/, linprog/, userlandfs/), but it’s not clear to me whether anything in os/ and/or private/ ought to be kept.
Yes, that’s the full set of libraries with the base C/POSIX and then BSD/GNU APIs.
It’s only used for APIs/ABIs that we had to break for some reason and couldn’t maintain ABI compatibility any other way. I don’t expect we’d adopt symbol versioning across the board unless we actually needed to for some reason.
R1 will remain ABI compatible with BeOS R5 on the 32-bit builds. After R1 (whenever that happens…) we may break ABI in a more comprehensive way, if we need to.
You should at least keep os/kernel/ and related headers because those APIs are implemented in libroot.so. Other headers in os/ are mostly implemented in libbe.so and so you don’t need those.
private/ headers are ones that are not ABI/API stable and may change at any time. Ideally applications wouldn’t ever use these, but sometimes it’s necessary.
Oh, interesting; 32-bit BeOS compatibility notwithstanding, I had assumed that Haiku has no ABI stability guarantees until R1 is released, but it sounds like that may have been a faulty assumption on my part? If Haiku already guarantees a stable ABI with symbol versioning when ABI breaks do happen, then it sounds like we shouldn’t just track a snapshot of Haiku master, but actually maintain proper symbol history as we do for other libcs.
Assuming that’s the case, there’s the question of how to represent Haiku versions on our end… we use a simple major.minor.patch scheme to represent libc versions, but it’s not clear if Haiku’s current version scheme would map onto that cleanly.
We (more or less) guarantee ABI compatibility for all public APIs (i.e. none in private/ and none in BPrivate namespace) that are not otherwise marked “experimental”. The last time we broke ABI in a non-forwards-compatible way was the time_t change before beta1; but as beta1 was the first release to support x86_64 officially anyway, we technically have maintained ABI compatibility there too.
Can you use the official ones from HaikuVersion.h, or do you need something more descriptive? (The current version is exposed via some symbols so applications can detect what libroot they’re running against, not just what one they compiled against.)
The versions get surfaced to users when compiling programs, e.g. in zig build-exe ... -target x86_64-freebsd.14.0, -target x86_64-linux.7.0.10-gnu.2.40, etc. (The general form is along the lines of <arch>-<os>[x.y[.z][...x.y[.z]]]-<libc>[x.y[.z]].) So it’s best if the versions correspond to the user-facing version in the OS/libc; I think those HaikuVersion.h values would not be great for this purpose…