Cross-compiling the GNU Hurd                             -*- Outline -*-

* READ HERE!

The procedure described below -- albeit not completely obsolete, of course --
is outdated a bit.  If you attempt to build a cross compiler, have a look at
<http://www.bddebian.com/~wiki/hurd/building/cross-compiling/> for now.

Last update 1998-06-01  Gordon Matzigkeit  <gord@gnu.org>.
Previous update 1996-04-11  Thomas Bushnell, n/BSG  <thomas@gnu.org>.

* Introduction
These are instructions for building the Hurd as in cross-development
environment.  Unless you are building the Hurd on an already running
Hurd system, you will need these directions to build the Hurd from any
other kind of system.  Even if you are using a Mach system (Lites,
say) you will *STILL* need to follow these directions; this is still
cross-compilation.

IMPORTANT: If you are not prepared to fix bugs without begging other
people for help, or you lack patience, then this process is *not for
you*!  Go get a binary distribution... downloading 80MB of files over
a 9600 baud PPP connection takes far less time and effort than
cross-compiling, especially when you consider that the size of the
source code for all the packages in the Hurd binary distribution is
larger than the distribution itself.

You will need *at least* 500 MB of free disk space for the build
process.  More is always better.

NOTE: On the other hand, do not be sloppy with any of these
instructions, until you have tried following them exactly, and they
didn't work for you the first time. There are all sorts of pitfalls
and untested paths, so it is better not to be creative with things
(like trying to install the cross-compiler somewhere other than
/usr/local).  Expect random problems if you deviate from these
instructions.  You have been warned.

In other words, follow these instructions closely, but not blindly.

You may wish to create build logs, so that you can trace any problems
after you let a compilation run unattended.  To do this, background
and redirect all make output to a file (i.e. `nohup make -k >&
make.out &').  If you wish to monitor the build, you can use a command
like `tail -f make.out'.  After the build completes, simply search the
log for `***' (i.e. `grep '\*\*\*' make.out'), and you'll find any
errors.

* Cross-compiler tools

First you must install a cross-GCC and binutils.  Currently, GCC 2.8.1
and binutils version 2.9.1 are the minimum suggested versions.

Even if you are building the Hurd on a 586, even if it's running a
different Mach-based OS, you are still cross-compiling.  Don't attempt
to use tools that have been configured for something other than
i586-gnu (unless, of course, you are trying to port the Hurd to a
different processor).

** Binutils

The cross-binutils installation is quite straightforward.  Just
configure, build and install them with commands like:

$ [cd to top of binutils source tree]
$ mkdir obj
$ cd obj
$ ../configure --prefix=/usr/local --target=i586-gnu
[...]
$ make
[...]
$ su
Password:
# make install
[...]
#

The above instructions show you how to create a new build
subdirectory, `obj', and then configure and build the package there.
You should get used to this process, because some of the Hurd packages
will not build properly in any other way.

This installation should be smooth.  If you see any strange errors
during the build process, you should investigate them, since they are
probably bugs.

** GCC (attempt #1)

Bootstrapping a GCC cross-compiler is only slightly more difficult
than installing a cross-binutils.  GCC has a few interdependencies
with the Hurd libc, such as the creation of the `libgcc2.a' library.

Therefore, the first time you try compiling and installing GCC, you
will need to kludge things so that you can get a mostly-working
compiler, then come back and redo them to get a fully-working
compiler.

There is a bug when creating a cross-compiler on certain platforms.
In order to avoid this bug, you should copy a working `float.h' header
file from a known working GCC installation for the same processor.  On
a GNU/Linux machine using gcc-2.7.2.1, `float.h' can be found in
`/usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h'.  In general,
you can find it in
`$(prefix)/lib/gcc-lib/$(host)/$(VERSION)/include/float.h'.  You will
need to copy this file into the `include' subdirectory of the unpacked
GCC distribution, overwriting the old `include/float.h' if it exists.

The build process should look something like the following.  Be sure
to use the `-k' and `LANGUAGES=c' make arguments this time around, or
else the build will fail in random places:

$ [cd to top of gcc source tree]
$ cp /usr/lib/gcc-lib/i386-linux/2.7.2.1/include/float.h include/float.h
$ mkdir obj
$ cd obj
$ ../configure --prefix=/usr/local --target=i586-gnu --with-gnu-as --with-gnu-ld
[...]
$ make -k CFLAGS="-g -O2" LANGUAGES=c
[... fails while trying to build libgcc2.a]
$ su
Password:
# make -k install LANGUAGES=c
[again, fails on libgcc2.a]
#

If the build fails anywhere except on libgcc2, you have a problem.
Investigate it.  Otherwise, you should now have a mostly-working
cross-compiler suite in /usr/local.

NOTE: Do not delete the GCC compile tree.  You will need it later in
order to finish the installation.  If you choose to delete it, you
will have to repeat this step in its entirety.

* Set up the Hurd root

You need space to "install" the compiled Hurd, its libraries, include
files, and binaries that will run on the Hurd.  In these instructions,
we will refer to this as the "installation staging area".  This will,
more or less, be a suitable image to use as a Hurd root image when you
are finished.

This space needs to be accessible to the machine doing the
cross-compilation, because the libc and include files that go in the
Hurd's root filesystem are the same ones that are needed during
cross-compilation.

We strongly advise that this directory not be put in /usr/local.  This
will tend to cause confusion.  It would be a good idea to create a new
filesystem, and mount it on your cross-compilation machine as /hurd.

If you followed the directions above, then in /usr/local/i586-gnu you
already have a number of cross-development tools (ar, ranlib, ld, as
and so forth).  This is the place where the compiler looks for
cross-development stuff.  So now make two symlinks, named
/usr/local/i586-gnu/include and /usr/local/i586-gnu/lib, and point
them at /hurd/include and /hurd/lib, where `/hurd' is the name of your
Hurd installation staging area.

If /usr/local/i586-gnu/include or /usr/local/i586-gnu/lib already
exists, you should move their contents to your Hurd installation
staging area before creating the symlinks.

If you don't do these steps, you will lose.  Do them now.

* Install Mach

Get the latest gnumach distribution, and configure it to cross
compile.  You should read the README in order to determine which
device driver options you should use.  You should also specify your
current build platform... in the following example, we are
cross-compiling from an i586-linux-gnu machine:

$ [cd to top of gnumach source tree]
$ mkdir obj
$ cd obj
$ CC=i586-gnu-gcc ../configure --build=i586-linux-gnu --host=i586-gnu \
  --enable-com --enable-floppy --enable-ide --enable-aha152x
[...]
$ make
[...]
$ su
Password:
# make install prefix=/hurd
[...]
#

Besides building the Mach kernel, this step installs several Mach
headers and interface files into the staging area.  These files are
required for cross-compilation.

* Install a cross-MiG

This process can be confusing, because there are so many different
varieties of cross-compilers:

1) When you were building Mach, above, the build process needed a MiG
which can could run on the build machine, but create code for GNU.
This is called `local-mig' in the Mach Makefiles.

2) Then, when you installed Mach, you also installed a MiG which can
run on GNU and create code for GNU.  This is called `cross-mig' in the
Makefiles.

3) Now, you need to install a version of MiG like #1, so that you can
use it to build the C library and the Hurd.  Unfortunately, the shell
script wrapper used in #1 is not appropriate for installation, so you
need to generate Yet-Another-MiG:

# make install-local-mig prefix=/usr/local
[...]
#

Be sure to set the `prefix' variable as indicated, or you will
accidentally clobber the MiG you installed in the previous step.

