Skip to content

Building on Ubuntu Linux (Unprivileged User)

SamJakob edited this page Feb 25, 2023 · 5 revisions

These instructions contain slight inaccuracies and need to be updated. Proceed at your own peril.

Before setting up your toolchain, you'll need to decide upon an installation prefix.
If you're running as a privileged user, you can leave the prefix as the default for your platform.

If, however, you are not running as a privileged user - e.g., on a shared system - you should install the toolchain in your home directory, however if you do this, make sure you use $HOME instead of ~ as some shells will not properly expand the prefix.

Suggested prefixes:

  • /usr/local/gcc
  • $HOME/gcc (mkdir -p $HOME/gcc)

You may decide to set a variable for your prefix, so that you don't have to specify it in full for each command:

# For example...
export GCCPREFIX="$HOME/gcc"
# Then $GCCPREFIX can be used for your prefix in each command.

Building the toolchain manually

Download or clone the latest version of gnu-binutils.
Note that we need to add --enable-targets=all to get EFI app support.
Run the following commands to configure and build gnu-binutils:

# Make sure to specify or substitute $GCCPREFIX!
./configure --enable-targets=all --target="x86_64-elf" --disable-nls --prefix="$GCCPREFIX"
make
make install

At this point, you'll need to update your PATH to include the cross-compiled linker and assembler tools. You can do this as follows:

# Assuming you're using bash as your shell.
# If you're using zsh, `source ~/.zshrc` instead.
source ~/.bashrc

Next, download or clone the latest version of gcc (use v11.2.0+). Run the following commands to configure and build gcc:

# Downloads GMP, MPFR and MPC. (Requirements for building GCC).
./contrib/download_prerequisites

# Switch to a build directory
# DON'T FORGET THIS STEP! Building in-tree is a bad idea,
# will probably break and is otherwise not recommended.
mkdir build-gcc
cd build-gcc

# Configure GCC for installation
../configure --target=x86_64-elf --prefix="$GCCPREFIX" --disable-nls --without-isl --without-headers --enable-languages=c,c++ --with-as="$(which x86_64-elf-as)" --with-ld="$(which x86_64-elf-ld)" --disable-hosted-libstdcxx

# Now make gcc and libgcc
make all-gcc
make install-gcc
make all-target-libgcc
make install-target-libgcc

Building gnu-efi

If you are able to install, or have gnu-efi already - you may just use that version.
Otherwise, you can clone the fork set up for this project. (It's a known compatible version of gnu-efi with a patch applied for Clang support. Note, however, that Clang support for this project was abandoned.)

  1. Change to gnu-efi (third-party/gnu-efi):
git pull --recurse-submodules # Make sure submodules are up-to-date.
cd third-party/gnu-efi

NOTE: This is a git submodule. You'll need to either clone the Thornhill repository with git clone git@github.com:SamJakob/thornhill.git --recurse-submodules (i.e., with the --recurse-submodules flag), or, alternatively - as shown - run git pull --recurse-submodules in third-party/gnu-efi.

  1. Create a local include directory for yourself (or use the system one with /usr/local/include):
mkdir -p $HOME/include
  1. Grab a supplementary ELF header file (elf.h) with:
curl https://gist.githubusercontent.com/SamJakob/8b0de39e1d1fcde5c7df204d7e2d899b/raw/elf.h | tee $HOME/include/elf.h
  1. Build gnu-efi with:
export CROSS_COMPILE="x86_64-elf-"
export CFLAGS="-I $HOME/include"
make
make install PREFIX="$GCCPREFIX"

Building cmake

Ensure you've cloned a version of CMake >= 3.20.

sudo apt install libssl-dev
wget https://github.com/Kitware/CMake/releases/download/v3.20.2/cmake-3.20.2.tar.gz
tar -zxvf cmake-3.20.2.tar.gz
cd cmake-3.20.2
./bootstrap
make -j 8
sudo make install