Common practices and problems found when porting to GNU/k*BSD =============================================================== debian-ports archive upload policy ---------------------------------- When you're going to upload your fixes to the debian-ports.org repository, check this first: Config scripts (config.guess and config.sub) -------------------------------------------- You must have the latest config.guess and config.sub. When you setup a build environment don't forget to install autotools-dev. Many packages have outdated config.* and only auto-update when those are available (some never auto-update). If those two files are not auto-updated in the package even with autotools-dev installed, copy them manually from "/usr/share/misc/config.*" and report this to the BTS. Add our system name to checks here and there -------------------------------------------- When the check doesn't concern kernel, but userland stuff (notably, libc), we want to match the same checks that match Linux. Make sure the definitions are not simply duplicated from Linux' because that will eventualy result in out-of-sync definitions that break for us. Example of triplet check: linux*-gnu | gnu* | k*bsd*-gnu) Example of uname check: Linux|GNU|GNU/*) Example of C macro check: defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) [note: GNU/Hurd defines __GNU__, and GNU/k*BSD define __GLIBC__ as hardcoded macro] Example of makefile check: ifneq (, $(filter Linux GNU GNU_%, $(shell uname -s))) [note1: findstring matches subwords, use filter instead] [note2: list must be the first parameter, otherwise matching fails] [note3: "%" is make's wildcard] When the check concerns kernel, we obviously want to match with FreeBSD's or NetBSD's. Example of triplet check: freebsd* | kfreebsd*-gnu) Example of uname check: *FreeBSD) Example of C macro check: defined(__FreeBSD__) || defined(__FreeBSD_kernel__) [note: see below for more details on this one] debian/control files -------------------- Example for Linux-specific build-dependency: Build-Depends: [...], libselinux1-dev [!kfreebsd-i386 !kfreebsd-amd64 !hurd-i386], dpkg-dev (>= 1.13.13), [...] Example for i386-only package: Build-Depends: [...], dpkg-dev (>= 1.13.13), [...] Architecture: i386 kfreebsd-i386 hurd-i386 Example for Linux-only package: Build-Depends: [...], dpkg-dev (>= 1.13.13), [...] Architecture: i386 ia64 alpha amd64 arm hppa m32r m68k mips mipsel powerpc ppc64 s390 s390x sh3 sh3eb sh4 sh4eb sparc WARNING: please note that this functionality is still not supported by debhelper Libraries, your beloved enemy ----------------------------- Here are some guidelines for building and porting libraries. Many libraries need porting work because they have to detect the system in order to decide how their shared object support works. When building a library make sure it generates the shared object (.so.*) files. Most of them will FTBFS if this fails, but a few will still build succesfuly, being the cause of horrible bugs in unrelated packages that are sometimes difficult to trace and can easily be avoided. First of all, check if your library uses libtool. A quick and reliable check is: grep 'Linux ELF' * If it reports matches in aclocal.m4 and configure, it means we're using libtool. Now check wether the installed libtool supports us: grep kfreebsd aclocal.m4 If no match is found, we need to re-libtoolize. Generaly, this involves: Check the 'configure' header for the version of autoconf that generated it. If that version is 2.13, give up. Your attempt at relibtoolising failed. (read the notes below for a method to work around the problem). Run 'libtoolize -c -f'. If everything is ok, this command should be a no-op. However, make sure it doesn't say you need to add the contents of 'libtool.m4' here or there. If it does, it means the package is keeping an old copy of libtool.m4 hidden somewhere (sigh). Sometimes it's just renamed, sometimes it's embedded in acinclude.m4. In whichever case, _don't_ update it manualy. Instead, remove the libtool.m4 bits from whereever they are. Check the 'aclocal.m4' header for the version of aclocal that generated it, and use the same major version (aclocal-1.x) to regenerate it. If the package includes an 'm4' directory you might need to pass '-I m4' to aclocal. Regenerate configure using autoconf 2.5x. Now make sure everything went as expected: grep kfreebsd configure This should do it. When you submit the bug, please point the maintainer to bug #242950, it contains some useful info for maintainers. Finally, if the library doesn't use libtool, expect a hardcoded check for Linux somewhere. This is how badly-portable libraries generaly handle the shared object definitions. Just find the check for Linux and add our triplet or uname output where it belongs. Preprocessor Variables ---------------------- How to check for system based on kernel of FreeBSD (i.e. either FreeBSD or GNU/kFreeBSD), the Right Way [tm]. #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) [...] #endif Alternatively, when there are lots of checks, this might be prefered: #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) # define __FreeBSD_kernel__ __FreeBSD__ #endif [...] #ifdef __FreeBSD_kernel__ [...] #endif Some notes on version checking stuff. You _may_ assume __FreeBSD__ contains major version information, but you must _not_ assume the same for __FreeBSD_kernel__. On GNU/kFreeBSD, __FreeBSD_kernel__ will only contain major version number after including . E.g: #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) # define __FreeBSD_kernel__ __FreeBSD__ #endif #include [...] #if __FreeBSD_kernel__ >= 6 [...] #else [...] #endif There are also __FreeBSD_version and __FreeBSD_kernel_version, which work similarly: #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) # define __FreeBSD_kernel__ __FreeBSD__ #endif #ifdef __FreeBSD_kernel__ # include # ifndef __FreeBSD_kernel_version # define __FreeBSD_kernel_version __FreeBSD_version # endif #endif [...] #if __FreeBSD_kernel_version >= 602010 [...] #else [...] #endif For possible values of __FreeBSD_*version variables, see: Important note on __FreeBSD_*version. Unlike FreeBSD, we ship packages that are not part of base _always_ providing binaries. Sometimes it's not important for a FreeBSD porter to maintain compatibility with different kernel ABIs in runtime, and per might opt for doing it in build time. However, we are going to ship two major kernel versions (5.x and 6.x) and our binaries should run on both. This is why we need to implement runtime detection whenever possible. An example, based on the previous one: #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) # define __FreeBSD_kernel__ __FreeBSD__ #endif #ifdef __FreeBSD_kernel__ # include # ifndef __FreeBSD_kernel_version # define __FreeBSD_kernel_version __FreeBSD_version # endif int get_kfreebsd_version () { [...] } #endif [...] #if __FreeBSD_kernel_version >= 602010 if (get_kfreebsd_version () >= 602010) { [...] } else #else { [...] } #endif get_kfreebsd_version () returns the latest version of kFreeBSD that uname () can garantee us, and converts it in a 6-digit format compatible with __FreeBSD_*version. I have put get_kfreebsd_version () in get_kfreebsd_version.c in this directory. You can copy and use it whereever you like. There are usage examples of all the above examples in [grub]/lib/device.c, so I suggest you have a look at it. Writing to devfs (kFreeBSD) --------------------------- On kFreeBSD's devfs it's only possible to create block/char devices and symlinks. So if you need to create some thing in /dev, like a named pipe create it in another place, then symlink from /dev. Note that the symlink you put in /dev will be removed on next reboot, so make sure the proper init.d script restores it. Generaly, you should use /var/run for your named pipe. The only exception is sysvinit, which can't assume /var is mounted and hence uses /etc. All other daemons can assume /var is mounted, so this shouldn't be an issue. RT signals ---------- kFreeBSD doesn't support POSIX RT (realtime) signals. We hope that this functionality is added someday but for now it's a porting issue for us. You can detect wether RT signals are available in the system via the SIGRTMIN and SIGRTMAX macros (which are not defined on kfreebsd-gnu). Get libc soname (6 or 6.1 on linux-gnu, 0.1 on kfreebsd-gnu, etc) ----------------------------------------------------------------- When obtaining the libc soname it is better to not hardcode it like a number of programs do. Instead, you can use something like get_libc_path.c to obtain the full path to libc shared object, and then strip the soname from there.