Using GCC as cross-compiler with x86_64 target

Edit: Almost five years later, this post still gets quite a bit of traffic. Today, you can get yourself a modern, ready made x86_64 cross-compiler, and associated binutils with a single command:

brew install x86_64-elf-gcc

Obviously you’ll need homebrew – which is available for (at least) macOS and Linux πŸ™‚

This post might still be handy if you’re wanting to build your own, but definitely get something more up to date than GCC 6 πŸ˜…

Future Me from 2023

This post is a little rough, and is intended both as a memory aid for myself and as an example for anyone else who needs to know this stuff. I’ve recently decided to push toward x86_64 support in my toy/research OS project, and needed to build a GCC cross compiler for that target. In my case I already had an x86 cross compiler built, but I’ve tried to make the steps general for those that don’t.

These steps are tested with binutils 2.26.1 and GCC 6.1.0. I’m using those versions as they match the version of my x86 cross compiler – These steps might work with the more recent versions, but I can’t guarantee it. I will at some point update my cross compilers, at which point I’ll update these steps.

1. Go to your $HOME/src. Create first if needed.

# mkdir ~/src
# cd ~/src

2. Set up prefixes. PATH is only needed if not already set (e.g. this is your first cross compiler on this system).

# export PREFIX="$HOME/opt/cross"
# export TARGET=x86_64-elf
# export PATH="$PREFIX/bin:$PATH"

3. Configure, build and install binutils

# tar xf /path/to/downloaded/binutils-2.26.1.tar.gz
# mkdir build-binutils-x86_64
# cd build-binutils-x86_64
# ../binutils-2.26.1/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
# make && make install

4. Extract GCC

# cd ..
# tar xf /path/to/downloaded/gcc-6.1.0.tar.gz

Ensure libgcc is built with no redzone – Add this:

MULTILIB_OPTIONS += mno-red-zone
MULTILIB_DIRNAMES += no-red-zone

to the following (new) file:

gcc-6.1.0/gcc/config/i386/t-x86_64-elf

And then make sure GCC configure knows about the new config:

# vim gcc-6.1.0/gcc/config.gcc
/x86_64-\*-elf\*)

And insert:

tmake_file="${tmake_file} i386/t-x86_64-elf"

above the tm_file line.

5. Configure GCC

# mkdir build-gcc-x86_64
# cd build-gcc-x86_64
# ../gcc-x.y.z/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers

6. Build GCC

# make all-gcc

Go make coffee/eat out at a restaurant/vacation in Barbados…

Note: If building with newer GCC (Found with 7.3.1), there’s an issue in the 6.1.0 source. If you see error:

error: ISO C++ forbids comparison between pointer and integer [-fpermissive]

relating to gcc/ubsan.c, then you’ll need to edit that file, and change line 1473 from:

|| xloc.file == '\0' || xloc.file[0] == '\xff'

to:

|| xloc.file[0] == '\0' || xloc.file[0] == '\xff'

7. Build libgcc

# make all-target-libgcc

8. Install GCC and libgcc

# make install-gcc
# make install-target-libgcc

9. Check the no-redzone libgcc is being used properly when -mno-red-zone is passed:

# x86_64-elf-gcc -mno-red-zone -print-libgcc-file-name

Should print (note the no-red-zone in the path):

$HOME/opt/cross/lib/gcc/x86_64-elf/6.1.0/no-red-zone/libgcc.a

10. Don’t forget to pass -mno-red-zone in LDFLAGS in the actual build!

Published by roscopeco

Principal Software Engineer, code junkie, retro computing nut, occasional blender artist and open-source activist.

Don’t bother to leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

PJ5 TTL CPU

Blog about the TTL based CPU design we're making

Don Charisma

because anything is possible with Charisma

Tech Filled Fantasy

One stop shop for all your tech-filled pleasures!