guidelines
GNU Hurd
hurd
porting
guidelines
Recent Changes
Preferences
Edit
History
Source
Discussion
Welcome to...
... the GNU Hurd!
Community
Donate
Contributing
Public Hurd Boxen
QEMU Images
Getting Help
Project Ideas
Open Issues
Documentation
FAQ
Hurd
Documentation
Running
Mach
Documentation
GNU Mach
MIG
Documentation
GNU MIG
Debian GNU/Hurd
GNU System
Hurd NG
This is a compilation of common porting problems and their solutions.
Additionally to this page, also see the section
General Porting Issues
of
, as well as further Debian-specific
porting
information.
There is a separate page about
System API Limitations
You may ask on the
bug-hurd
mailing list for details or
questions about fixing bugs.
GNU build system
For a good overview of the components in the GNU build system, see
and
The GNU build system distinguishes between 'build', 'host' and 'target' machines.
The 'build' machine is where compilers are run, the 'host' machine where the package
being built will run, and for cross compiling the 'target' machine, on which the compiler
built will generate code for.
When using GNU autotools to configure a package config.guess and config.sub from autotools-dev
are used to find out the build machine identity: CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM.
For GNU/Hurd config.guess gives 'i686-unknown-gnu0.3'. Sometimes a quadruple is used
adding KERNEL, e.g. for Linux on an amd64: 'x86_64-unknown-linux-gnu'. This
is however actually a triple, it just happens that the operating system part
unfortunately contains a '-'. config.sub is used to
canonicalize on these triplets, e.g. config.sub i686-gnu gives 'i686-pc-gnu'.
On Debian systems the build Makefile is debian/rules and some Debian packages will set $host to
'i486-pc-gnu'. This is accomplished with the 'dpkg-architecture -qDEB_HOST_GNU_TYPE' construct
forwarded to configure in debian/rules, e.g. configure --host=$DEB_HOST_GNU_TYPE.
Another way to set $build, $host etc is via the Debian dh_auto_configure script from the debhelper
package which uses the Perl code autoconf.pm to find out these variables.
Fixing configure.{ac,in}
The GNU/Hurd (and GNU/kFreeBSD) toolchain is extremely close to the GNU/Linux toolchain.
configure.ac thus very often just needs to be fixed by using the same cases as Linux, that is, turn
switch "$host_os" in
case linux*)
into
switch "$host_os" in
case linux*|k*bsd-gnu*|gnu*)
for a host_os case statement, or
switch "$host" in
case *-linux*)
into
switch "$host" in
case *-linux*|*-k*bsd-gnu*|*-gnu*)
If separate case is needed, make sure to put
-gnu
after
-linux
switch "$host" in
case *-linux*|*-k*bsd-gnu*)
something;;
case *-gnu*)
something else;;
because else
-gnu
would catch i386-pc-linux-gnu for instance...
Note: some of such statements are not from the source package itself, but from aclocal.m4 which is actually from libtool. In such case, the package simply needs to be re-libtoolize-d.
Preprocessor Define
IRC, freenode, #hurd, 2013-10-23
in my code?
on top of it
Undefined
bits/confname.h
macros (
PIPE_BUF
, ...)
If macro
XXX
is undefined, but macro
_SC_XXX
or
_PC_XXX
is defined in
bits/confname.h
, you probably need to use
sysconf
pathconf
or
fpathconf
to obtain it dynamicaly.
The following macros have been found in this offending situation (add more if you find them):
PIPE_BUF
An example with
sysconf
: (when you find a
sysconf
offending macro, put a better example)
#ifndef XXX
#define XXX sysconf(_SC_XXX)
#endif
/* offending code using XXX follows */
An example with
fpathconf
#ifdef PIPE_BUF
read(fd, buff, PIPE_BUF - 1);
#else
read(fd, buff, fpathconf(fd, _PC_PIPE_BUF) - 1);
#endif
/* note we can't #define PIPE_BUF, because it depends
on the "fd" variable */
Bad File Descriptor
If you get Bad File Descriptor error when trying to read from a file (or accessing it at all), check the
open()
invocation. The second argument is the access method. If it is a hard coded number instead of a symbol defined in the standard header files, the code is screwed and should be fixed to either use
O_RDONLY
O_WRONLY
or
O_RDWR
. This bug was observed in the
fortunes
and
mtools
packages for example.
PATH_MAX
MAX_PATH
MAXPATHLEN
_POSIX_PATH_MAX
Every unconditionalized use of
PATH_MAX
MAX_PATH
or
MAXPATHLEN
is a POSIX incompatibility. If there is no upper limit on the length of a path (as its the case for GNU), this symbol is not defined in any header file. Instead, you need to either use a different implementation that does not rely on the length of a string or use
sysconf()
to query the length at runtime. If
sysconf()
returns -1, you have to use
realloc()
to allocate the needed memory dynamically. Usually it is thus simpler to just use dynamic allocation. Sometimes the amount is actually known. Else, a geometrically growing loop can be used: for instance, see
Alioth patch
or
Pulseaudio patch
. Note that in some cases there are GNU extensions that just work fine: when the
__GLIBC__
macro is defined,
getcwd()
calls can be just replaced by
get_current_dir_name()
calls.
Note: constants such as
_POSIX_PATH_MAX
are only the minimum required value
for a potential corresponding
PATH_MAX
macro. They are not a replacement for
PATH_MAX
, just the minimum value that one can assume.
Note 2: Yes, some POSIX functions such as
realpath()
actually assume that
PATH_MAX
is defined. This is a bug of the POSIX standard, which got fixed in
the latest revisions, in which one can simply pass
NULL
to get a dynamically
allocated buffer.
ARG_MAX
Same rationale as
PATH_MAX
. There is no limit on the number of arguments.
IOV_MAX
Same rationale as
PATH_MAX
. There is no limit on the number of iovec items.
MAXHOSTNAMELEN
Same as
PATH_MAX
. When you find a
gethostname()
function, which acts on a static buffer, you can replace it with Neal's
xgethostname function
which returns the hostname as a dynamic buffer. For example:
Buggy code:
char localhost[MAXHOSTNAMELEN];
...
gethostname(localhost, sizeof(localhost));
Fixed code:
#include "xgethostname.h"
...
char *localhost;
...
localhost = xgethostname();
if (! localhost)
perror ("xgethostname");
return ERROR;
...
/* use LOCALHOST. */
free (localhost);
NOFILE
Replace with
getrlimit(RLIMIT_NOFILE,...)
#ifdef __MACH__
Some applications put Apple Darwin-specific code inside
#ifdef __MACH__
guards. Such guard is clearly not enough, since not only Apple uses Mach as a
kernel. This should be replaced by
#if defined(__MACH__) && defined(__APPLE__)
mach/clock.h
Some applications unconditionally use Darwin-specific functions coming
from
mach/clock.h
to get the clock. This is unnecessarily unportable,
clock_gettime
can simply be used instead, and the
#ifdef __MACH__
guard for the
mach/clock.h
inclusion be fixed as explained above.
GNU specific
#define
If you need to include specific code for GNU/Hurd using
#if
...
#endif
, then you can use the
__GNU__
symbol to do so. But think (at least) thrice! before doing so. In most situations, this is completely unnecessary and will create more problems than it may solve. Better ask on the mailing list how to do it right if you can't think of a better solution.
sys_errlist[]
vs.
strerror()
If a program has only support for
sys_errlist[]
you will have to do some work to make it compile on GNU, which has dropped support for it and does only provide
strerror()
. Steinar Hamre writes about
strerror()
strerror()
should be used because:
It is the modern, POSIX way.
It is localized.
It handles invalid signals/numbers out of range. (better errorhandling and not a buffer-overflow-candidate/security risk)
strerror()
should always be used if it is available. Unfortunaly there are still some old non-POSIX systems that do not have
strerror()
, only
sys_errlist[]
Today, only supporting
strerror()
is far better than only supporting
sys_errlist[]
. The best (from a portability viewpoint), however is supporting both. For configure.in, you will need:
AC_CHECK_FUNCS(strerror)
To
config.h.in
, you need to add:
#undef HAVE_STRERROR
Then something like:
#ifndef HAVE_STRERROR
static char *
private_strerror (errnum)
int errnum;
extern char *sys_errlist[];
extern int sys_nerr;
if (errnum > 0 && errnum <= sys_nerr)
return sys_errlist[errnum];
return "Unknown system error";
#define strerror private_strerror
#endif /* HAVE_STRERROR */
You can for example look in the latest coreutils (the above is a simplified version of what I found there.) Patches should of course be sent to upstream maintainers, this is very useful even for systems with a working
sys_errlist[]
Of course, if you don't care about broken systems (like MS-DOG) not supporting
strerror()
you can just replace
sys_errlist[]
directly (upstream might not accept your patch, but debian should have no problem)
C++,
error_t
and
E*
On the Hurd,
error_t
is an enumeration of the
E*
constants. However, C++
does not like
E*
integer macros being directly assigned to that enumeration. In short, replace
error_t err = EINTR;
by
error_t err = error_t(EINTR);
Missing
termio.h
Change it to use
termios.h
(check for it properly with autoconf
HAVE_TERMIOS_H
or the
__GLIBC__
macro)
Also, change calls to
ioctl(fd, TCGETS, ...)
and
ioctl(fd, TCSETS, ...)
with
tcgetattr(fd, ...)
and
tcsetattr(fd, ...)
AC_HEADER_TERMIO
The autoconf check for
AC_HEADER_TERMIO
tryes to check for termios, but it's only really checking for termio in
termios.h
. It is better to use
AC_CHECK_HEADERS(termio.h termios.h)
missing
_IOT
This comes from ioctls. Fixing this is easy if the structure members can be expressed by using the _IOT() macro, else it's simply impossible... See
bits/termios.h
for an instance:
#define _IOT_termios /* Hurd ioctl type field. */ \
_IOT (_IOTS (tcflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2)
The rationale behind is that on the Hurd ioctl numbers actually encode how the
data should be transferred via RPC: here
struct termios
holds 4 members of
type
tcflag_ts
, then
NCCS
members of type
cc_tsi
and finaly 2 members of
type
speed_ts
, so the RPC mecanism will know how to transfer them.
As you can see, this limits the number of contiguous kinds of members to 3, and
in addition to that (see the bitfield described in
ioctls.h
), the third kind
of member is limited to 3 members. This is a design limitation, there is no way
to overcome it at the moment.
Note: if a field member is a pointer, then the ioctl can't be expressed
this way, and that makes sense, since the server you're talking to
doesn't have direct access to your memory. Ways other than ioctls must
then be found.
SA_SIGINFO
Implemented by Jérémie Koenig, pending upload in Debian eglibc 2.13-19.
SA_NOCLDWAIT
Not implemented yet.
SOL_IP
Not implemented yet.
HZ
Linuxish and doesn't even make sense since the value may vary according to the running kernel. Should use
sysconf(_SC_CLK_TCK)
or
CLK_TCK
instead.
SIOCDEVPRIVATE
Oh, we should probably provide it.
MAP_NORESERVE
Not POSIX, but we could implement it.
See
mmap
O_DIRECT
Long story to implement.
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
We could easily provide it;
PTHREAD_STACK_MIN
We don't really have a minimum value. We could define it to 4096 (or ~16, which
is our actual minimum), but most applications making use of
PTHREAD_STACK_MIN
would just crash with such a value.
The application knows way better than the OS which stack size it needs and have
its own hint about the stack size, and thus use
PTHREAD_STACK_MIN
only as a
minimum, not as a hint.
linux/types.h
or
asm/types.h
These are not POSIX,
sys/types.h
and
stdint.h
should be used instead.
iopl
Not supported and actually very dangerous (permits userland to completely disable interruptions...). Replace with
ioperm(0, 65536, 1)
semget
sem_open
Not implemented yet, will always fail. Use
sem_init()
instead if possible.
sem_init
with pshared=1 is not available yet either.
net/if_arp.h
net/ethernet.h
, etc.
Not implemented, not POSIX. Try to disable the feature in the package.
linux/parport.h
linux/ppdev.h
There is no programming interface for the parallel port on GNU/Hurd yet.
linux/cdrom.h
Use instead.
CBAUD
This is not actually standard; cfsetspeed, cfsetispeed, or cfsetospeed should be used instead.
IUCLC
IUCLC is a GNU extension.
#define _GNU_SOURCE
thus has to be used to get the definition (even if Linux unconditionally provides it, it should not).
errno
values
When dealing with
errno
, you should always use the predefined error codes defined with the
E*
constants, instead of manually comparing/assigning/etc with their values.
For example (C/C++):
/* check whether it does not exist */
if (errno == 2)
...
or Python:
# check whether it does not exist
try:
...
except OSError, err:
err.errno == 2:
...
This is wrong, as
the actual values of the
E*
are unspecified (per POSIX)
. You must always use the predefined constants for the possible errors.
For example (C/C++):
/* check whether it does not exist */
if (errno == ENOENT)
...
With Python, you can use the
errno
module
for the various constants:
# check whether it does not exist
try:
...
except OSError, err:
import errno
err.errno == errno.ENOENT:
...
undefined reference to
dlopen
dlsym
dlclose
Configure script often hardcode the library that contains dlopen & such (
-ldl
), and only for Linux. Simply add the other GNU OS cases: replace
linux*
with
linux*|gnu*|k*bsd*-gnu*
struct sockaddr
sa_len/sa_family
IRC, freenode, #hurd, 2014-02-18
issue in iceweasel down to nspr
structure that includes sa_len before sa_family, and nspr directly maps
that into its own structure, assuming the internal layout is the same
the hurd
*** rbraun_hurd (c3445c23@gateway/web/freenode/ip.195.68.92.35) has joined
channel #hurd
Invalid argument Failed to write cookie file: Unknown error (os/kern)
303" error
glibc/hurd somewhere
copyright (C) 2008-2011 Chris Porter and the qwebirc project --
Mozilla/5.0 (X11; GNU i686-AT386; rv:27.0) Gecko/20100101 Firefox/27.0
Iceweasel/27.0
IRC, freenode, #hurd, 2014-02-19
have the same layout as the native one
old 4.4bsd header that defines sa_len before sa_family, making all sorts
of tests fail in nspr
elsewhere
work, multiple tabs, gnash running (things like youtube and freenode web
chat client among other things)
Missing
linux/types.h
asm/types.h
linux/limits.h
asm/byteorder.h
sys/endian.h
asm/ioctl.h
asm/ioctls.h
linux/soundcard.h
These are often used (from lame rgrep results) instead of their standard equivalents:
sys/types.h
(or
stdint.h
for fixed-size types),
limits.h
endian.h
sys/ioctl.h
sys/soundcard.h
Missing
sys/*.h
linux/*.h
These are linuxish things, they may not have Hurd equivalents yet, better disable the code.
Links:
community/gsoc/project ideas/maxpath
community/weblogs/ArneBab/porting-simple-packages
faq/software
glibc/mmap
porting
running/debian/porting
running/distrib
user/tlecarrour
user/tlecarrour/patch life cycle
Copyright © 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011,
2012, 2013, 2014, 2016 Free Software Foundation, Inc.
License:
GFDL 1.2+
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with no Invariant
Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license
is included in the section entitled
GNU Free Documentation License
Last edited
2016-11-11 23:59:42 UTC