Skip to content

Latest commit

 

History

History
320 lines (231 loc) · 7.96 KB

File metadata and controls

320 lines (231 loc) · 7.96 KB

Documentation

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.

Choosing the host architecture

target_arch names the architecture a toolchain produces code FOR. host_arch names the one its binaries RUN on, and defaults to whatever architecture Bazel itself is running on, so building natively on either x86_64 or aarch64 needs no configuration at all:

# On an x86_64 machine this is an x86_64-hosted cross toolchain; on an aarch64 machine it is a
# native one. Either way it targets aarch64.
gcc_toolchains.toolchain(
    name = "gcc_toolchain_aarch64",
    target_arch = "aarch64",
)

It drives exec_compatible_with on the generated toolchain(), so toolchain resolution picks the toolchain whose binaries the execution platform can actually run.

Set it explicitly only to fetch a toolchain for a host you are not on — for example to declare an aarch64-hosted toolchain from x86_64:

gcc_toolchains.toolchain(
    name = "gcc_toolchain_aarch64_host",
    host_arch = "aarch64",
    target_arch = "aarch64",
)

gcc-builds publishes aarch64-hosted archives from the 08072026 release on, which covers GCC 14.3.0 and newer. Asking for a version with no build for that host fails at fetch time, naming the hosts it does have. armv7 is a target only.

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.