DEV Community

Asuzu Kosisochukwu
Asuzu Kosisochukwu

Posted on

Operating System Development Series Part 1: Building a GCC cross compiler for i386 target on an M1 MacBook

A cross compiler is an important tool when building an operating system as it allows you to write code for a target system different from your host/development system. In this case I am building an operating system for an x86 architecture based device, particularly the i386 hardware which is an intel 8086 chip, from my host machine which is an M1 MacBook, the new M1 chips are ARM based which can introduce some challenges when building an operating system for a chip using a different architecture. This blog post highlights the steps I took to build the cross complier I will be using in developing the operating system.

Compilers are used to convert high level code into executable binaries on your target operating system. The compiler loads header files and dependencies of the operating system it is being compiled on. This is an issue for operating system development because we don’t want to have dependencies of our development operating system when building our own operating system as this will lead to errors.

Steps to building the cross compiler:

Building a gcc cross compiler is actually quite simple, first you need to create a folder for handling your OS development.

In this case lets name this file OSDev

mkdir OSDev
Enter fullscreen mode Exit fullscreen mode

This folder is where we will be keeping or Operating system development related code and tools. This helps simply our development and avoids conflicts as the compilers and tools installed might conflict with your current development system.

It is advisable to keep this OSDev folder where you keep your other software development tools, code or packages. In my case i kept it in my /Developer folder

There are two main components we are install which are:

  • binutils
  • gcc

The binutils are used to store the utilities your program will be able to use when it is compiled from your cross compiler, since it will not have access to your OS platform libraries.

GCC is the actual cross compiler that will be used for compiling your OS code.

# Move into the OSDev directory because this is where all your os development tools will be
cd OSDev

Enter fullscreen mode Exit fullscreen mode

Next we will have to download the code for GCC and binutils. The easiest way to do this is by downloading the code through the mirrors of these projects.

GETTING READY

Before we start we have to ensure that some path parameters are exported to the shell so we can reuse it as we are building our compiler

export PREFIX="$HOME/Developer/OSDev/opt/cross"
export TARGET=i686-elf
export PATH="$PREFIX/bin:$PATH"
Enter fullscreen mode Exit fullscreen mode

The ‘PREFIX’ defines where we want our cross compiler and its dependencies to be located, while ‘TARGET’ defines what type of processor we are building for.

BINUTILS

You will go to the mirrors of the projects and download the .tar.gz compressed files. It is advised to download the latest version available. The link to the mirror is

Index of /gnu/binutils

When you download the compressed binutils code, extract it an move the code to the OSDev folder

cd OSDev
ls
binutils-2.39/
Enter fullscreen mode Exit fullscreen mode

In my case the version of binutils is 2.39, this folder will be only folder in my OSDev folder at this point in time. You can dispose the compressed file you extracted from if you wish.

Now lets build the bitutils for our target platform. First we will create a build-binutils folder which we will use for build the binaries. The build-binutils should be created in the OSDev directory.

cd OSDev
mkdir build-binutils
cd build-binutils

../binutils-2.39/configure --target=$TARGET --prefix="$PREFIX" --with-sysroot --disable-nls --disable-werror
make
make install 
Enter fullscreen mode Exit fullscreen mode

This will build the binutils for the target platform and store it in the folder you defined as your ‘PREFIX’.

Running this commands will create an opt folder within your OSDev folder, and then a cross folder within opt

cd OSdev
ls
build-binutils/ binutils-2.39/ opt/
cd opt
ls
cross/
cd cross
ls
Lists a bunch of libraries and binaries that are now usable in you cross compiler
Enter fullscreen mode Exit fullscreen mode

GCC

Now we will download the source code of the gcc compiler just as we did with the binutils. We will download the compressed .tar.gz file and extract it into our OSDev folder. We will download this from the mirror which can be found here

https://ftp.gnu.org/gnu/gcc/

When you download the compressed gcc file, extract it and move the resulting folder into your OSDev folder

cd OSDev
ls
build-binutils/ binutils-2.39/ opt/ gcc-12.2.0/
cd gcc-12.2.0

# This will install all the required dependencies such as mpc, mpfr and gmp
./contrib/download_prerequisites
Enter fullscreen mode Exit fullscreen mode

In this situation we are using the version 12.2.0 of the gcc compiler.

Now lets build the gcc compiler the same way we built the binutils.

cd OSDev

# The $PREFIX/bin dir _must_ be in the PATH. We did that above.
which -- $TARGET-as || echo $TARGET-as is not in the PATH

mkdir build-gcc
cd build-gcc
../gcc-12.2.0/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --enable-languages=c,c++ --without-headers
make all-gcc
make all-target-libgcc
make install-gcc
make install-target-libgcc
Enter fullscreen mode Exit fullscreen mode

Congratulations! we have successfully built our compiler. The compiler is located here

OSDev/opt/cross/bin/i686-elf-gcc
Enter fullscreen mode Exit fullscreen mode

Test the cross compiler by checking the version

OSDev/opt/cross/bin/i686-elf-gcc --version
Enter fullscreen mode Exit fullscreen mode

Now our cross compiler is functioning properly we want to export the path so we can call the compiler from anywhere in our terminal

export PATH="full-path-to-folder/Developer/OSDev/opt/cross/bin:$PATH"
Enter fullscreen mode Exit fullscreen mode

This will enable us to call our compiler anywhere in our terminal as such

i686-elf-gcc --version
Enter fullscreen mode Exit fullscreen mode

This is temporary and if we close the terminal we will not be able to do this unless we re export it. To permanently export the path we need to add the export command the .profile file for the terminal. In my case i use zsh, there for i will have to edit the .zshrc file as such

nano .zshrc
Enter fullscreen mode Exit fullscreen mode

Then add this command to the end of the file

export PATH="full-path-to-folder/Developer/OSDev/opt/cross/bin:$PATH"
Enter fullscreen mode Exit fullscreen mode

Now you have a cross compiler and can use it to build our kernel.

Top comments (1)

Collapse
 
erikobryant profile image
erikobryant

Hey Asuzu,
My name is Erik O'Bryant and I'm assembling a team of developers to make an AI powered operating system. An OS like this would use AI to interpret and execute commands from its user, giving the user limitless control over their computers without having to be skilled in computer science. You seem to know a lot about building operating systems and so I was wondering if you'd want to join my team and help me develop this new 'intelligent operating system'. Let me know if you're interested (my email is erockthefrog@gmail.com).