Embedded Linux projects do not always build cleanly with the newest compiler installed on a workstation. A legacy BSP, an older kernel tree, a vendor SDK, or a cross-compilation support package may require an older GCC and G++ version. On Ubuntu, this usually means keeping several compiler versions installed at the same time and switching the default gcc and g++ commands only when a project needs it.
This guide explains how to install multiple GCC and G++ versions on Ubuntu and manage the active compiler with update-alternatives. The same method is useful when working on Linux SBC projects, old embedded SDKs, kernel modules, driver code, or BSP packages that were validated against a specific compiler version.
Before changing the default compiler on a production build machine, record the current compiler version and confirm which project actually needs the older toolchain. Changing /usr/bin/gcc affects any build process that calls gcc directly, so it should be done deliberately.
Check the currently installed GCC and G++ versions
Start by checking which compiler binaries already exist under /usr/bin.
ls -l /usr/bin/gcc*
ls -l /usr/bin/g++*
You can also check the active compiler versions directly:
gcc --version
g++ --version
On many Ubuntu systems, /usr/bin/gcc and /usr/bin/g++ are symbolic links. They may point directly to a versioned binary such as /usr/bin/gcc-11, or they may point through the alternatives system. The goal of the setup below is to let Ubuntu manage those links cleanly instead of editing symlinks by hand.
Install the GCC and G++ versions you need
Install the compiler versions required by your projects. For example, an older SDK may need GCC 4.8 or GCC 5, while the system may already have GCC 7 or a newer version.
sudo apt update
sudo apt install gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib
sudo apt install gcc-5 gcc-5-multilib g++-5 g++-5-multilib
sudo apt install gcc-7 gcc-7-multilib g++-7 g++-7-multilib
The exact package names depend on the Ubuntu release and enabled repositories. Very old compiler packages, such as GCC 4.8, may not be available in the default repositories of a modern Ubuntu release. In that case, consider using an older Ubuntu build container, a vendor-provided SDK image, or a dedicated virtual machine instead of forcing unsupported packages into a current system.
For embedded work, this is often safer. A BSP that was created for Ubuntu 16.04 or 18.04 may expect old build tools, old Python behavior, or old library versions, not only an older compiler.
Understand update-alternatives
Ubuntu uses update-alternatives to maintain symbolic links for commands where several compatible implementations may exist. The official Ubuntu manual describes it as a tool that maintains symbolic links determining default commands. You can read the Ubuntu manpage for update-alternatives for the full command reference.
For GCC management, gcc should be treated as the master command and g++ should be configured as a slave command. This keeps both compilers on the same version when you switch. Without the slave link, it is easy to accidentally use gcc-4.8 with g++-7, which can make build failures harder to understand.
Register GCC and G++ with update-alternatives
Use update-alternatives --install to register each compiler version. The priority value decides which version is selected automatically when the alternative group is in auto mode. A higher number means higher priority.
| Version | GCC path | G++ path | Example priority |
|---|---|---|---|
| GCC 4.8 | /usr/bin/gcc-4.8 | /usr/bin/g++-4.8 | 40 |
| GCC 5 | /usr/bin/gcc-5 | /usr/bin/g++-5 | 50 |
| GCC 7 | /usr/bin/gcc-7 | /usr/bin/g++-7 | 70 |
Register the compiler versions like this:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 \
--slave /usr/bin/g++ g++ /usr/bin/g++-4.8
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 50 \
--slave /usr/bin/g++ g++ /usr/bin/g++-5
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 \
--slave /usr/bin/g++ g++ /usr/bin/g++-7
The first path after --install is the generic link, /usr/bin/gcc. The second gcc is the alternatives group name. The third path is the real compiler binary. The number is the priority.
The --slave part connects /usr/bin/g++ to the same selection. When you select GCC 4.8, G++ 4.8 is selected as well. When you select GCC 7, G++ 7 follows.
Select the active GCC version
After registering the alternatives, run:
sudo update-alternatives --config gcc
Ubuntu will print a menu similar to this:
There are 3 choices for the alternative gcc (providing /usr/bin/gcc).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/gcc-7 70 auto mode
1 /usr/bin/gcc-4.8 40 manual mode
2 /usr/bin/gcc-5 50 manual mode
3 /usr/bin/gcc-7 70 manual mode
Press <enter> to keep the current choice[*], or type selection number:
To switch to GCC 4.8, type:
1
The system will then use /usr/bin/gcc-4.8 for the generic gcc command. Because g++ was configured as a slave link, /usr/bin/g++ should switch to /usr/bin/g++-4.8 at the same time.
If you want Ubuntu to return to automatic priority selection, use:
sudo update-alternatives --auto gcc
In auto mode, the compiler with the highest registered priority becomes the default. In the example above, GCC 7 has priority 70, so it will be selected automatically.
Verify the selected compiler
Always verify both C and C++ compilers after switching:
gcc -v
g++ -v
For a shorter check:
gcc --version
g++ --version
You can also inspect the symlinks:
ls -l /usr/bin/gcc /usr/bin/g++
ls -l /etc/alternatives/gcc /etc/alternatives/g++
If gcc and g++ show different major versions, review the alternatives registration. The usual cause is that g++ was not added as a slave link when the gcc alternative was installed.
Remove an alternative entry
If a compiler version should no longer be offered by update-alternatives, remove that alternative first:
sudo update-alternatives --remove gcc /usr/bin/gcc-4.8
Then remove the packages if they are no longer needed:
sudo apt remove gcc-4.8 gcc-4.8-multilib g++-4.8 g++-4.8-multilib
sudo apt autoremove
Do not remove compiler packages while an active project still depends on them. For long-lived embedded products, it is often better to keep a documented build environment, such as a VM or container, so the BSP can be rebuilt years later with the same compiler baseline.
Practical notes for embedded Linux builds
For BSP and driver support, switching the host compiler is only one part of the build environment. Kernel version, make version, libc headers, Python version, device tree tools, cross-toolchain path, and SDK scripts can all affect the result.
When a vendor SDK asks for an old GCC version, keep a short build note with:
- Ubuntu release
- GCC and G++ version
- Cross-compiler version, if used
- SDK or BSP version
- Required environment variables
- Build command
- Known patches or warnings
That record saves time when another engineer needs to reproduce the same firmware image later.
Summary
Ubuntu can keep several GCC and G++ versions installed at the same time. Use update-alternatives to register each version, set clear priorities, and keep gcc and g++ synchronized with a slave link. Use sudo update-alternatives --config gcc when a project needs a specific compiler, then verify the result with gcc -v and g++ -v.
For old embedded SDKs, avoid turning the main workstation into a fragile legacy environment. If the required compiler is too old for the current Ubuntu release, a dedicated VM or container is usually the cleaner engineering choice.
