Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# The vendored instance of googletest v1.11.0 is not supported by current Bazel version.
# It will cause errors in Bazel if not ignored
# A fixed version exists on the central Bazel registry that can be used on the Bazel side:
# https://registry.bazel.build/modules/googletest/1.11.0
libs/3rdparty/googletest
12 changes: 12 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
build:s32k148_gcc --platforms=//bazel/platform:s32k148
# Default to gcc
build:s32k148 --config=s32k148_gcc

# TODO: Temporary config only needed for artifact analysis
# Make Bazel's build match CMake s32k148-freertos-gcc default config
build:s32k148_relwithdebinfo --config=s32k148
build:s32k148_relwithdebinfo --copt=-g3
build:s32k148_relwithdebinfo --copt=-O2
build:s32k148_relwithdebinfo --copt=-DNDEBUG

test --//bazel/config/executable_config=unit_test
1 change: 1 addition & 0 deletions .bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8.6.0
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ doc/api/doc-coverage.info
doc/api/doxygenOut
tools/puncover_tool/output/
venv
bazel-*
bazel-bin
bazel-openbsw
bazel-out
bazel-testlogs
12 changes: 12 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module(
name = "openbsw",
version = "0.0.1",
)

bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_cc", version = "0.2.17")
bazel_dep(name = "bazel_skylib", version = "1.9.0")

register_toolchains(
"//bazel/toolchain:cc_toolchain_arm_none_eabi_gcc",
)
209 changes: 209 additions & 0 deletions MODULE.bazel.lock
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we want to check-in this file or not. I think i improves reproducibility, but it is can be very unhandy in case it is not updated properly because it is always modified during a build. Should we set --lockfile_mode=error in our .bazelrc? This would also ensure that in case something is changed CI will fail and the developer has to check-in an updated version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely a concern worth discussing. Thank you for bringing it up.

  • Bazel's best practices mention:

Include the lockfile in version control to facilitate collaboration and ensure that all team members have access to the same lockfile, promoting consistent development environments across the project.

  • In prinicple the lockfile should not be regenerated during normal builds even with the default lockfile_mode=update
  • For Ci I would propose to include this as one of the first steps: bazel mod graph --lockfile_mode=error

I personnally have not have problems with bazel lockfiles / version control in newer Bazel version. If you have another perspective I'm also happy to go with your proposal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just know that we recently checked-in the lockfile in a bigger project recently and I always have the issue that it is changed on every build and I always end-up with a modified file. That's exetremely unhandy.

But maybe that is just an issue in this project and we do not have a problem here. I think we can give it a try and experience how it behaves. And, as we said, in case we have a check in CI by bazel mod graph --lockfile_mode=error it would be ensured that nobody forgets to check-in the lockfile.

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions bazel/config/executable_config/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Build configuration flag for selecting between application build variants.
This allows targets to define variable dependencies/headers/sources based on the
active build variant (reference_app or unit_test).

