2013-01-26

Towards GCC for HelenOS (2) - libgmp

In my previous post about bringing GCC to HelenOS, no actual GCC dependency was compiled. In this post I will describe porting GNU MP Bignum library (libgmp).

This time I will go directly to compiling this library. I assume you already have the configure-for-helenos.sh script ready.

First, a simple patch has to be applied to ensure including of <stdio.h>:

--- gmp-5.1.0/gmp-h.in  2012-12-18 20:05:09.000000000 +0100
+++ gmp-5.1.0/gmp-h.in  2013-01-18 18:27:45.965852213 +0100
@@ -24,6 +24,8 @@
 #if defined (__cplusplus)
 #include <iosfwd>   /* for std::istream, std::ostream, std::string */
 #include <cstdio>
+#else
+#include <stdio.h>
 #endif

Next, the built-in tests require the setbuf() function to be present. This function is part of C89 but is somehow missing in our libc. I suspect that this will not be the only function missing: I will add these functions to my GCC port repository and always compile against this one.

I decided that for now I will try to port it only to the ia32 as it it the simplest (for me) to run and it may save me (at least for now) some troubles because I am compiling on the same architecture.

Finally, we can run the wrapper script:

~/bin/configure-for-helenos.sh \
    -d ~/helenos/gcc-port/ \
    --link-with-cc \
    --ldflags-ignored \
    --cflags="-D_STDIO_H -DHAVE_STRCHR -Wl,--undefined=longjmp" \
    --arch-arg=--host= \
    -- \
        ./configure \
            --disable-shared

Most of the arguments shall look familiar. There are two new ones. First, the --arch-arg automatically adds the correct architecture name to its parameter. I.e. it will look what is the currently selected architecture of HelenOS and append the --host= option with correct argument (--host=i686-pc-linux-gnu for ia32).

The --cflags adds another flags for C compiler, I will describe them in more detail.

-D_STDIO_H
libgmp somehow expects that inclusion guards for standard headers follow some pattern in their naming. HelenOS uses yet different pattern so we need to help the headers a bit (see also the patch above).
-DHAVE_STRCHR
Somehow, the configuration script is not able to detect that we do have strchr().
-Wl,--undefined=longjmp
This one is interesting. The whole problem originates at the fact that we are linking against static libraries. Although the linker flags for specifying libraries do not distinguish between static and dynamic, the behaviour or rather the consequences are different.
The problem is that the linker reads the libraries in the order they were specified on the command-line and does not look backwards when resolving symbols. Thus for static linking you need to specify the libraries from the most specific ones to the most generic ones (i.e. you would put libc as the last one). That is easy to do if you control how the building is done. For someone else's libraries that is not that simple to achieve.
Currently, the script uses --start-group and --whole-archive magic but that doesn't work for libc (due to some problem with soft-int related functions). I admit I have not investigated this into more details but the result is that when tests for libgmp are compiled, the compilation fails on undefined longjmp. The mysterious linker flags --undefined hints the linker that it should treat the given symbol as not yet resolved. It is then properly resolved on -lc and the linking is successful.
--disable-shared
Again, we are compiling only static versions.

Compiling is then straightforward:

make

This will compile the sources and if the run is okay, you can compile the provided tests:

make check

This will fail because the make is also trying to launch them. If you want to actually run them, copy them to uspace/dist/gmp (you need to create that directory first) and rebuild HelenOS. Then boot HelenOS and you can run them manually. All of them shall pass :-).

That is all for now. On the horizon is MPFR. Ahoy!

Žádné komentáře:

Okomentovat