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
gccandg++are drivers: they run the preprocessor, compiler (cc1/cc1plus), assembler (as), and linker (ld).- Choose the language standard explicitly:
-std=c17,-std=c++20, or the GNU dialects such as-std=gnu23. - Start from
-Wall -Wextra, add targeted warnings, and try-fanalyzerfor C. - Optimize with
-O2for most releases,-Ogfor debugging, and measure before using-O3or-march=native. - Harden release builds with
_FORTIFY_SOURCE, stack protection, PIE, and RELRO. - Cross-compilers are separate GCC builds for each target triple, such as
aarch64-linux-gnu-gcc.
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
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
- Clang — The LLVM-based alternative
- LLVM — Compiler infrastructure
- C — Systems programming in C
- C++ — Modern C++
- Embedded C — Cross-compiling for microcontrollers
- CMake — Toolchain files and portable builds