Skip to content

Commit

Permalink
Use MSV to select the version of the toolchain
Browse files Browse the repository at this point in the history
This commit fixes an issue with the bzlmod extension that prevents
consuming MODULE.bazel files from being able to select the version of
the toolchain. Now, the bzlmod extension selects the minimum version
from the modules that have requested the toolchain and uses that for the
system. This allows consumers to upgrade the version of
arm_gnu_toolchain without needing to ugprade their compiler version, as
well.
  • Loading branch information
AmateurECE committed Mar 14, 2024
1 parent 5daa14f commit 51e25a2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 28 deletions.
4 changes: 4 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ module(
bazel_dep(name = "platforms", version = "0.0.8")

arm_toolchain = use_extension("@arm_gnu_toolchain//:extensions.bzl", "arm_toolchain")
# NOTE: It's important that we update these versions whenever a new toolchain
# version is added--otherwise the Minimum Selected Version algorithm in the
# module extension will select the version here if a consumer attempts to use
# the newer toolchain.
arm_toolchain.arm_none_eabi(version = "13.2.1")
use_repo(
arm_toolchain,
Expand Down
38 changes: 20 additions & 18 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 62 additions & 10 deletions extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,69 @@ load(
"arm_none_linux_gnueabihf_deps",
)

def compare_versions(left, right):
"""
Compare two version strings, assuming that they're both of the form
major.minor.patch.
Returns:
-1 if left < right
0 if left == right
1 if left > right
"""
left_parts = [int(i) for i in left.split('.')]
right_parts = [int(i) for i in right.split('.')]
for i in range(3):
if left_parts[0] < right_parts[0]:
return -1

if left_parts[0] > right_parts[0]:
return 1

return 0

def minimum_supported_version(versions):
"""Obtains the minimum version from the list of version strings."""
if not len(versions):
return None

if 1 == len(versions):
return versions[0]

minimum = versions[0]
for version in versions[1:]:
if compare_versions(minimum, version) > 0:
minimum = version

return minimum

def get_toolchain_versions(module_ctx, tag_class):
"""Extract toolchain versions from tag classes obtained by evaluating
the lambda on each module."""
versions = []
for mod in module_ctx.modules:
for attr in tag_class(mod):
versions.append(attr.version)
return versions

def _arm_toolchain_impl(ctx):
for mod in ctx.modules:
# FIXME: The module extension fails if this is removed, but it
# prevents the ability to override the toolchain version in the
# consuming MODULE.bazel. We should implement some form of MSV
# selection here.
if mod.name == "arm_gnu_toolchain":
for attr in mod.tags.arm_none_eabi:
arm_none_eabi_deps(version = attr.version)
for attr in mod.tags.arm_none_linux_gnueabihf:
arm_none_linux_gnueabihf_deps(version = attr.version)
selected_baremetal_version = minimum_supported_version(
get_toolchain_versions(
ctx,
lambda mod: mod.tags.arm_none_eabi,
)
)
if selected_baremetal_version:
arm_none_eabi_deps(version = selected_baremetal_version)

selected_linux_version = minimum_supported_version(
get_toolchain_versions(
ctx,
lambda mod: mod.tags.arm_none_linux_gnueabihf,
)
)
if selected_linux_version:
arm_none_linux_gnueabihf_deps(version = selected_linux_version)

_toolchain = tag_class(attrs = {
"version": attr.string(),
Expand Down

0 comments on commit 51e25a2

Please sign in to comment.