Documentation

August 10, 2026 ยท View on GitHub

For the rules definitions, see defs.md.

For examples on how to use this repository, see the examples.

For how to bump the pinned toolchain tarballs, see updating-gcc-builds.md.

Getting Started

Basic Setup

Add the following to your WORKSPACE file:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "gcc_toolchain",
    # Add appropriate URL and SHA for your desired version
)

load("@gcc_toolchain//toolchain:repositories.bzl", "gcc_toolchain_dependencies")

gcc_toolchain_dependencies()

load("@gcc_toolchain//toolchain:defs.bzl", "gcc_register_toolchain", "ARCHS")

# Register toolchains for desired architectures
gcc_register_toolchain(
    name = "gcc_toolchain_x86_64",
    target_arch = ARCHS.x86_64,
)

gcc_register_toolchain(
    name = "gcc_toolchain_aarch64", 
    target_arch = ARCHS.aarch64,
)

gcc_register_toolchain(
    name = "gcc_toolchain_armv7",
    target_arch = ARCHS.armv7,
)

Selecting the GCC version

Every GCC version listed in AVAILABLE_GCC_VERSIONS is registered as a toolchain, and the @gcc_toolchain//toolchain:gcc_version flag picks which one resolves:

bazel build --@gcc_toolchain//toolchain:gcc_version=15.2.0 //...

Leaving the flag unset uses the gcc_version the toolchain was declared with, which defaults to the newest available version. Only the selected version is downloaded โ€” the others are declared but never fetched.

Because it is an ordinary build flag, it can be bound to a .bazelrc config:

build:gcc15 --@gcc_toolchain//toolchain:gcc_version=15.2.0

To change which version is used while the flag is unset, set it when declaring the toolchain. An explicit --@gcc_toolchain//toolchain:gcc_version still overrides it:

gcc_toolchains.toolchain(
    name = "gcc_toolchain_x86_64",
    gcc_version = "15.2.0",
    target_arch = "x86_64",
)

Each version also gets a config_setting, so build rules can branch on the selected compiler:

copts = select({
    "@gcc_toolchain//toolchain:gcc_version_12_5_0": ["-Wno-maybe-uninitialized"],
    "//conditions:default": [],
})

Note that these settings only match when the flag is set explicitly, so a select() over them needs a //conditions:default branch to cover the unset case.

Language Support

Pure C

For C-only code, no additional configuration is needed. The toolchain does not automatically link libstdc++, allowing for clean C compilation without C++ standard library dependencies.

C++

Full C++ support with modern standards (C++17 by default). The toolchain includes optimized include paths and flags for improved compilation performance. C++ programs that need the standard library should explicitly link it:

cc_binary(
    name = "my_cpp_program",
    srcs = ["main.cpp"],
    linkopts = ["-lstdc++"],  # Add when using C++ standard library.
)

Fortran

Complete Fortran support including:

  • Modern Fortran standards.
  • OpenMP support for parallel computing.
  • Integration with C/C++ code.

Example Fortran target with OpenMP:

fortran_library(
    name = "my_fortran_lib",
    srcs = ["source.f90"],
    copts = ["-fopenmp"],
    linkopts = ["-fopenmp"],
)

Advanced Configuration

Linking C++ Standard Library

The toolchain does not automatically link the C++ standard library, giving you full control over the linking behavior:

Dynamic linking (default for C++):

cc_binary(
    name = "my_program",
    srcs = ["main.cpp"],
    linkopts = ["-lstdc++"],
)

Static linking:

cc_binary(
    name = "my_program", 
    srcs = ["main.cpp"],
    linkopts = ["-l:libstdc++.a"],
)

No C++ standard library (for C code or custom implementations):

cc_binary(
    name = "my_c_program",
    srcs = ["main.c"],
    # No additional linkopts needed.
)

Remote Build Execution (RBE)

The toolchain has been optimized for remote execution with improved performance and macOS host compatibility. Add the following to your .bazelrc, replacing @<gcc_toolchain_workspace> with the name given to the http_archive when importing this repository:

build --host_platform=@<gcc_toolchain_workspace>//platforms:x86_64_linux_remote
build --extra_execution_platforms=@<gcc_toolchain_workspace>//platforms:x86_64_linux_remote
build --cpu k8 # Force host platforms other than Linux to use this configuration.
build --crosstool_top=@gcc_toolchain_x86_64//:_cc_toolchain # Allows the toolchain resolution for --cpu k8.
build --strategy=remote
build --genrule_strategy=remote
build --spawn_strategy=remote

Linking with lld

By default the toolchain links with the GNU BFD linker (ld). The toolchain also ships LLVM's lld, which you can opt into through the linker-lld feature. lld is generally faster than BFD and is a drop-in replacement for most use cases.

Enable it for an individual target with the features attribute:

cc_binary(
    name = "my_program",
    srcs = ["main.c"],
    features = ["linker-lld"],
)

Or enable it for an entire build. Add the following to your .bazelrc:

build:lld --features linker-lld

Then build with:

bazel build --config lld //<your_binary>

Running sanitizers

If you want to run automated tests with the sanitizers enabled, see how we do testing under //tests/sanitizers, and how we call them from CI.

For running the binaries with the sanitizers enabled, check the following topics.

Address Sanitizer (asan)

Add the following to your .bazelrc:

build:asan --features asan
build:asan --strip never
build:asan --action_env ASAN_OPTIONS=detect_leaks=0:color=always

Then run:

bazel run --config asan //<your_binary>

Leak Sanitizer (lsan)

Add the following to your .bazelrc:

build:lsan --features lsan
build:lsan --strip never
build:lsan --action_env LSAN_OPTIONS=verbosity=1:log_threads=1:report_objects=1

Then run:

bazel run --config lsan //<your_binary>

Thread Sanitizer (tsan)

Add the following to your .bazelrc:

build:tsan --features tsan
build:tsan --strip never
build:tsan --action_env TSAN_OPTIONS=halt_on_error=1:second_deadlock_stack=1

Then run:

bazel run --config tsan //<your_binary>

Undefined Behaviour Sanitizer (ubsan)

Add the following to your .bazelrc:

build:ubsan --features ubsan
build:ubsan --strip never
build:ubsan --action_env UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1

Then run:

bazel run --config ubsan //<your_binary>

Troubleshooting

Getting Help

  • Check the examples for working configurations.
  • Open an issue on GitHub for persistent problems.