As part of the Software Portability & Optimization course, we will learn how to contribute and write compiler optimizations in the form of passes. For this lab, I will simply install and build the source code, on two different machines x86
& aarch64
.
Building the GCC Source Code
Installing the Source from Official GCC git
I followed the official instructions to download the GCC compiler source code, through the git repo. I repeated all these steps twice, for each machine. The following command installed the repo into the default gcc folder, in my home directory: ~/gcc
.
git clone git://gcc.gnu.org/git/gcc.git
Forking & Git Backups
Since neither machine is backed up, I wanted to make sure my work, speficially any changes I make to the source, is saved. To do this, I forked the mirror git repo, then generated and added ssh keys from each server – to my github settings.
# Generate key
ssh-keygen -t ed25519 -C "your-email@example.com"
# Check that the keys work to connect
ssh -T git@github.com
Then, inside the /gcc
directory, I need to change the “remote” git target – I do not want to push any of my changes to the official repo.
# Set git remote to my forked branch
>> git remote set-url origin git@github.com:emilyfagin/gcc.git
# Check the set git remote
>> git remote -v
origin git@github.com:emilyfagin/gcc.git (fetch)
origin git@github.com:emilyfagin/gcc.git (push)
Now, I need to create my new branch – I will create 2 branches, one for the x86
machine, and another for aarch64
. Keeping them separate can help avoid conflicts such as machine specific configurations or optimizations, and it allows me to backup different work from each machine.
# x86: create, checkout to the branch, and push it to remote
git checkout -b x86
git push origin x86
# aarch64: create, checkout to the branch, and push it to remote
git checkout -b aarch64
git push origin aarch64
Configuring the Build
Then, I configured my build directory, to be separate from the source directory, for good practice:
mkdir ~/gcc-build-001
cd ~/gcc-build-001
~/gcc/configure --prefix=$HOME/gcc-test-001 --enable-languages=c,c++
When the process was done, I was excited to continue and build the source. However, the output from the config process spat out something strange, which caused some errors in the build:
conftest.c:10:10: fatal error: isl/schedule.h: No such file or directory
10 | #include <isl/schedule.h>
| ^~~~~~~~~~~~~~~~
configure:9445: result: required isl version is 0.15 or later
Troubleshooting: required isl
dependency
After I noticed there was a problem, i searched everywhere in the web, for a solution on how to properly install this dependency. I tried running sudo dnf isl-devel
but didn’t have enough permissions, which indicated that this wasn’t the right move. Eventually I stumbled upon the answer – which was right there, in front of me – on the official GCC installing guide:
cd ~/gcc
# This script downloads the support libraries - dependencies - for me
./contrib/download_prerequisites
After this, I re-ran my build configuration, and inspected the output – it was good to go!
Performing the Build
Before performing the build, I started a screen
process, which ensures that if my ssh
connection is interrupted, my build will not be compramised.
screen -RaD
Now, I am ready to start my build. This could take anywhere from 20 minutes, to multiple hours, depending on the resources available at the time (how many people are using the server), configurations, the gcc version and machine version. To log the time it takes for the build, I used the time
& tee
command. I also used -j 24
to specify the use of 24 cores in the build process, to speed it up. Without specifying the jobs, it would be a single process, and can take forever.
# the brackets "(...)" ensure that time gets logged as well
(time make -j 24) |& tee build.log
Installing the Build
Now that the build process finished, and the time is recorded, I am ready to move on to installing the build, in the directory I specified during my configuration stage. Specifying the /gcc-test-001
directory as the target for the build install, ensures that the system’s gcc compiler is uneffected – the goal is not to override any system files, but experiement with compiling the always-changing gcc source code. Since this was already configured earlier, all I have to do is run:
make install
Testing the Build
To test that the newly build compiler works as expected, I can run the following command, which will perform tests to see if the compiler can successfully build a C program:
make -k check
There were a few warnings and minor errors that seemed to show up, but overall the process exited with a good status, and the program seemed to compile.
If I wanted to set the installed build as the default compiler for my environment, I can set the PATH
to include the bin
directory, from the installation folder:
PATH=$HOME/gcc-test-001:$PATH
Installed Compiler vs. System’s Compiler
To prove that the newly installed compiler is different from the system’s, I will check the system-wide version, and then the version inside the installation directory:
# check system version
>> gcc --version
gcc (GCC) 14.2.1 20240912 (Red Hat 14.2.1-3)
# check installed version
>> ~/gcc-test-001/bin/gcc --version
gcc (GCC) 15.0.1 20250306 (experimental)
Current Development Version
To check if the compiled version is the same as the current developmental version, I checked the git log inside the gcc directory, to check the date of the latest commit on my branch.
>> git log -1
commit d6d7da92fb598c50d25332011bffe6b6515c9669 (HEAD -> x86,
origin/master, origin/x86, origin/HEAD)
Author: Alex Coplan <alex.coplan@arm.com>
Date: Wed Mar 5 15:45:09 2025 +0000
pair-fusion: Add singleton move_range asserts [PR114492]
...
I also checked the release timeline, to compare with the versions I compiled. Looks like the latest released version is the 14.2
, which compared to my experimental 15.0
– is way earlier.
To ease the process, and improve future sessions, I permanently added the path variables, using .bashrc
file.
# .bashrc
...
# Include locally installed autogen library
export LD_LIBRARY_PATH="$HOME/usr/lib64"
# Prioritize the new gcc build as default (gcc commands)
export PATH="$HOME/gcc-test-001/bin:$PATH:$HOME/usr/bin"
...
Compiling hello.c
To test my compiler, I created a test C
file:
// hello.c
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
And attempted to compile and execute it:
>> which gcc
~/gcc-test-001/bin/gcc
>> gcc hello.c -o hello
>> ./hello
Hello, World!
And of course, it worked! Now, lets see how long it took for each server to run.
Build Times
x86_64 | aarch64 | |
First build | real 49m11.731s user 449m53.994s sys 21m25.377s | real 111m8.973s user 1077m10.087s sys 35m6.352s |
Null build | real 0m16.209s user 0m13.789s sys 0m12.070s | |
Small-Change Build touch ~/gcc/gcc/passes.cc ) | real 0m52.803s user 1m13.327s sys 0m21.475s |
Leave a Reply