Last active
January 13, 2026 23:51
-
-
Save harrisonturton/fecda22244585cb1ca8216d5a4975e1d to your computer and use it in GitHub Desktop.
Bazel cc toolchain based on the embedded Arm GNU Toolchain
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| load("//toolchains/arm_none_eabi:cc_toolchain_config.bzl", "cc_toolchain_config") | |
| filegroup( | |
| name = "empty", | |
| srcs = [], | |
| ) | |
| filegroup( | |
| name = "compiler_files", | |
| srcs = [ | |
| "@darwin_arm64_gcc_arm_none_eabi//:arm_none_eabi", | |
| "@darwin_arm64_gcc_arm_none_eabi//:bin/arm-none-eabi-gcc", | |
| "@darwin_arm64_gcc_arm_none_eabi//:include", | |
| "@darwin_arm64_gcc_arm_none_eabi//:lib", | |
| "@darwin_arm64_gcc_arm_none_eabi//:libexec", | |
| ], | |
| ) | |
| filegroup( | |
| name = "linker_files", | |
| srcs = [ | |
| "STM32F446RETX_FLASH.ld", | |
| "@darwin_arm64_gcc_arm_none_eabi//:arm_none_eabi", | |
| "@darwin_arm64_gcc_arm_none_eabi//:bin/arm-none-eabi-gcc", | |
| "@darwin_arm64_gcc_arm_none_eabi//:lib", | |
| ], | |
| ) | |
| cc_toolchain_config( | |
| name = "cc_toolchain_config", | |
| compiler = "@darwin_arm64_gcc_arm_none_eabi//:bin/arm-none-eabi-gcc", | |
| linker_script = "STM32F446RETX_FLASH.ld", | |
| strip = "@darwin_arm64_gcc_arm_none_eabi//:bin/arm-none-eabi-strip", | |
| toolchain_identifier = "macos_arm64_toolchain", | |
| ) | |
| cc_toolchain( | |
| name = "cc_toolchain", | |
| all_files = ":empty", | |
| ar_files = ":empty", | |
| as_files = ":compiler_files", | |
| compiler_files = ":compiler_files", | |
| dwp_files = ":empty", | |
| linker_files = ":linker_files", | |
| objcopy_files = ":empty", | |
| strip_files = ":empty", | |
| supports_param_files = False, | |
| toolchain_config = ":cc_toolchain_config", | |
| toolchain_identifier = "macos_arm64_toolchain", | |
| ) | |
| toolchain( | |
| name = "arm_none_eabi", | |
| toolchain = ":cc_toolchain", | |
| toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", | |
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "cc toolchain configuration" | |
| load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES", "ACTION_NAME_GROUPS") | |
| load( | |
| "@rules_cc//cc:cc_toolchain_config_lib.bzl", | |
| "action_config", | |
| "feature", | |
| "flag_group", | |
| "flag_set", | |
| "tool", | |
| "variable_with_value", | |
| ) | |
| load("@rules_cc//cc/common:cc_common.bzl", "cc_common") | |
| load("@rules_cc//cc/toolchains:cc_toolchain_config_info.bzl", "CcToolchainConfigInfo") | |
| def _disabled_legacy_features(): | |
| """Bazel implicitly patches a bunch of legacy features unless you override them yourself""" | |
| legacy_features = [ | |
| "legacy_compile_flags", | |
| "default_compile_flags", | |
| "dependency_file", | |
| "pic", | |
| "per_object_debug_info", | |
| "preprocessor_defines", | |
| "includes", | |
| "include_paths", | |
| "fdo_instrument", | |
| "fdo_optimize", | |
| "cs_fdo_instrument", | |
| "cs_fdo_optimize", | |
| "fdo_prefetch_hints", | |
| "autofdo", | |
| "build_interface_libraries", | |
| "dynamic_library_linker_tool", | |
| "shared_flag", | |
| "linkstamps", | |
| "output_execpath_flags", | |
| "runtime_library_search_directories", | |
| "library_search_directories", | |
| "archiver_flags", | |
| "libraries_to_link", | |
| "force_pic_flags", | |
| "user_link_flags", | |
| "legacy_link_flags", | |
| "static_libgcc", | |
| "fission_support", | |
| "strip_debug_symbols", | |
| "coverage", | |
| "llvm_coverage_map_format", | |
| "gcc_coverage_map_format", | |
| "fully_static_link", | |
| "user_compile_flags", | |
| "sysroot", | |
| "unfiltered_compile_flags", | |
| "linker_param_file", | |
| "compiler_input_flags", | |
| "compiler_output_flags", | |
| ] | |
| return [ | |
| feature( | |
| name = "no_legacy_features", | |
| enabled = True, | |
| ), | |
| ] + [ | |
| feature( | |
| name = name, | |
| enabled = False, | |
| ) | |
| for name in legacy_features | |
| ] | |
| def _action_configs(ctx): | |
| """Configuration for actions used by this toolchain.""" | |
| return [ | |
| action_config( | |
| action_name = ACTION_NAMES.c_compile, | |
| enabled = True, | |
| tools = [tool(tool = ctx.executable.compiler)], | |
| ), | |
| action_config( | |
| action_name = ACTION_NAMES.assemble, | |
| enabled = True, | |
| tools = [tool(tool = ctx.executable.compiler)], | |
| ), | |
| action_config( | |
| action_name = ACTION_NAMES.cpp_link_executable, | |
| enabled = True, | |
| tools = [tool(tool = ctx.executable.compiler)], | |
| ), | |
| # Required by Bazel legacy features | |
| action_config( | |
| action_name = ACTION_NAMES.strip, | |
| enabled = True, | |
| tools = [tool(tool = ctx.executable.strip)], | |
| ), | |
| ] | |
| def _features(ctx): | |
| "Commandline flags for each compilation stage, using tools from the action configs" | |
| compiler_include_flags = feature( | |
| name = "compiler_include_flags", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_compile_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = [ | |
| "-no-canonical-prefixes", | |
| "-fno-canonical-system-headers", | |
| ], | |
| ), | |
| flag_group( | |
| flags = ["-iquote", "%{quote_include_paths}"], | |
| iterate_over = "quote_include_paths", | |
| ), | |
| flag_group( | |
| flags = ["-I%{include_paths}"], | |
| iterate_over = "include_paths", | |
| ), | |
| flag_group( | |
| flags = ["-isystem", "%{system_include_paths}"], | |
| iterate_over = "system_include_paths", | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| compiler_input_flags = feature( | |
| name = "compiler_inputs", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_compile_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = [ | |
| "-ffunction-sections", | |
| "-fdata-sections", | |
| "-fstack-usage", | |
| "-std=gnu11", | |
| "-mcpu=cortex-m4", | |
| "-mthumb", | |
| "--specs=nano.specs", | |
| "-mfpu=fpv4-sp-d16", | |
| "-mfloat-abi=hard", | |
| "-Wa,-mimplicit-it=thumb", | |
| ], | |
| ), | |
| flag_group( | |
| flags = ["-c", "%{source_file}"], | |
| expand_if_available = "source_file", | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| compiler_output_flags = feature( | |
| name = "compiler_outputs", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_compile_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = ["-S"], | |
| expand_if_available = "output_assembly_file", | |
| ), | |
| flag_group( | |
| flags = ["-E"], | |
| expand_if_available = "output_preprocess_file", | |
| ), | |
| flag_group( | |
| flags = ["-o", "%{output_file}"], | |
| expand_if_available = "output_file", | |
| ), | |
| # Bazel requires dependency files to be outputted during | |
| # compilation, these are implicitly read and used to declare | |
| # per-file dependency edges. This is undocumented. | |
| flag_group( | |
| flags = ["-MD", "-MF", "%{dependency_file}"], | |
| expand_if_available = "dependency_file", | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| linker_input_flags = feature( | |
| name = "linker_inputs", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_link_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = [ | |
| "-mcpu=cortex-m4", | |
| "-mthumb", | |
| "--specs=nosys.specs", | |
| "-mfpu=fpv4-sp-d16", | |
| "-mfloat-abi=hard", | |
| "-static", | |
| "--specs=nano.specs", | |
| "-Wl,--gc-sections", | |
| ], | |
| ), | |
| flag_group( | |
| iterate_over = "libraries_to_link", | |
| flag_groups = [ | |
| # User inputs | |
| flag_group( | |
| flags = ["%{linker_input_files}"], | |
| iterate_over = "linker_input_files", | |
| expand_if_available = "linker_input_files", | |
| ), | |
| # Object files | |
| flag_group( | |
| flags = ["%{libraries_to_link.name}"], | |
| expand_if_equal = variable_with_value( | |
| name = "libraries_to_link.type", | |
| value = "object_file", | |
| ), | |
| ), | |
| # Static libraries | |
| flag_group( | |
| flags = ["-no-whole-archive"], | |
| expand_if_true = "libraries_to_link.is_whole_archive", | |
| expand_if_equal = variable_with_value( | |
| name = "libraries_to_link.type", | |
| value = "static_library", | |
| ), | |
| ), | |
| # Dynamic libraries | |
| flag_group( | |
| flags = ["-l%{libraries_to_link.name}"], | |
| expand_if_equal = variable_with_value( | |
| name = "libraries_to_link.type", | |
| value = "dynamic_library", | |
| ), | |
| ), | |
| ], | |
| expand_if_available = "libraries_to_link", | |
| ), | |
| flag_group( | |
| flags = [ | |
| "-Wl,--start-group", | |
| "-lc", | |
| "-lm", | |
| "-lstdc++", | |
| "-lsupc++", | |
| "-Wl,--end-group", | |
| ], | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| linker_output_flags = feature( | |
| name = "linker_output_flags", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_link_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = ["-o", "%{output_execpath}"], | |
| expand_if_available = "output_execpath", | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| linker_script_flags = feature( | |
| name = "linker_script_flags", | |
| enabled = True, | |
| flag_sets = [ | |
| flag_set( | |
| actions = ACTION_NAME_GROUPS.all_cc_link_actions, | |
| flag_groups = [ | |
| flag_group( | |
| flags = ["-T", ctx.file.linker_script.path], | |
| ), | |
| ], | |
| ), | |
| ], | |
| ) | |
| return [ | |
| compiler_include_flags, | |
| compiler_input_flags, | |
| compiler_output_flags, | |
| linker_input_flags, | |
| linker_output_flags, | |
| linker_script_flags, | |
| ] | |
| def _cc_toolchain_config_impl(ctx): | |
| return cc_common.create_cc_toolchain_config_info( | |
| ctx = ctx, | |
| toolchain_identifier = ctx.attr.toolchain_identifier, | |
| # These features use gcc flavoured flags, so it should be safe to | |
| # hardcode gcc given that this identifier is exposed via | |
| # `@bazel_tools//tools/cpp:compiler` and typically used to select | |
| # compiler-specific flags | |
| compiler = "gcc", | |
| features = _disabled_legacy_features() + _features(ctx), | |
| action_configs = _action_configs(ctx), | |
| ) | |
| cc_toolchain_config = rule( | |
| implementation = _cc_toolchain_config_impl, | |
| attrs = { | |
| "toolchain_identifier": attr.string( | |
| doc = "Identifier for the toolchain", | |
| mandatory = True, | |
| ), | |
| "compiler": attr.label( | |
| mandatory = True, | |
| doc = "Compiler binary", | |
| executable = True, | |
| allow_single_file = True, | |
| cfg = "exec", | |
| ), | |
| "linker_script": attr.label( | |
| mandatory = True, | |
| doc = "Linker script", | |
| allow_single_file = True, | |
| ), | |
| "strip": attr.label( | |
| mandatory = True, | |
| doc = "Strip binary", | |
| executable = True, | |
| allow_single_file = True, | |
| cfg = "exec", | |
| ), | |
| }, | |
| provides = [CcToolchainConfigInfo], | |
| fragments = ["cpp"], | |
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "ARM-provided GCC and newlib-based toolchain" | |
| http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") | |
| # The toolchain is provided from the downloads on this page: | |
| # | |
| # https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads | |
| # | |
| # Note that these download links will redirect to Azure Blob Storage links. In | |
| # order to get a stable URL that Bazel is happy with, we must resolve the | |
| # redirected link and use that here. | |
| http_archive( | |
| name = "darwin_arm64_gcc_arm_none_eabi", | |
| build_file = "//:third_party/gcc_arm_none_eabi/gcc_arm_none_eabi.BUILD", | |
| strip_prefix = "arm-gnu-toolchain-15.2.rel1-darwin-arm64-arm-none-eabi", | |
| # No integrity because the SHA256sum seems to change on every download. | |
| # Possibly an embedded timestamp somewhere? | |
| url = "https://armkeil.blob.core.windows.net/developer/files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-darwin-arm64-arm-none-eabi.tar.xz", | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment