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/hsct.sh 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/hsct.sh 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/gmp-h.in
[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/ew.py
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
-Wl,-T/inc/_link.ld
-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!
Comments
Watch comments through RSS