GCC

The GNU Compiler Collection (GCC) is one of the most important pieces of free software ever written. It compiles C, C++, Fortran, Ada, Go, D, Objective-C, and Modula-2, with a Rust front end in development, for dozens of processor architectures. Most Linux distributions are built with it, the Linux kernel has historically required it, and embedded developers rely on GCC cross-compilers such as arm-none-eabi-gcc for microcontrollers.

Using GCC well means understanding what the gcc command actually does — it is a driver that runs a preprocessor, compiler, assembler, and linker — and knowing which flags control standards, warnings, optimization, debugging, and security hardening.

TL;DR

Quick Example

Watching the four stages the driver normally runs for you:

A hardened, optimized release build of a C++ service:

-g in release builds keeps debug information available (often split into separate files) for crash analysis without affecting optimization.

Core Concepts

The Driver and Toolchain

gcc -v prints every command the driver runs, which is invaluable when debugging include paths, library search paths, or linker errors. The C++ runtime is libstdc++; g++ links it automatically.

Language Standards and Dialects

GCC defaults to a GNU dialect of a recent standard — recent releases default to gnu23 for C and gnu++17 for C++. Specify the standard explicitly so builds do not change when the compiler is upgraded. GNU dialects enable extensions; strict ISO modes (-std=c17, -std=c++20) with -Wpedantic help portability.

Warnings and Analysis

Optimization Levels

-march=native tunes for the build machine's CPU and can produce binaries that crash on older CPUs — use an explicit baseline such as -march=x86-64-v2 for distributed binaries.

LTO and PGO

Link-time optimization (-flto) optimizes across translation units at link time. Profile-guided optimization builds with -fprofile-generate, runs representative workloads to collect profiles, and rebuilds with -fprofile-use, often giving significant speedups for branch-heavy code.

Hardening Release Builds

Compiler and linker options can make many memory-safety bugs harder to exploit:

Many distributions enable some of these by default. The OpenSSF compiler hardening guide maintains recommended sets.

Cross-Compilation and Toolchains

A GCC cross-compiler is built for a specific target triple — aarch64-linux-gnu, arm-none-eabi, riscv64-linux-gnu — and comes with matching binutils and a C library (glibc, musl, or newlib for bare metal). Embedded projects use vendor or Arm GNU Toolchain releases; Linux cross builds often use distribution packages, crosstool-NG, or container images. See Embedded C.

Choose and pin a toolchain version per project — through container images, toolchain files, or package version locks — because new GCC releases add warnings, change defaults, and occasionally expose latent undefined behavior.

GCC Compared With Clang

See Clang and LLVM.

Best Practices

Be Explicit About Standards and Targets

Set -std=, the target architecture baseline, and optimization level in the build system, not in individual developers' environments.

Build With Warnings as Errors in CI

Let developers see warnings locally and fail CI on them, so warning counts never grow unnoticed.

Keep Debug Information for Releases

Build with -g, strip binaries for deployment, and keep the debug files to symbolize crash dumps.

Test With Sanitizers

GCC supports -fsanitize=address,undefined too. Run tests with sanitizers in a dedicated CI job.

Common Mistakes

Relying on the Default Standard

-march=native in Distributed Binaries

Library Order on the Link Line

FAQ

What does GCC stand for?

The GNU Compiler Collection. It began as the GNU C Compiler and grew to support many languages and targets.

What is the difference between gcc and g++?

Both are drivers for the same compiler collection. g++ treats source files as C++ by default and links the C++ standard library automatically; gcc treats .c files as C and does not link libstdc++.

Which optimization level should I use?

-O2 for most release builds, -Og or -O0 for debugging, and -Os for size-constrained targets. Use -O3 only after measuring that it helps your workload.

How do I cross-compile with GCC?

Install or build a GCC toolchain for the target triple, such as aarch64-linux-gnu-gcc, with a matching sysroot or C library, and point your build system at it through a toolchain file.

Should I use GCC or Clang?

Use the compiler your platform and dependencies expect, and consider building with both in CI. GCC supports more languages and is standard on Linux; Clang offers a richer tooling ecosystem.

Related Topics

References