- Set via --//bazel/config/executable_config=<value>
- Defaults to "reference_app"
- Overridden to "unit_test" for bazel test commands in .bazelrc
"""
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")

string_flag(
name = "executable_config",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether we need this? I think we use it for the select in the label_flag right? I wonder whether we could also handle this through a transition such that we can simply build the reference app or the unit tests?

Copy link
Copy Markdown

@the-nick-fischer the-nick-fischer May 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that it's a bit awkward to model the OpenBSW structures in Bazel out of the box.

Personally, I've not worked with Bazel transitions yet, but I've heard that they can get quite complex and lead to bad performance if not used correctly.
We're currently setting some defaults for executable_config so reference_app will be set in general,but gets overwritten by unit_tets for bazel test.

What would be the advantages of using transitions? Is the "payoff" big enough to warrant the increased complexity (if there is any)?

NOTE: executable_config will also be used in selects in other lib targets (expected: app_configuration, common_impl, uds_configuration, lwip_configuration, bsp_configuration)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So transitions can be really hard to understand, I agree, and they can also (in case used wildly) introduce performance issues (especially in terms of caching and building the same files multiple times). Let's have a separate discussion on transition, since I think it is not a trivial topic :)

build_setting_default = "reference_app",
values = ["reference_app", "unit_test"],
visibility = ["//visibility:public"],
)

config_setting(
name = "reference_app",
flag_values = {":executable_config": "reference_app"},
visibility = ["//visibility:public"],
)

config_setting(
name = "unit_test",
flag_values = {":executable_config": "unit_test"},
visibility = ["//visibility:public"],
)
7 changes: 7 additions & 0 deletions bazel/platform/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
platform(
name = "s32k148",
constraint_values = [
"@platforms//cpu:armv7e-m",
"@platforms//os:none",
],
)
29 changes: 29 additions & 0 deletions bazel/toolchain/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
load(":arm_none_eabi/gcc/arm_none_eabi_gcc_cc_toolchain_config.bzl", "cc_toolchain_config")

package(default_visibility = ["//visibility:public"])

filegroup(name = "empty")

cc_toolchain_config(name = "arm_none_eabi_gcc_toolchain_config")

cc_toolchain(
name = "arm_none_eabi_gcc_toolchain",
all_files = ":empty",
compiler_files = ":empty",
dwp_files = ":empty",
linker_files = ":empty",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 0,
toolchain_config = ":arm_none_eabi_gcc_toolchain_config",
)

toolchain(
name = "cc_toolchain_arm_none_eabi_gcc",
target_compatible_with = [
"@platforms//os:none",
"@platforms//cpu:armv7e-m",
],
toolchain = ":arm_none_eabi_gcc_toolchain",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
load(
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
"feature",
"flag_group",
"flag_set",
"tool_path",
)

_ALL_C_COMPILE_ACTIONS = [
ACTION_NAMES.c_compile,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.assemble,
]

_ALL_CXX_COMPILE_ACTIONS = [
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
]

_ALL_COMPILE_ACTIONS = _ALL_C_COMPILE_ACTIONS + _ALL_CXX_COMPILE_ACTIONS

_ALL_LINK_ACTIONS = [
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
]

_ALL_ASSEMBLE_ACTIONS = [
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
]

_ARM_GNU_TOOLCHAIN_ROOT = "/opt/arm-gnu-toolchain"

def _impl(ctx):
tool_paths = [
tool_path(
name = "gcc",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-gcc",
),
tool_path(
name = "ld",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-ld",
),
tool_path(
name = "ar",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-ar",
),
tool_path(
name = "cpp",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-cpp",
),
tool_path(
name = "gcov",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-gcov",
),
tool_path(
name = "nm",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-nm",
),
tool_path(
name = "objdump",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-objdump",
),
tool_path(
name = "strip",
path = _ARM_GNU_TOOLCHAIN_ROOT + "/bin/arm-none-eabi-strip",
),
]

features = [
feature(
name = "architecture_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-mcpu=cortex-m4",
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-fmessage-length=0",
],
),
],
),
],
),
feature(
name = "common_compile_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-Wno-psabi",
"-fdata-sections",
"-ffunction-sections",
"-fno-asynchronous-unwind-tables",
"-fno-builtin",
"-fno-common",
"-fshort-enums",
"-fstack-usage",
"-mno-unaligned-access",
"-mthumb",
],
),
],
),
],
),
feature(
name = "c_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_C_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-ffreestanding",
"-funsigned-bitfields",
],
),
],
),
],
),
feature(
name = "cxx_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_CXX_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-std=gnu++17",
"-fno-exceptions",
"-fno-non-call-exceptions",
"-fno-rtti",
"-fno-threadsafe-statics",
"-fno-use-cxa-atexit",
"-femit-class-debug-always",
"-funsigned-bitfields",
],
),
],
),
],
),
feature(
name = "assembler_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_ASSEMBLE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-g",
],
),
],
),
],
),

feature(
name = "realtime_os_define",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = ["-DREALTIME_OS=1"],
),
],
),
],
),
feature(
name = "default_linker_flags",
enabled = True,
flag_sets = [
flag_set(
actions = _ALL_LINK_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-mcpu=cortex-m4",
"-mfloat-abi=hard",
"-mfpu=fpv4-sp-d16",
"-static",
"-Wl,--gc-sections",
"-specs=nano.specs",
"-specs=nosys.specs",
],
),
],
),
],
),

# TODO: Verify if assumption is correct: bare-metal targets do not use PIC or dynamic linking
feature(name = "supports_pic", enabled = False),
feature(name = "supports_dynamic_linker", enabled = False),
]

return cc_common.create_cc_toolchain_config_info(
ctx = ctx,
features = features,
cxx_builtin_include_directories = [
_ARM_GNU_TOOLCHAIN_ROOT + "/lib/gcc/arm-none-eabi",
_ARM_GNU_TOOLCHAIN_ROOT + "/arm-none-eabi/include",
],
toolchain_identifier = "arm_none_eabi_gcc_toolchain",
host_system_name = "local",
target_system_name = "arm-none-eabi",
target_cpu = "cortex-m4",
target_libc = "newlib-nano",
compiler = "gcc",
abi_version = "eabi",
abi_libc_version = "newlib",
tool_paths = tool_paths,
)

cc_toolchain_config = rule(
implementation = _impl,
attrs = {},
provides = [CcToolchainConfigInfo],
)
Loading
Loading