Skip to content
Draft
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
2 changes: 1 addition & 1 deletion environment_setup/setup_software.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ host_software_packages=(
libffi-dev # needed to use _ctypes in Python3
libssl-dev # needed to build Python 3 with ssl support
openssl # possibly also necessary for ssl in Python 3
sshpass #used to remotely ssh into robots via Ansible
sshpass # used to remotely ssh into robots via Ansible
unzip # installing tigers autoref
xvfb # used for CI to run GUI applications
)
Expand Down
7 changes: 7 additions & 0 deletions environment_setup/setup_software_mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ host_software_packages=(
node@20
go@1.24
clang-format@20
sshpass # used to remotely ssh into robots via Ansible
)

for pkg in "${host_software_packages[@]}"; do
Expand Down Expand Up @@ -59,6 +60,8 @@ sudo pip install -r macos_requirements.txt

print_status_msg "Done Setting Up Python Environment"

sudo ln -s /opt/tbotspython/bin/platformio /usr/local/bin/platformio

print_status_msg "Fetching game controller"
install_gamecontroller $sys

Expand All @@ -76,6 +79,10 @@ print_status_msg "Setting up cross compiler for robot software"
install_cross_compiler $sys
print_status_msg "Done setting up cross compiler for robot software"

print_status_msg "Setting up STM32 cross-compiler for motor board firmware"
install_stm32_cross_compiler $sys
print_status_msg "Done setting up STM32 cross-compiler"

print_status_msg "Setting Up Python Development Headers"
install_python_toolchain_headers
print_status_msg "Done Setting Up Python Development Headers"
Expand Down
18 changes: 8 additions & 10 deletions environment_setup/util.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,10 @@ install_clang_format() {
}

