[[!meta copyright="Copyright © 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc."]] [[!meta license="""[[!toggle id="license" text="GFDL 1.2+"]][[!toggleable id="license" text="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|/fdl]]."]]"""]] 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 [[running/debian/porting]] information. There is a separate page about [[System_API_Limitations]]. You may ask on the [[mailing lists/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 Is there a preprocessor define gcc sets for hurd which I can check in my code? __GNU__ glibc sets it if i'm right I also see that __MACH__ gets set that's also set on Mac OS X right, which uncovered a bug in the code the microkernel doesn't always implies what operating system runs on top of it braunr: but __GNU__ is the correct define for hurd specific code? yes ## 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](http://alioth.debian.org/tracker/download.php/30628/410472/303735/1575/cpulimit-path-max-fix.patch) or [Pulseaudio patch](http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=patch-pulse;att=1;bug=522100). 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](http://walfield.org/pub/people/neal/xgethostname/) 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,...)` ## 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 [[glibc/mmap]]. ## `O_DIRECT` Long story to implement. ## `PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP` We could easily provide it; ## `PTHREAD_STACK_MIN` We should actually provide it. ## `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, will always fail. Use `sem_init()` instead if possible. ## `net/if_arp.h`, `net/ethernet.h`, etc. Not implemented, not POSIX. Try to disable the feature in the package. ## There is no programming interface for the parallel port on GNU/Hurd yet. ## 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)](http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_03.html#tag_02_03). 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](http://docs.python.org/library/errno.html) 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 if there is someone here that can help, i've traced the https issue in iceweasel down to nspr the problem being that the hurd uses the old 4.4bsd sockaddr structure that includes sa_len before sa_family, and nspr directly maps that into its own structure, assuming the internal layout is the same i need to change a configure script so that a macro is defined for the hurd let's see if that works better :) there, ssl now works \o/ it's still the experimental one and there are other minor issues (like no logo on the about panel :p) that's a feature^TM maybe it's not a mistake i haven't seen that version on linux to actually compare *** rbraun_hurd (c3445c23@gateway/web/freenode/ip.195.68.92.35) has joined channel #hurd webchat from freenode :) :D there is also this weird :"Failed to truncate cookie file: Invalid argument Failed to write cookie file: Unknown error (os/kern) 303" error but i guess it's simply a matter of supporting an option in glibc/hurd somewhere 18:06 CTCP VERSION reply from rbraun_hurd: qwebirc v0.91, 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 hm, i didn't version the iceweasel packages :/ i'll rebuild them properly and put them on my repository oh, the freenode webchat actually runs in gnash oO ### IRC, freenode, #hurd, 2014-02-19 http://darnassus.sceen.net/~rbraun/nspr4_hurd.patch in short: nsprt has its own struct sockaddr, which it assumes to have the same layout as the native one doesn't kfreebsd also have sockaddr_len ? and of course, that's not the case on the hurd, because we use an old 4.4bsd header that defines sa_len before sa_family, making all sorts of tests fail in nspr hm i don't know we could discuss that with them but i doubt they don't use iceweasel :) it really seems kfreebsd has sa_len etc. kfreebsd really has sa_len so put it in the new case too :) i'll ask them first something in nspr might already take care of the bsd case elsewhere nspr knows more about bsd systems than it knows about the hurd :) but with all these fixed, i could run iceweasel for a whole day at 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.