* Build the GNU C library

In order to build the GNU C library for the Hurd, you will need recent
versions of several tools, including gawk.  See the glibc INSTALL file
for more details.

** Install Hurd headers

The Hurd interface definitions and include files need to be visible to
the cross-compiler so that the C library can use them.

$ [cd to top of hurd source tree]
$ mkdir obj
$ cd obj
$ ../configure --build=i586-linux-gnu --host=i586-gnu \
  --prefix=/hurd --disable-profile
[...]
$ su
Password:
# make install-headers no_deps=t
[...]
#

This step may spout a few warning messages, but you don't need to
worry about them, because you aren't interested in compiling any of
the Hurd (yet).


** Build and install C library

Configure, compile, and install the core GNU C library (note that we
reset the `install_root' variable instead of `prefix'):

$ [cd to top of glibc source tree]
$ mkdir obj
$ cd obj
$ ../configure --build=i586-linux-gnu --host=i586-gnu \
   --prefix= --enable-add-ons=crypt --disable-profile
[...]
$ make -k
[... fails when trying to link programs]
$ su
Password:
# make -k install install_root=/hurd
[... again, fails]
#

This process fails because the cross-GCC you installed is missing
libgcc2.a, which is required to link working programs.  Do not delete
the libc source files... you will need them again very soon.

** Finish GCC install

If you were silly, and deleted the GCC source tree, you need to go
back to the first GCC build step and follow those instructions again
(which should successfully build and install the entire C
cross-compiler).

Otherwise, there are now enough headers to finish installing the GCC
cross-compiler, so do it:

$ [cd to top of gcc source tree]
$ cd obj
$ make -k
[...]
$ su
Password:
# make -k install
[...]
#

This time there should be no failures.

** Finish libc install

Now there is a fully-working GCC, so the libc programs can be built.
Continue the build process:

$ [cd to top of glibc source tree]
$ cd obj
$ make -k
[...]
$ su
Password:
# make -k install install_root=/hurd
[...]
#

There should be no errors or warnings from this step.


* Install the Hurd

Since you already configured the Hurd in a previous step, you can now
build and install it:

$ [cd to top of hurd source tree]
$ cd obj
$ make -k
[...]
$ su
Password:
# make -k install prefix=/hurd
[...]
#

This step should complete with no problems.


* Final details

Now in your Hurd staging area are the complete binaries for the Hurd
and its programs, and the C library and its associated programs.  You
will want binaries for other programs too, of course--for example, you
have no shell yet.  In general, you can build most GNU packages
without too much hassle using your cross compilers.  In this way you
can build up as much of a binary distribution as you like.

See the file `INSTALL-binary' for instructions on bootstrapping and
running your new binaries.