install_cross_compiler() {
file_name=aarch64-tbots-linux-gnu-for-aarch64
if is_darwin $1; then
full_file_name=$file_name.tar.xz
curl -L "https://raw.githubusercontent.com/UBC-Thunderbots/Software-External-Dependencies/refs/heads/main/toolchain/$full_file_name" \
-o /tmp/tbots_download_cache/$full_file_name
tar -xf /tmp/tbots_download_cache/$full_file_name -C /tmp/tbots_download_cache/
sudo mv /tmp/tbots_download_cache/aarch64-tbots-linux-gnu /opt/tbotspython
rm /tmp/tbots_download_cache/$full_file_name
brew install messense/macos-cross-toolchains/aarch64-unknown-linux-gnu
else
file_name=aarch64-tbots-linux-gnu-for-aarch64
if is_x86 $1; then
file_name=aarch64-tbots-linux-gnu-for-x86
fi
Expand Down Expand Up @@ -127,14 +122,17 @@ install_python_dev_cross_compile_headers() {

install_stm32_cross_compiler() {
arch="aarch64"
if is_x86 $1; then
if is_darwin $1; then
arch="darwin-arm64"
elif is_x86 $1; then
arch="x86_64"
fi
download_link=https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/arm-gnu-toolchain-14.3.rel1-${arch}-arm-none-eabi.tar.xz
toolchain_name=arm-gnu-toolchain-14.3.rel1-${arch}-arm-none-eabi
download_link=https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/${toolchain_name}.tar.xz

wget -N $download_link -O /tmp/tbots_download_cache/arm-gnu-toolchain.tar.xz
tar -xf /tmp/tbots_download_cache/arm-gnu-toolchain.tar.xz -C /tmp/tbots_download_cache/
sudo mv /tmp/tbots_download_cache/arm-gnu-toolchain-14.3.rel1-${arch}-arm-none-eabi /opt/tbotspython/arm-none-eabi-gcc
sudo mv /tmp/tbots_download_cache/${toolchain_name} /opt/tbotspython/arm-none-eabi-gcc
rm /tmp/tbots_download_cache/arm-gnu-toolchain.tar.xz
}

Expand Down
7 changes: 7 additions & 0 deletions src/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ register_toolchains(
)

register_toolchains(
"//toolchains/cc:cc_toolchain_for_macos_robot",
"//toolchains/cc:cc_toolchain_for_k8_aarch64_linux",
"//toolchains/cc:cc_toolchain_for_k8",
"//toolchains/cc:cc_toolchain_for_aarch64",
Expand Down Expand Up @@ -286,6 +287,12 @@ new_local_repository(
path = "/opt/tbotspython/aarch64-tbots-linux-gnu/",
)

new_local_repository(
name = "macos_robot_gcc",
build_file = "@//extlibs:macos_robot_gcc.BUILD",
path = "/opt/homebrew/Cellar/aarch64-unknown-linux-gnu/15.2.0/toolchain/",
)

new_local_repository(
name = "motor_board_gcc",
build_file = "@//extlibs:motor_board_gcc.BUILD",
Expand Down
9 changes: 9 additions & 0 deletions src/extlibs/macos_robot_gcc.BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package(default_visibility = ["//visibility:public"])

# The prebuilt messense aarch64-unknown-linux-gnu toolchain (Homebrew), exposed
# as Bazel inputs so its binaries (gcc, ld, as, ...) are staged into the sandbox
# when cross-compiling robot firmware on macOS.
filegroup(
name = "everything",
srcs = glob(["**"]),
)
2 changes: 2 additions & 0 deletions src/software/embedded/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ cc_library(
name = "spi_utils",
srcs = ["spi_utils.cpp"],
hdrs = ["spi_utils.h"],
# Uses Linux kernel headers (linux/spi/spidev.h); robot-only.
target_compatible_with = ["@platforms//os:linux"],
deps = [
"//software/logger",
],
Expand Down
2 changes: 2 additions & 0 deletions src/software/embedded/gpio/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ cc_library(
"gpio.h",
"gpio_char_dev.h",
],
# Uses Linux kernel headers (linux/gpio.h); robot-only.
target_compatible_with = ["@platforms//os:linux"],
deps = [
"//software/logger",
"//software/logger:network_logger",
Expand Down
2 changes: 2 additions & 0 deletions src/software/embedded/motor_controller/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ cc_library(
"stspin_motor_controller.h",
"tmc_motor_controller.h",
],
# Uses Linux kernel headers (linux/spi/spidev.h); robot-only.
target_compatible_with = ["@platforms//os:linux"],
deps = [
":motor_board",
":motor_fault_indicator",
Expand Down
2 changes: 2 additions & 0 deletions src/software/embedded/services/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ cc_library(
name = "imu",
srcs = ["imu.cpp"],
hdrs = ["imu.h"],
# Uses Linux kernel headers (linux/i2c-dev.h); robot-only.
target_compatible_with = ["@platforms//os:linux"],
deps = [
"//proto:tbots_cc_proto",
"//shared:constants",
Expand Down
9 changes: 8 additions & 1 deletion src/tbots.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def create_command(config: BuildConfig, extra_args: list[str]) -> list[str]:
if config.test_suite and config.action == ActionArgument.test:
target = """-- //... \\
-//software/gameplay_tests/... \\
-//toolchains/cc/... \\
-//toolchains/... \\
-//software:unix_full_system_tar_gen"""
else:
target = fuzzy_find_target(
Expand All @@ -214,6 +214,13 @@ def create_command(config: BuildConfig, extra_args: list[str]) -> list[str]:
if condition:
command += list(flag.value)

# `test --suite` resolves to //..., and `bazel test` would also try to BUILD
# every non-test target in that pattern — including robot firmware that only
# compiles with the cross toolchain (e.g. thunderloop pulls in linux/* headers
# that don't exist on the host). Restrict to test targets and their deps.
if config.test_suite and config.action == ActionArgument.test:
command += ["--build_tests_only"]

if config.jobs_option:
command += [f"--jobs={config.jobs_option}"]

Expand Down
74 changes: 74 additions & 0 deletions src/toolchains/cc/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ cc_toolchain_config_k8_aarch64_linux(

toolchain(
name = "cc_toolchain_for_k8_aarch64_linux",
exec_compatible_with = [
"@platforms//os:linux",
],
target_compatible_with = [
"@platforms//cpu:aarch64",
"@platforms//os:linux",
Expand All @@ -278,6 +281,77 @@ toolchain(
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)

# NOTE: the Cellar path is version-pinned; a repository rule should derive it
# (e.g. from `brew --prefix`) once this is productionized.
MACOS_ROBOT_TC = "/opt/homebrew/Cellar/aarch64-unknown-linux-gnu/15.2.0/toolchain"

cc_toolchain_config_k8_aarch64_linux(
name = "gcc_macos_robot",
builtin_include_directories = [
MACOS_ROBOT_TC + "/aarch64-unknown-linux-gnu/include/c++/15.2.0",
MACOS_ROBOT_TC + "/aarch64-unknown-linux-gnu/include/c++/15.2.0/aarch64-unknown-linux-gnu",
MACOS_ROBOT_TC + "/aarch64-unknown-linux-gnu/include/c++/15.2.0/backward",
MACOS_ROBOT_TC + "/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/include",
MACOS_ROBOT_TC + "/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/include-fixed",
MACOS_ROBOT_TC + "/aarch64-unknown-linux-gnu/include",
MACOS_ROBOT_TC + "/aarch64-unknown-linux-gnu/sysroot/usr/include",
] + make_builtin_include_directories(),
tool_paths = {
"ar": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-ar",
"cpp": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-cpp",
# messense ships no dwp; point at gcc (unused without fission).
"dwp": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-gcc",
# wrapper forces -fuse-ld=bfd (messense has no gold linker).
"gcc": "wrapper/macos_robot_gcc",
"gcov": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-gcov",
"ld": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-ld",
"nm": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-nm",
"objcopy": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-objcopy",
"objdump": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-objdump",
"strip": MACOS_ROBOT_TC + "/bin/aarch64-unknown-linux-gnu-strip",
},
toolchain_identifier = "gcc-macos-robot",
)

filegroup(
name = "macos_robot_everything",
srcs = [
"wrapper/macos_robot_gcc",
"@macos_robot_gcc//:everything",
],
)

cc_toolchain(
name = "cc_toolchain_macos_robot",
all_files = ":macos_robot_everything",
ar_files = ":macos_robot_everything",
as_files = ":macos_robot_everything",
compiler_files = ":macos_robot_everything",
dwp_files = ":macos_robot_everything",
linker_files = ":macos_robot_everything",
objcopy_files = ":macos_robot_everything",
strip_files = ":macos_robot_everything",
supports_param_files = 0,
tags = ["no-ide"],
toolchain_config = ":gcc_macos_robot",
toolchain_identifier = "gcc-macos-robot",
)

toolchain(
name = "cc_toolchain_for_macos_robot",
exec_compatible_with = [
"@platforms//os:osx",
"@platforms//cpu:aarch64",
],
target_compatible_with = [
"@platforms//cpu:aarch64",
"@platforms//os:linux",
":glibc_2_27",
],
toolchain = ":cc_toolchain_macos_robot",
toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
)

toolchain(
name = "cc_toolchain_for_k8",
exec_compatible_with = [
Expand Down
26 changes: 26 additions & 0 deletions src/toolchains/cc/wrapper/macos_robot_gcc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash --norc

# Wrapper around the prebuilt messense aarch64-unknown-linux-gnu GCC 15.2.0,
# applying two robot-deployment fix-ups (both no-ops for compile-only calls):
#
# * Static C++ runtime: this toolchain is GCC 15, newer than the robot's system
# libstdc++, so a dynamic libstdc++ dependency requires GLIBCXX/CXXABI symbol
# versions the robot doesn't have. Bazel passes an explicit `-lstdc++`, which
# `-static-libstdc++` does NOT intercept, so rewrite it to the static archive
# (`-l:libstdc++.a`). `-static-libgcc` covers libgcc.
#
# * `-fuse-ld=bfd`: messense ships only the BFD linker (no ld.gold), but the
# shared cc_toolchain config adds `-fuse-ld=gold`; appending bfd wins.

TC=/opt/homebrew/Cellar/aarch64-unknown-linux-gnu/15.2.0/toolchain

args=()
for a in "$@"; do
if [ "$a" = "-lstdc++" ]; then
args+=("-l:libstdc++.a")
else
args+=("$a")
fi
done

exec "$TC/bin/aarch64-unknown-linux-gnu-gcc" "${args[@]}" -fuse-ld=bfd -static-libgcc
Loading