How To Install Gcc In Ubuntu

How To Install Gcc In Ubuntu

Reading time1 min
#Linux#Programming#Development#GCC#Ubuntu#C++

Mastering GCC Installation in Ubuntu: Practical Engineer’s Guide

GCC is a core toolchain for C and C++ work under Linux, but too many environments are held together with assumptions like “the default package is enough.” Over time, this leads to build failures, misaligned CI/CD pipelines, or subtle ABI incompatibilities—especially on shared development hosts, container builds, or when reproducing legacy binaries.

Below: how to control GCC versions and their ancillary libraries on Ubuntu, get reliable switches between major releases, and mitigate common pain points encountered in real-world workflows.


Get Up and Running: No-Frills GCC Setup

Don’t just install gcc—install every essential build tool:

sudo apt update
sudo apt install build-essential

Aside from gcc and g++, this includes make, basic headers, and utility binaries needed for reliable C/C++ compilations.

Check installed runtime/version:

gcc --version

Sample output as seen in Ubuntu 22.04 environments:

gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

Note: Default Ubuntu LTS releases may lag; cross-check with apt-cache policy gcc to verify what’s pinned by the repo.


Managing Multiple GCC Versions

Modern CI requirements often mean juggling legacy code needing older compilers alongside bleeding-edge toolchains. Relying on a single system gcc is asking for trouble.

List all available versions (as of June 2024):

apt-cache search '^gcc-[0-9]$'

Expected output varies, but typically includes:

  • gcc-7
  • gcc-8
  • gcc-9
  • gcc-10
  • gcc-11
  • gcc-12

Install a specific release (e.g., gcc-10):

sudo apt install gcc-10 g++-10

Note: Always pair g++-X with its corresponding gcc-X to avoid header mismatch issues when switching.

Fast Compiler Switching: update-alternatives

Suppose your build script fails with “error: invalid conversion from ... in /usr/include/c++/X.Y/”. Common cause: the wrong major GCC version.

Register available versions:

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 110
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 120

Same for g++:

sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 110

Switch interactively:

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

Immediate change is effective—open a new shell or verify with:

gcc --version

Gotcha:
Some third-party scripts (notably in node-gyp or older CMake configurations) hardcode /usr/bin/gcc-X. Always verify the shebangs and paths when tracking odd build errors.


Dependency Pitfalls: Header and Library Synchronization

New developers hit this: “fatal error: bits/c++config.h: No such file or directory”

This almost always means the corresponding libstdc++ headers aren’t installed for that GCC version.

sudo apt install libstdc++-10-dev  # Replace 10 with version as needed

Or, for i386 builds on x86_64 hosts:

sudo apt install libc6-dev-i386

Check for dangling symlinks or wrong binaries:

ls -l /usr/bin/gcc*

Clean up or correct with update-alternatives if binaries mismatch or outdated versions remain.

Known issue:
Mixed Docker builds may layer distinct GCC toolchains, leading to unpredictable C++ ABI results and ‘undefined reference’ errors. Always hard-pin your base images, or manually install desired GCC across all build stages.


Compiler Flags: Basic but Vital

Hardware constraints and security best practices dictate flag choice.

Common optimization:

  • -O2: General performance boost, without introducing aggressive heuristics.
  • -O3: High-risk optimization; may break subtle code.

Typical hardening:

  • -fstack-protector-strong
  • -D_FORTIFY_SOURCE=2
  • -Werror=format-security

Real-world Makefile line:

CFLAGS=-O2 -Wall -Wextra -fstack-protector-strong -D_FORTIFY_SOURCE=2

Or plain compile:

gcc -O2 -fstack-protector-strong -D_FORTIFY_SOURCE=2 -o hello hello.c

Automate Switching: Shell Aliases & Scripting

Cycling GCC versions frequently? Add persistent aliases:

alias usegcc10='sudo update-alternatives --set gcc /usr/bin/gcc-10 && sudo update-alternatives --set g++ /usr/bin/g++-10'
alias usegcc12='sudo update-alternatives --set gcc /usr/bin/gcc-12 && sudo update-alternatives --set g++ /usr/bin/g++-12'

Drop these in ~/.bashrc or as project-specific shell scripts. Reduces tedious version pinning.


Building GCC From Source: When Packages Aren’t Enough

Sometimes, you require a GCC with custom patching, or simply a newer minor release:

Quick workflow:

  1. Download tarball from https://ftp.gnu.org/gnu/gcc/gcc-/
  2. Install prerequisites (sudo apt install libgmp-dev libmpfr-dev libmpc-dev flex bison)
  3. Extract tarball, then:
    ./configure --prefix=$HOME/gcc-custom --enable-languages=c,c++ --disable-multilib
    make -j$(nproc)
    make install
    
  4. Add $HOME/gcc-custom/bin to your $PATH.

Trade-off:
Source builds can take over an hour. Always isolate custom builds to a non-global prefix to avoid package manager conflicts.


Not-So-Obvious Tip

When targeting cross-distribution compatibility (e.g., Ubuntu 20.04 host but Ubuntu 22.04 containers), preferring a tool like ccache with architecture-specific symlinks can vastly improve build times on repeated recompiles, while avoiding subtle version collision due to shared object files.


Summary

A robust GCC setup in Ubuntu comes down to version pinning, correct alternatives configuration, and ensuring that headers/libs are always in sync. Automate version switches, always check the actual symlink targets, and—when necessary—don’t hesitate to build from source for critical requirements. Most build failures after system upgrades trace directly to missing or misaligned GCC/stdlibc++ libraries; pin them early, script for repeatability, and periodic audits reduce later surprises.