* toolchain/cross-gnu.mdwn: I added an introductory paragraph to explain the difference between native and cross compilation, and I linked to Flavio's cross-hurd project. I removed the cross-gnu project reference. Does anyone still use that shell script? And I added Sergey's guide for how to cross-compile the X86 Hurd on a GNU/Linux machine as an example guide. --- toolchain/cross-gnu.mdwn | 351 ++++++++++++++++++--------------------- 1 file changed, 160 insertions(+), 191 deletions(-)
diff --git a/toolchain/cross-gnu.mdwn b/toolchain/cross-gnu.mdwn index 53a85214..da07b1eb 100644 --- a/toolchain/cross-gnu.mdwn +++ b/toolchain/cross-gnu.mdwn @@ -11,16 +11,23 @@ License|/fdl]]."]]"""]] [[!tag stable_URL]] -[[Thomas_Schwinge|tschwinge]] has written a shell script for building a -complete cross-build environment for GNU/Hurd systems. - -Find it in the [[source_repositories/incubator]], *cross-gnu/master* branch. - - -# Using - -Read through it. Understand it. Only then use it by following the next steps. - +How do you go about building the Hurd on a different CPU architecture? +Typically you compile the Hurd natively. That is to say, that you +build an `X86_64` Hurd on an `X86_64` computer, but how do you compile +the Hurd to a new CPU architecture? Say AArch64, Power9, or Risc-V ? +In that case you build the Hurd with a `X86_64` computer for a +different architecture, which is called a cross build. Some Hurd +developers (like Sergey) prefer to develop the Hurd on via cross +building it, which lets them use GNU/Linux's gdb to debug the +resulting binaries. Others like Samuel, prefer just to use the +standard debian workflow that Debian GNU/Hurd provides. + +Flávio Cruz has written a shell script to cross build GNU/Hurd systems +called [[cross-hurd|https://github.com/flavioc/cross-hurd]]. It is +probably the most complete tool for the job. With it you can build a +`hurd-i386` and `hurd-x86_64` system with GNU/Linux. If you are +trying to cross-build an AArch64 Hurd system, then you will probably +want to look at the [[arm port page|open_issues/arm_port]]. # Status @@ -30,189 +37,151 @@ support for C and C++ so far, but not for other languages. A bunch of fixes / enhancements of [[glibc]] are missing. We're working towards minimizing these differences, as well as towards pushing all patches upstream. +# cross compiling the Hurd manually + +Just use Flávio's [[cross-hurd|https://github.com/flavioc/cross-hurd]] +project. If however, you just want to cross-compile the Hurd manually +for the learning experienence or want to port the Hurd to a CPU +architecture that cross-hurd doesn't support, then please do read +through Flávio's cross-hurd project. Try to understand how it works. +Only then try to manually cross-compile the Hurd. + +Here's how you can cross-compile a X86 (32 bit) Hurd from a GNU/Linux +machine. On your GNU/Linux machine install the dependencies: bison, +flex, the three libraries GCC needs. In the below guide, make sure +that you download the latest software. The below guide will have to +download outdated software, but the build process is still the same. +The guide below has `-j8` written a lot, which corresponds to the +number of cores that your processor has. If your processor has four +cores then use `-j4` instead. + +Set up the basic directory structure: + + $ export PREFIX=~/dev/crosshurd + $ export PATH=$PREFIX/bin:$PATH + $ mkdir $PREFIX && cd $PREFIX + $ mkdir src include i686-gnu + $ ln -s ../include i686-gnu/sys-include + $ ln -s ../lib i686-gnu/lib + $ cd src + +Build binutils: + + $ wget https://ftp.gnu.org/gnu/binutils/binutils-2.39.tar.gz + $ tar xf binutils-2.39.tar.gz + $ cd binutils-2.39 + $ mkdir build && cd build + $ ../configure --target=i686-gnu --prefix=$PREFIX --with-lib-path=$PREFIX/lib + $ make -j8 + $ make install + +Verify that e.g. `$PREFIX/bin/i686-gnu-nm -v` works. + +Now build GCC: + + $ wget https://ftp.gnu.org/gnu/gcc/gcc-12.2.0/gcc-12.2.0.tar.gz + $ tar xf gcc-12.2.0.tar.gz + $ cd gcc-12.2.0 + $ mkdir build && cd build + $ ../configure --prefix=$PREFIX --target=i686-gnu + --with-lib-path=$PREFIX/lib --disable-multilib --enable-languages=c + $ make -j8 all-gcc + $ make install-gcc + +Note that at this step we're only building GCC itself, not libgcc -- +that will have to wait until we install glibc headers. + +Next, we want to build MIG. MIG needs Mach headers, but we can't build +GNU Mach without MIG. So what we do is we 'make' GNU Mach twice, once +to install the headers, and later on once more to actually build it. + + $ git clone git://git.savannah.gnu.org/hurd/gnumach.git + $ cd gnumach + $ autoreconf -i + $ mkdir build && cd build + $ CC=gcc ../configure --prefix=$PREFIX --host=i686-gnu + $ make install-data + +At configuring step, it will warn that "mig was not found, we will not +be able to build a kernel, only install headers. Install or build mig +against them, and run configure again". This is exactly how we want it +at this first step. + +The trick here is to tell configure to use host's GCC instead of our +previously built i686-gnu-gcc. This is because we are not yet building +GNU Mach for real, we're only doing this to install the headers. But +we need to appease configure into generating a Makefile for us, hence +`CC=gcc`. + +Now we should have `$PREFIX/include/mach/message.h`, +`$PREFIX/include/mach/i386/machine_types.defs` and suchlike. + +Now, onto building MIG: + + $ git clone git://git.savannah.gnu.org/hurd/mig.git + $ cd mig + $ autoreconf -i + $ mkdir build && cd build + $ ../configure --target=i686-gnu --prefix=$PREFIX + $ make -j8 + $ make install + +Now, before we build glibc, we should install Hurd headers similarly +to how we've installed Mach headers above: + + $ git clone git://git.savannah.gnu.org/hurd/hurd.git + $ cd hurd + $ autoreconf -i + $ mkdir build && cd build + $ CC=gcc ../configure --host=i686-gnu --without-parted \ + --without-libcrypt --without-libbz2 --without-libz --without-rump + $ make no_deps=t prefix=$PREFIX install-headers + +Now, it's finally time to tweak glibc: + + $ git clone https://sourceware.org/git/glibc.git + $ mkdir build && cd build + $ ../configure --build=$(../scripts/config.guess) --host=i686-gnu \ + --prefix=$PREFIX --with-headers=$PREFIX/include + $ make install-headers + +We also need to do some hacky things manually in order for this to +start looking enough like a real glibc installation: + + $ touch $PREFIX/include/gnu/stubs.h $PREFIX/lib/libc.so + $ make csu/subdir_lib && install csu/crt1.o csu/crti.o csu/crtn.o $PREFIX/lib + +Now we can go back to GCC and build libgcc: + + $ make configure-target-libgcc + $ make -j8 all-target-libgcc + $ make install-target-libgcc + +And now we can once again go to glibc and build it for real: + + $ make PARALLELMFLAGS=-j8 + $ make install + +At this point it should be possible to cross-compile a C hello world +for the Hurd with no ceremony: -## Supported Versions of Source Packages - -/!\ This is outdated. Contact [[tschwinge]]. - -The following ones are known to work. Others may work as well, but no -guarantee is given. Always the preferred version is listed first. - - * [[`src/binutils`|binutils]] - - * CVS `binutils-2_20-branch` - - $ mkdir binutils-2_20-branch - $ cd binutils-2_20-branch/ - $ cvs -d:pserver:anon...@sources.redhat.com:/cvs/src ↩ - co -r binutils-2_20-branch binutils - - The sources are rooted in `binutils-2_20-branch/src/`. Also use the above - commands for updating, instead of the usual `cvs update`. - - * Release 2.22 or later from <ftp://ftp.gnu.org/gnu/binutils/> - should also be fine. - - * [[`src/gcc`|gcc]] - - * SVN `gcc-4_5-branch` - - $ svn co svn://gcc.gnu.org/svn/gcc/branches/gcc-4_5-branch - - Patches: - - * <http://gcc.gnu.org/ml/gcc-patches/2010-04/msg00602.html> - - Prepare: - - $ ( cd gcc-4_5-branch/ && contrib/gcc_update --touch ) - - * SVN `gcc-4_4-branch` - - $ svn co svn://gcc.gnu.org/svn/gcc/branches/gcc-4_4-branch - - Patches: - - * <http://gcc.gnu.org/ml/gcc-patches/2010-04/msg00602.html> - - Prepare: - - $ ( cd gcc-4_4-branch/ && contrib/gcc_update --touch ) - - * Releases of the 4.5 and 4.4 series from <ftp://ftp.gnu.org/gnu/gcc/> - should also be fine, but need the same set of patches as the - `gcc-4_5-branch` needs. - - * [[`src/gnumach`|microkernel/mach/gnumach]] - - * Git `master` branch - - $ git clone ↩ - git://git.sv.gnu.org/hurd/gnumach.git gnumach - - Prepare: - - $ ( cd gnumach/ && autoreconf -vi ) - - * [[`src/mig`|microkernel/mach/mig/gnu_mig]] - - * Git `master` branch - - $ git clone ↩ - git://git.sv.gnu.org/hurd/mig.git mig - - Prepare: - - $ ( cd mig/ && autoreconf -vi ) - - * [[`src/hurd`|hurd]] - - * Git `master` branch - - $ git clone ↩ - git://git.sv.gnu.org/hurd/hurd.git hurd - - * [[`src/libpthread`|libpthread]] - - * Git `tschwinge/Peter_Herbolzheimer` branch - - $ git clone --no-checkout ↩ - git://git.sv.gnu.org/hurd/libpthread.git libpthread - $ cd libpthread/ - $ git checkout origin/tschwinge/Peter_Herbolzheimer - - Prepare: - - $ ( cd libpthread/ && autoreconf -vi ) - - * [[`src/glibc`|glibc]] - - * Git `tschwinge/Roger_Whittaker` branch - - $ git clone --no-checkout ↩ - git://git.sv.gnu.org/hurd/glibc.git glibc - $ cd glibc/ - $ git checkout origin/tschwinge/Roger_Whittaker - -<!-- - - * [[`src/gdb`|gdb]] - - This is optional and will only be compiled if present. - - * CVS `gdb_6_6-branch` - - $ cvs -d:pserver:anon...@sources.redhat.com:/cvs/src ↩ - co -r gdb_6_6-branch gdb - $ mv src gdb_6_6-branch - - Also needs some patch because of MIG changes, if I remember correctly. - - * Recent tarballs from <ftp://ftp.gnu.org/gnu/gdb/> should also work. - ---> - - -## Preparation - -The raw source code trees are about 1 GiB. - -Unpack the tarballs if you downloaded any. - -Create a directory where the cross build shall be rooted in, and a `src` -subdirectory in there. Then create symbolic links for every of the above -packages: from `src/PACKAGE` to where you stored or unpacked it. If you don't -intend to build several cross compilers or use the source trees otherwise, you -can also directly store the source trees in `src/`. The source trees can be -shared between multiple cross build trees since the packages' build systems are -supposed not to modify the files in the source trees. Not all packages adhere -to that, but they fail to do so only for pre-processed documentation, etc. - -Either make sure that `cross-gnu-env` and `cross-gnu` are found in `$PATH` -(`~/bin/`, for example) or alternatively remember to use their full paths in -the following. - -The system you're running the script on (the *build* system) needs to have -basic development tools installed, that is, a C compiler with libraries, -`make`, and several more packages. If anything is missing, the *cross-gnu* -build will abort, and you have to install the missing dependencies and resume -the *cross-gnu* build. - - -## Setting Up the Environment - -Do this every time you intend to use the cross compiler: - - $ ROOT=to/the/cross/build/root - $ . cross-gnu-env - -This will set several environment variables, which are later used by (a) the -`cross-gnu` script and (b) by you, the user of the cross compiler. `$TARGET` -will be set by the script, `$PATH` will be adjusted, etc. See the -`cross-gnu-env` file for all environment variables that are set, as well as -their default values. `$ROOT` will be made an absolute path if it isn't -already. - -Later, you'll be able to do things like `../configure --host="$TARGET"`, and the -cross compiler will be found automatically. - - -## Creating the Cross Build Environment - -This will need an additional 2 GiB. + $ $PREFIX/bin/i686-gnu-gcc hello.c -o hello -After setting up the environment, just run `cross-gnu` and watch the messages -flow by. In the end you should see a message: *[...]/cross-gnu: Everything -should be in place now.* +Now we can rebuild Mach and Hurd properly, if we want to: + + $ make distclean + $ ../configure --prefix=$PREFIX --host=i686-gnu + $ make -j8 + $ make install + $ make distclean + $ ../configure --host=i686-gnu --without-parted --without-libcrypt \ + --without-libbz2 --without-libz --without-rump + $ make -j8 DESTDIR=$PREFIX install -## Staying Up-To-Date +Now we can run boot the Hurd. Your [[qemu +invocation|hurd/running/qemu]] will look different depending on what +you want, but it will probably look a little like this (note I did not +test this): -You can re-run `cross-gnu` to rebuild the parts of the sources that have -changed since the last run. This will save a lot of time compared to starting -from scratch again. Also, it is especially useful if you aren't working with -unpacked tarballs, but on CVS's / SVN's / Git's branches or want to quickly get -a new toolchain -with patches you applied to the source trees. However: do *not* use this -technique when doing major changes to the source trees, like switching from GCC -4.4 to GCC 4.5. + $ qemu-system-i386 -m 4GB -drive cache=writeback,file=hd.img -M q35 -- 2.45.2