Support CXX configuration options in Bazel
diff --git a/bazel/config/BUILD.bazel b/bazel/config/BUILD.bazel index 96d96fd..9307b5e 100644 --- a/bazel/config/BUILD.bazel +++ b/bazel/config/BUILD.bazel
@@ -27,6 +27,24 @@ build_setting_default = "compile_time_choice", ) +# PICO_BAZEL_CONFIG: PICO_CXX_ENABLE_EXCEPTIONS, Enabled CXX exception handling, type=bool, default=0, group=pico_cxx_options +bool_flag( + name = "PICO_CXX_ENABLE_EXCEPTIONS", + build_setting_default = False, +) + +# PICO_BAZEL_CONFIG: PICO_CXX_ENABLE_RTTI, Enabled CXX rtti, type=bool, default=0, group=pico_cxx_options +bool_flag( + name = "PICO_CXX_ENABLE_RTTI", + build_setting_default = False, +) + +# PICO_BAZEL_CONFIG: PICO_CXX_ENABLE_CXA_ATEXIT, Enabled cxa-atexit, type=bool, default=0, group=pico_cxx_options +bool_flag( + name = "PICO_CXX_ENABLE_CXA_ATEXIT", + build_setting_default = False, +) + # This should always point to a cc_library that provides # a "pico_config_extra_headers.h". label_flag(
diff --git a/bazel/constraint/BUILD.bazel b/bazel/constraint/BUILD.bazel index 76fee88..837f7c8 100644 --- a/bazel/constraint/BUILD.bazel +++ b/bazel/constraint/BUILD.bazel
@@ -40,6 +40,21 @@ flag_values = {"//bazel/config:PICO_NO_GC_SECTIONS": "True"}, ) +config_setting( + name = "pico_cxx_enable_exceptions_enabled", + flag_values = {"//bazel/config:PICO_CXX_ENABLE_EXCEPTIONS": "True"}, +) + +config_setting( + name = "pico_cxx_enable_rtti_enabled", + flag_values = {"//bazel/config:PICO_CXX_ENABLE_RTTI": "True"}, +) + +config_setting( + name = "pico_cxx_enable_cxa_atexit_enabled", + flag_values = {"//bazel/config:PICO_CXX_ENABLE_RTTI": "True"}, +) + # This constraint setting guides Bazel's build file evaluation differences # across different stdio configurations (e.g. stdio_usb needs TinyUSB). constraint_setting(
diff --git a/bazel/toolchain/BUILD.bazel b/bazel/toolchain/BUILD.bazel index b66f552..4c07e30 100644 --- a/bazel/toolchain/BUILD.bazel +++ b/bazel/toolchain/BUILD.bazel
@@ -2,6 +2,7 @@ load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list") load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature") load("@rules_cc//cc/toolchains:toolchain.bzl", "cc_toolchain") +load("configurable_feature.bzl", "configurable_toolchain_feature") cc_args( name = "cortex-m0", @@ -44,37 +45,35 @@ ], ) -cc_args( - name = "gc_sections_compile_args", - actions = ["@rules_cc//cc/toolchains/actions:compile_actions"], - args = [ +configurable_toolchain_feature( + name = "gc_sections", + copts = [ "-ffunction-sections", "-fdata-sections", ], + linkopts = ["-Wl,--gc-sections"], + disable_if = "//bazel/constraint:pico_no_gc_sections_enabled", ) -cc_args( - name = "gc_sections_link_args", - actions = ["@rules_cc//cc/toolchains/actions:link_actions"], - args = ["-Wl,--gc-sections"], -) - -cc_args_list( - name = "gc_sections_args", - args = [ - ":gc_sections_compile_args", - ":gc_sections_link_args" +configurable_toolchain_feature( + name = "cxx_no_exceptions", + cxxopts = [ + "-fno-exceptions", + "-fno-unwind-tables", ], + disable_if = "//bazel/constraint:pico_cxx_enable_exceptions_enabled", ) -cc_feature( - name = "gc_sections", - feature_name = "gc_sections", - args = [":gc_sections_args"], - enabled = select({ - "//bazel/constraint:pico_no_gc_sections_enabled": False, - "//conditions:default": True, - }), +configurable_toolchain_feature( + name = "cxx_no_rtti", + cxxopts = ["-fno-rtti"], + disable_if = "//bazel/constraint:pico_cxx_enable_rtti_enabled", +) + +configurable_toolchain_feature( + name = "cxx_no_cxa_atexit", + cxxopts = ["-fno-use-cxa-atexit"], + disable_if = "//bazel/constraint:pico_cxx_enable_cxa_atexit_enabled", ) # TODO: Make this shim unnecessary. @@ -168,6 +167,9 @@ "@pico-sdk//bazel/toolchain:legacy_features", "@pico-sdk//bazel/toolchain:override_debug", "@pico-sdk//bazel/toolchain:gc_sections", + "@pico-sdk//bazel/toolchain:cxx_no_exceptions", + "@pico-sdk//bazel/toolchain:cxx_no_rtti", + "@pico-sdk//bazel/toolchain:cxx_no_cxa_atexit", ], ) for host_os, host_cpu in HOSTS]
diff --git a/bazel/toolchain/configurable_feature.bzl b/bazel/toolchain/configurable_feature.bzl new file mode 100644 index 0000000..19e59a5 --- /dev/null +++ b/bazel/toolchain/configurable_feature.bzl
@@ -0,0 +1,54 @@ +load("@rules_cc//cc/toolchains:args.bzl", "cc_args") +load("@rules_cc//cc/toolchains:args_list.bzl", "cc_args_list") +load("@rules_cc//cc/toolchains:feature.bzl", "cc_feature") + +def configurable_toolchain_feature(name, copts = [], cxxopts = [], linkopts = [], enable_if=None, disable_if=None): + if enable_if != None and disable_if != None: + fail('Cannot specify both enable_if and disable_if') + if enable_if == None and disable_if == None: + fail('Must specify at least one of enable_if and disable_if') + if enable_if == None: + enable_if = "//conditions:default" + if disable_if == None: + disable_if = "//conditions:default" + + all_args = [] + + if copts: + cc_args( + name = name + "_cc_args", + actions = ["@rules_cc//cc/toolchains/actions:compile_actions"], + args = copts, + ) + all_args.append(name + "_cc_args") + + if cxxopts: + cc_args( + name = name + "_cxx_args", + actions = ["@rules_cc//cc/toolchains/actions:cpp_compile_actions"], + args = cxxopts, + ) + all_args.append(name + "_cxx_args") + + if linkopts: + cc_args( + name = name + "_link_args", + actions = ["@rules_cc//cc/toolchains/actions:link_actions"], + args = linkopts, + ) + all_args.append(name + "_link_args") + + cc_args_list( + name = name + "_args", + args = all_args, + ) + + cc_feature( + name = name, + feature_name = name, + args = [":{}_args".format(name)], + enabled = select({ + disable_if: False, + enable_if: True, + }), + )
diff --git a/bazel/util/sdk_define.bzl b/bazel/util/sdk_define.bzl new file mode 100644 index 0000000..72ecdfe --- /dev/null +++ b/bazel/util/sdk_define.bzl
@@ -0,0 +1,25 @@ +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +def _pico_sdk_define_impl(ctx): + val = ctx.attr.from_flag[BuildSettingInfo].value + + if type(val) == "string": + # Strings need quotes. + val = "\"{}\"".format(val) + elif type(val) == "bool": + # Convert bools to 0 or 1. + val = 1 if val else 0 + cc_ctx = cc_common.create_compilation_context( + defines = depset( + ["{}={}".format(ctx.attr.define_name, val)] + ) + ) + return [CcInfo(compilation_context = cc_ctx)] + +pico_sdk_define = rule( + implementation = _pico_sdk_define_impl, + attrs = { + "define_name": attr.string(mandatory = True), + "from_flag": attr.label(mandatory = True), + } +)
diff --git a/src/rp2_common/pico_standard_link/BUILD.bazel b/src/rp2_common/pico_standard_link/BUILD.bazel index 46b94d9..0de9005 100644 --- a/src/rp2_common/pico_standard_link/BUILD.bazel +++ b/src/rp2_common/pico_standard_link/BUILD.bazel
@@ -1,11 +1,20 @@ +load("//bazel/util:sdk_define.bzl", "pico_sdk_define") + package(default_visibility = ["//visibility:public"]) +# PICO_BUILD_DEFINE: PICO_CXX_ENABLE_EXCEPTIONS, value of CMake var PICO_CXX_ENABLE_EXCEPTIONS, type=string, default=0, group=pico_cxx_options +pico_sdk_define( + name = "PICO_CXX_ENABLE_EXCEPTIONS", + define_name = "PICO_CXX_ENABLE_EXCEPTIONS", + from_flag = "//bazel/config:PICO_CXX_ENABLE_EXCEPTIONS", +) + cc_library( name = "pico_standard_link", srcs = [ "binary_info.c", "crt0.S", - # "new_delete.cpp", # TODO: Doesn't build yet? + "new_delete.cpp", ], # TODO: Make this configurable. linkopts = [ @@ -16,6 +25,7 @@ "//conditions:default": ["@platforms//:incompatible"], }), deps = [ + ":PICO_CXX_ENABLE_EXCEPTIONS", "memmap_default.ld", "//src/common/pico_base:pico_base_interface", "//src/common/pico_binary_info",