Blog | About

GCC for HelenOS: sitrep

06 Nov 2013

Tags: HelenOS, porting, GCC and coastline

After quite a long time I have another progress report about my efforts to bring GCC to run in HelenOS. It can be summarized in three words. It runs. Somehow.

Below is a screenshot of HelenOS with GCC installed and compiling the Hello, World! program.


As you can see, it somehow works. The user needs to specify a lot of switches to actually compile the source code but it produces a valid binary that we can run.

I am planning another post describing in more detail the current "to-do" list. The rest of this post is for those who want to try to build GCC for HelenOS by themselves or for those who are interested in some technical details of the process.

Building GCC for HelenOS

Unless you want to play with a lot of environment variables and a lot of command-line switches, the easiest way to build GCC is to use my scripts from the coastline repository that I wrote about earlier.

I will assume that you have cloned this repository into ~/helenos/coastline.

This repository contains scripts for building various software for HelenOS. The actual build takes place in a different directory though. I will assume that you will use ~/helenos/coastline-build-ia32. The ia32 suffix denotes that we will be building for 32bit Intel architecture (the naming is not mandatory but it seems to me as a natural way to do things).

Before we start building GCC, we need to prepare the build directory a little bit. First of all, add the following text to ~/helenos/coastline-build-ia32/hsct.conf.

root = /your/path/to/helenos/mainline/directory
arch = ia32

As you probably noticed, you can use the mainline branch as all the needed fixes were already integrated. The path shall be an absolute path, fully expanded (that is: no ~ for home directory etc.).

Before proceeding to building GCC, configure and build HelenOS for ia32, with following options set:

  • Include development files
  • Build binutils binaries

Once this is finished, change to ~/helenos/coastline-build-ia32 and issue the following command.

~/helenos/coastline/ install gcc

This command does the following:

  • Downloads tarballs with GCC and other libraries
  • Determines what are the prerequisities for building GCC and builds them first
  • Patches GCC sources to enable cross-compilation to HelenOS
  • Executes the GCC ./configure script with proper switches
  • Builds GCC for HelenOS
  • And installs the compiled binaries into HelenOS source tree, under the uspace/dist directory.

If there is no problem, the above command should start with following messages printed (I manually shortened some of them so they fit here more easily)

>>> Need to build libgmp first.
    -> Running ~/helenos/coast/ package libgmp
>>> Obtaining CC, CFLAGS etc.
>>> Fetching sources...
>>> Building...
[hsct]: tar xjf gmp-5.1.0.tar.bz2
>>> Patching gmp.h...
patching file gmp-5.1.0/
[hsct]: ./configure --disable-shared <... and much more options>
checking build system type... coreisbr-unknown-linux-gnu
checking host system type... i686-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for i686-pc-linux-gnu-strip... no
checking for strip... strip
configure: WARNING: using cross tools not prefixed with host triplet
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes

and end after several minutes (depending on how powerful machine you have) with following text

make[1]: Leaving directory '~/helenos/coast-build-ia32/build/gcc/build/gcc'
[hsct]: mkdir ~/helenos/coast-build-ia32/apps/gcc
[hsct]: cp PKG/usr/local/bin/gcc ~/helenos/coast-build-ia32/apps/gcc
[hsct]: cp PKG/usr/local/bin/cpp ~/helenos/coast-build-ia32/apps/gcc
[hsct]: cp PKG/usr/local/bin/gcov ~/helenos/coast-build-ia32/apps/gcc
[hsct]: cp PKG/usr/local/libexec/gcc/i686-pc-linux-gnu/4.6.3/cc1 ~/helenos/coast-build-ia32/apps/gcc
>>> Installing...
[hsct]: mkdir -p ~/helenos/mainline/uspace/dist/coast/gcc/
[hsct]: cp ~/helenos/coast-build-ia32/apps/gcc/* ~/helenos/mainline/uspace/dist/coast/gcc/
>>> Creating install script

If you encounter some problem, I would be glad to help. It is okay to post code excerpts thought the comment form below (please, use the <PRE> tag for it) but for long parts rather use some external service, such as PasteBin.

Before I describe some of the patches applied to the sources, let's try the GCC in HelenOS. Switch back to HelenOS and rebuild it (just run make).

Now, you can start HelenOS and see GCC running. The easiest way is to run the tools/ helper script. Once inside HelenOS shell, install GCC to /app/ by executing

batch /coast/install.gcc

This is needed for following reasons.

  • All files coming from the coastline are installed into uspace/dist/coast to allow smooth cleaning.
  • gcc currently has a hard-coded path to other binaries it launches and expects them in /app/.

After this "installation", you can try running gcc -v. The last line shall say.

gcc version 4.6.3 (GCC)

Now you can try to compile the demos. Do not forget that a lot of switches are needed now:

-nostdinc -I/inc/c
-nostdlib -L/lib -lc -lsoftint

Harbour, patches & co.

Here I would like to describe a bit what patches are currently needed and why. Most of the notes here are based on the comments in the GCC HARBOUR file that controls the compilation and installation. For details, I recommend consulting the gcc/HARBOUR file and the individual patches. Here, only the most important ones are desribed.

First of all, it is necessary to use a custom (hosted) GCC binary. I had some problems convincing ./configure about the proper flags to GCC and thus I used the approach used by the binutils port. Instead of GCC a shell script is used that adds all the HelenOS-specific flags plus a bunch of other flags needed to build GCC.

Next, there is a bunch of patches where configure is not able to properly detect some functionality. I was not able to figure out why it makes some assumptions but in the end the patches are pretty small.

Another bigger group of patches forces cross-compilation. The problem is rather simple. Let's assume you want to compile GCC for ia32 on a 32bit Intel machine running Linux (which I believe is a pretty common situation). The ia32 architecture means you are using i686-pc-linux-gnu target of the cross-compiler (i.e. you use i686-pc-linux-gnu-gcc for compilation). And this target would be also given to the configure script via the --target and --host options. However, the configure script also detects on which system it runs (using the config.guess and --build option) and for this setting, it would detect i686-pc-linux-gnu. Yes, that is the same value. Thus, all three options would use the same value: to the script it looks that no cross-compilation is taking place. However, this is only one part of the problem. The other part is that during the compilation of GCC extra (generator) tools are build and these are run during the compilation. And since to the configure script it looks that there is no cross-compilation taking place, it uses the same flags etc. both for building the tools and for building the compiler. Obviously, running tools built with HelenOS libraries under Linux can not work. Unfortunately, only forcing the cross-compilation by setting variables in the configure scripts is not enough. It is also necessary to force different --target from --build. For ia32 that is done by substituing i686 with i386 which somehow works. Proper solution is to create a HelenOS-specific target.

Last thing that is worth mentioning is how gcc executes other programs. gcc (the binary) is actually only a driver that coordinates launching other binaries doing the actual job. Among them is the preprocessor cpp, assembler or linker. The process of starting a different binary is hidden inside iberty library that is used as a unifying wrapper by many GNU programs. The module responsible is called PEX (process execution). Since we are compiling for POSIX system, it naturally expects that launching of the programs would be done with the fork/exec pair. Of course, HelenOS does not provide such functions and their emulations would be very difficult, if not impossible. A sidenote: I think we would be able to emulate vfork() by duplicating fibril stack which could work in most cases. Anyway, here the simplest solution was to modify the PEX implementation and replace it with HelenOS specific functions. The implementation is in a standalone file that needs to be cleaned-up. Quite a lot, as a matter of fact.

Instead of conclusion

First of all, thank you if you followed this post so far. As I already said, I am planning another post about GCC porting summarizing what still needs to be done to have GCC as a native compiler inside HelenOS. I would be glad if you try to build GCC by yourself using my coastline scripts. If you encounter a problem, feel free to either report it here as a comment (just don't paste too long logs here) or as a bug report in coastline. I am also subscribed to HelenOS development mailing list if you have a more generic question/comment regarding porting applications to HelenOS.

Thanks for reading!


Watch comments through RSS

Add a comment

The e-mail will be used to get a Gravatar picture and will not be directly displayed.

Please, show me you are not a robot.

You can use basic HTML formatting (following tags are allowed: A, CODE, PRE, B, I, STRONG, P and BLOCKQUOTE). For replies, I recommend using the Quote button next to a post.