├── tools ├── workspace │ ├── BUILD │ ├── mbed │ │ ├── BUILD │ │ ├── stm32g4.patch │ │ ├── mbed.patch │ │ ├── package.BUILD │ │ ├── rules.bzl │ │ ├── json.bzl │ │ └── repository.bzl │ ├── arm_gcc │ │ ├── BUILD │ │ ├── package.BUILD │ │ └── repository.bzl │ └── default.bzl ├── cc_toolchain │ ├── wrapper │ │ ├── arm-none-eabi-ar │ │ ├── arm-none-eabi-cpp │ │ ├── arm-none-eabi-gcc │ │ ├── arm-none-eabi-ld │ │ ├── arm-none-eabi-nm │ │ ├── arm-none-eabi-gcov │ │ ├── arm-none-eabi-strip │ │ ├── arm-none-eabi-objcopy │ │ ├── arm-none-eabi-objdump │ │ └── arm-none-eabi-g++ │ ├── BUILD │ └── cc_toolchain_config.bzl ├── BUILD └── bazel ├── .gitignore ├── .travis.yml ├── travis-ci.sh ├── .bazelrc ├── LICENSE ├── example ├── common.h ├── common.cc ├── example1.cc ├── BUILD └── stm32f411.ld ├── cpu └── BUILD ├── rules.bzl ├── BUILD ├── WORKSPACE └── README.md /tools/workspace/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tools/workspace/mbed/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bazel-* 2 | *~ 3 | -------------------------------------------------------------------------------- /tools/workspace/arm_gcc/BUILD: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | script: ./travis-ci.sh 2 | dist: bionic 3 | language: cpp 4 | -------------------------------------------------------------------------------- /tools/workspace/mbed/stm32g4.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjbots/rules_mbed/HEAD/tools/workspace/mbed/stm32g4.patch -------------------------------------------------------------------------------- /travis-ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -ev 4 | 5 | ./tools/bazel build --config=stm32f4 //... 6 | ./tools/bazel build //example:common 7 | -------------------------------------------------------------------------------- /.bazelrc: -------------------------------------------------------------------------------- 1 | common --noenable_bzlmod 2 | build --noincompatible_enable_cc_toolchain_resolution 3 | 4 | build --incompatible_enable_cc_toolchain_resolution 5 | build --compiler=compiler 6 | build --nostart_end_lib 7 | 8 | build:stm32f4 --cpu=stm32f4 9 | build:stm32f4 --platforms=//:stm32f4 10 | build:stm32f4 --crosstool_top=//tools/cc_toolchain:toolchain 11 | -------------------------------------------------------------------------------- /tools/workspace/mbed/mbed.patch: -------------------------------------------------------------------------------- 1 | diff -ur mbed-os-mbed-os-5.13.2/platform/mbed_rtc_time.h updated-mbed-5.13.2/platform/mbed_rtc_time.h 2 | --- mbed-os-mbed-os-5.13.2/platform/mbed_rtc_time.h 2019-07-26 14:24:03.000000000 -0400 3 | +++ updated-mbed-5.13.2/platform/mbed_rtc_time.h 2019-07-31 22:46:07.029224634 -0400 4 | @@ -23,6 +23,7 @@ 5 | */ 6 | 7 | #include 8 | +#include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | Only in updated-mbed-5.13.2/platform: mbed_rtc_time.h~ 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 2 | mafanasyev@gmail.com 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /example/common.h: -------------------------------------------------------------------------------- 1 | // Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | int do_work(); 16 | -------------------------------------------------------------------------------- /example/common.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | int do_work() { 16 | return 10; 17 | } 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-ar: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-ar "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-cpp: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-cpp "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-gcc: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-gcc "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-ld: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-ld "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-nm: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-nm "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-gcov: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-gcov "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-strip: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-strip "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-objcopy: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-objcopy "$@" 18 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-objdump: -------------------------------------------------------------------------------- 1 | #!/bin/bash --norc 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | exec external/com_arm_developer_gcc/bin/arm-none-eabi-objdump "$@" 18 | -------------------------------------------------------------------------------- /tools/BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | environment(name = "k8") 20 | environment(name = "stm32f4") 21 | 22 | environment_group( 23 | name = "cpus", 24 | environments = [":k8", ":stm32f4"], 25 | defaults = [":stm32f4"], 26 | ) 27 | -------------------------------------------------------------------------------- /example/example1.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "common.h" 18 | #include "mbed.h" 19 | 20 | int main(int, char**) { 21 | DigitalOut led(LED1); 22 | 23 | for (;;) { 24 | printf("%d\n", do_work()); 25 | printf("hello there!\n"); 26 | led.write(!led.read()); 27 | wait(1.0); 28 | } 29 | return 0; 30 | } 31 | 32 | extern "C" { 33 | void abort() { 34 | mbed_die(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cpu/BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | constraint_value( 20 | name = "stm32f0", 21 | constraint_setting = "@platforms//cpu:cpu", 22 | ) 23 | 24 | constraint_value( 25 | name = "stm32f4", 26 | constraint_setting = "@platforms//cpu:cpu", 27 | ) 28 | 29 | constraint_value( 30 | name = "stm32g4", 31 | constraint_setting = "@platforms//cpu:cpu", 32 | ) 33 | -------------------------------------------------------------------------------- /tools/workspace/arm_gcc/package.BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | filegroup( 20 | name = "everything", 21 | srcs = glob(["**"]), 22 | ) 23 | 24 | filegroup( 25 | name = "gcc", 26 | srcs = ["bin/arm-none-eabi-gcc"], 27 | ) 28 | 29 | filegroup( 30 | name = "cpp", 31 | srcs = ["bin/arm-none-eabi-cpp"], 32 | ) 33 | 34 | filegroup( 35 | name = "objcopy", 36 | srcs = ["bin/arm-none-eabi-objcopy"], 37 | ) 38 | -------------------------------------------------------------------------------- /rules.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | load("//tools/workspace:default.bzl", "DEFAULT_CONFIG", "add_default_repositories") 18 | 19 | def mbed_register(config = DEFAULT_CONFIG): 20 | add_default_repositories(config=config) 21 | 22 | native.register_toolchains( 23 | "@com_github_mjbots_rules_mbed//tools/cc_toolchain:cc_toolchain_stm32f0", 24 | "@com_github_mjbots_rules_mbed//tools/cc_toolchain:cc_toolchain_stm32f4", 25 | "@com_github_mjbots_rules_mbed//tools/cc_toolchain:cc_toolchain_stm32g4", 26 | ) 27 | -------------------------------------------------------------------------------- /example/BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | load("@com_github_ARMmbed_mbed-os//:rules.bzl", "mbed_binary") 18 | load("@com_github_ARMmbed_mbed-os_g474//:rules.bzl", mbed_g4_binary="mbed_binary") 19 | 20 | cc_library( 21 | name = "common", 22 | hdrs = ["common.h"], 23 | srcs = ["common.cc"], 24 | ) 25 | 26 | mbed_binary( 27 | name = "example1", 28 | srcs = ["example1.cc"], 29 | deps = [":common"], 30 | ) 31 | 32 | mbed_g4_binary( 33 | name = "g4_example1", 34 | srcs = ["example1.cc"], 35 | deps = [":common"], 36 | ) 37 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | platform( 20 | name = "stm32f0", 21 | constraint_values = [ 22 | "@platforms//os:none", 23 | "//cpu:stm32f0", 24 | ], 25 | ) 26 | 27 | platform( 28 | name = "stm32f4", 29 | constraint_values = [ 30 | "@platforms//os:none", 31 | "//cpu:stm32f4", 32 | ], 33 | ) 34 | 35 | platform( 36 | name = "stm32g4", 37 | constraint_values = [ 38 | "@platforms//os:none", 39 | "//cpu:stm32g4", 40 | ], 41 | ) 42 | -------------------------------------------------------------------------------- /tools/workspace/arm_gcc/repository.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 18 | 19 | 20 | def arm_gcc_repository(name): 21 | http_archive( 22 | name = name, 23 | urls = [ 24 | "https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/11.3.rel1/binrel/arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi.tar.xz", 25 | ], 26 | sha256 = "d420d87f68615d9163b99bbb62fe69e85132dc0a8cd69fca04e813597fe06121", 27 | strip_prefix = "arm-gnu-toolchain-11.3.rel1-x86_64-arm-none-eabi", 28 | build_file = Label("//tools/workspace/arm_gcc:package.BUILD"), 29 | ) 30 | -------------------------------------------------------------------------------- /WORKSPACE: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | workspace(name = "com_github_mjbots_rules_mbed") 18 | 19 | BAZEL_VERSION = "7.4.1" 20 | BAZEL_VERSION_SHA = "c97f02133adce63f0c28678ac1f21d65fa8255c80429b588aeeba8a1fac6202b" 21 | 22 | load("//:rules.bzl", "mbed_register") 23 | load("//tools/workspace/mbed:repository.bzl", "mbed_repository") 24 | 25 | mbed_register() 26 | 27 | mbed_repository( 28 | name = "com_github_ARMmbed_mbed-os_g474", 29 | target = "targets/TARGET_STM/TARGET_STM32G4/TARGET_STM32G474xE/TARGET_NUCLEO_G474RE", 30 | config = { 31 | "MBED_CONF_RTOS_PRESENT": "0", 32 | "DEVICE_STDIO_MESSAGES": "0", 33 | "MBED_CONF_TARGET_CONSOLE_UART": "1", 34 | }, 35 | ) 36 | -------------------------------------------------------------------------------- /tools/workspace/default.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | load("//tools/workspace/arm_gcc:repository.bzl", "arm_gcc_repository") 18 | load("//tools/workspace/mbed:repository.bzl", "mbed_repository") 19 | 20 | 21 | DEFAULT_CONFIG = { 22 | "mbed_target": "targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F446xE/TARGET_NUCLEO_F446ZE", 23 | "mbed_config": None, 24 | } 25 | 26 | def add_default_repositories(*, config = DEFAULT_CONFIG, excludes = []): 27 | if "arm_gcc" not in excludes: 28 | arm_gcc_repository(name = "com_arm_developer_gcc") 29 | if "mbed" not in excludes: 30 | mbed_repository(name = "com_github_ARMmbed_mbed-os", 31 | target = config["mbed_target"], 32 | config = config["mbed_config"]) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mbed rules for Bazel # 2 | 3 | This package provides bazel (https://bazel.build) rules for building 4 | binaries for mbed-os (https://github.com/ARMmbed/mbed-os) embedded 5 | targets. It includes bazel configuration for the ARM-GCC toolchain, 6 | as well as dedicated bazel rules for building output binary files. It 7 | supports multiple distinct mbed targets within the same build. 8 | 9 | * License: Apache 2.0 10 | * travis-ci [![Build Status](https://travis-ci.org/mjbots/rules_mbed.svg?branch=master)](https://travis-ci.org/mjbots/rules_mbed) 11 | * Processors: STM32F0, STM32F4, and STM32G4 family processors 12 | 13 | ## Usage ## 14 | 15 | In `WORKSPACE` add this: 16 | 17 | ``` 18 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 19 | 20 | RULES_MBED_COMMIT = "XXX" 21 | 22 | http_archive( 23 | name = "rules_mbed", 24 | url = "https://github.com/mjbots/bazel_deps/{}.zip".format(RULES_MBED_COMMIT), 25 | sha256 = "XXX", 26 | strip_prefix = "rules_mbed-{}".format(RULES_MBED_COMMIT), 27 | ) 28 | 29 | load("@rules_mbed//:rules.bzl", "mbed_register") 30 | mbed_register(config = { 31 | "mbed_target": "targets/TARGET_STM/TARGET_STM32F4/TARGET_STM32F411xE/TARGET_NUCLEO_F411RE", 32 | "mbed_config": None, 33 | } 34 | ) 35 | ``` 36 | 37 | Then in a BUILD file you can use: 38 | 39 | ``` 40 | load("@com_github_ARMmbed_mbed-os//:rules.bzl", "mbed_binary") 41 | 42 | mbed_binary( 43 | name = "example", 44 | srcs = ["example.cc"], 45 | ) 46 | ``` 47 | 48 | And in your bazelrc you can list: 49 | 50 | ``` 51 | build --incompatible_enable_cc_toolchain_resolution 52 | build --platforms=@rules_mbed//:stm32f4 53 | ``` 54 | -------------------------------------------------------------------------------- /tools/workspace/mbed/package.BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | 20 | # Yay, The mbed source is full of circular dependencies. About the 21 | # best we can do is lump everything into one giant cc_library and suck 22 | # up the recompilation time. 23 | cc_library( 24 | name = "mbed", 25 | hdrs = glob( 26 | @HDR_GLOBS@ 27 | ), 28 | srcs = glob( 29 | @SRC_GLOBS@ 30 | ), 31 | includes = 32 | @INCLUDES@ 33 | , 34 | copts = 35 | @COPTS@ 36 | , 37 | defines = [ 38 | "_RTE_", 39 | "__MBED__", 40 | "__FPU_PRESENT", 41 | "__CMSIS_RTOS", 42 | "__MBED_CMSIS_RTOS_CM", 43 | "TOOLCHAIN_GCC", 44 | "TOOLCHAIN_GCC_ARM", 45 | 46 | "TARGET_RELEASE", 47 | "TARGET_LIKE_MBED", 48 | 49 | ] + @DEFINES@, 50 | features = ["noimplicitfunction"], 51 | ) 52 | 53 | genrule( 54 | name = "preprocess_linker_script", 55 | srcs = ["linker_script.ld.in"], 56 | outs = ["linker_script.ld"], 57 | tools = [ 58 | "@com_arm_developer_gcc//:everything", 59 | "@com_arm_developer_gcc//:cpp", 60 | ], 61 | cmd = "$(location @com_arm_developer_gcc//:cpp) -P {} $< -o $@".format( 62 | " ".join(["-D{}".format(x) for x in @DEFINES@ 63 | if x.find('|') == -1])), 64 | ) 65 | -------------------------------------------------------------------------------- /tools/cc_toolchain/wrapper/arm-none-eabi-g++: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 -B 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import os 18 | import sys 19 | 20 | """Delegate to the C compiler and strip C++ specific options if 21 | necessary.""" 22 | 23 | 24 | def is_cpp_arg(x): 25 | if x.startswith("-stdc++="): 26 | return True 27 | if x == "-Wno-register": 28 | return True 29 | if x == "-Wno-sized-deallocation": 30 | return True 31 | 32 | return False 33 | 34 | 35 | def strip_cpp_args(input_args): 36 | return [x for x in input_args if not is_cpp_arg(x)] 37 | 38 | 39 | def run(path, args): 40 | os.execv(path, [path] + args[1:]) 41 | 42 | 43 | def main(): 44 | args = sys.argv[:] 45 | 46 | # The ARM GCC has -isystem busted, and forces all headers found 47 | # through that path to be C only. Bazel passes all includes as 48 | # "-isystem", which doesn't interact very well with gcc. Lets 49 | # just fix that here. 50 | args = [(x if x != "-isystem" else "-I") for x in args] 51 | 52 | is_a_c_file_present = len( 53 | [x for x in args 54 | if x.endswith(".c") or x.endswith(".S")]) > 0 55 | 56 | if not is_a_c_file_present: 57 | run("external/com_arm_developer_gcc/bin/arm-none-eabi-g++", args) 58 | else: 59 | run("external/com_arm_developer_gcc/bin/arm-none-eabi-gcc", strip_cpp_args(args)) 60 | 61 | 62 | if __name__ == '__main__': 63 | main() 64 | -------------------------------------------------------------------------------- /tools/bazel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 -B 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import os 18 | import re 19 | import shutil 20 | import subprocess 21 | import sys 22 | import tempfile 23 | 24 | SCRIPT_PATH = os.path.basename(__file__) 25 | 26 | def find_workspace_dir(): 27 | path = SCRIPT_PATH 28 | while True: 29 | maybe_workspace = os.path.join(path, 'WORKSPACE') 30 | if os.path.exists(maybe_workspace): 31 | return path 32 | 33 | assert path != '' 34 | 35 | old_path = path 36 | path = os.path.dirname(path) 37 | assert path != old_path 38 | 39 | 40 | WORKSPACE_DIR = find_workspace_dir() 41 | 42 | def maybe_copy(maybe_filename, dest): 43 | if not os.path.exists(maybe_filename): 44 | return 45 | 46 | with open(maybe_filename, 'rb') as f: 47 | dest.write(f.read()) 48 | 49 | 50 | def get_workspace_var(var): 51 | search = re.compile(r'^{}\s*=\s*"(.*)"'.format(var)) 52 | 53 | with open(os.path.join(WORKSPACE_DIR, 'WORKSPACE'), 'r') as f: 54 | for line in f: 55 | match = re.search(search, line) 56 | if not match: 57 | continue 58 | 59 | return match.group(1) 60 | 61 | raise RuntimeError('Must supply a {} in the WORKSPACE'.format(var)) 62 | 63 | 64 | BAZEL_REMOTE_SOURCE = 'https://github.com/bazelbuild/bazel/releases/download' 65 | 66 | BAZEL_BIN_CACHE = os.path.expanduser('~/.cache/bazel') 67 | BAZEL_VERSION = get_workspace_var('BAZEL_VERSION') 68 | BAZEL_VERSION_SHA = get_workspace_var('BAZEL_VERSION_SHA') 69 | 70 | 71 | def download_bazel(dest): 72 | dist_tempfile = tempfile.NamedTemporaryFile(prefix='bazeldl-', delete=False) 73 | 74 | url = '{}/{}/bazel-{}-linux-x86_64'.format( 75 | BAZEL_REMOTE_SOURCE, BAZEL_VERSION, BAZEL_VERSION) 76 | 77 | print('Downloading bazel {} from {}'.format( 78 | BAZEL_VERSION, url), 79 | file=sys.stderr, flush=True) 80 | 81 | subprocess.check_call(['curl', '-L', url, '-o', dist_tempfile.name]) 82 | 83 | actual_sha256 = subprocess.check_output([ 84 | 'sha256sum', dist_tempfile.name]).decode('utf-8').split(' ')[0] 85 | 86 | if actual_sha256 != BAZEL_VERSION_SHA.lower(): 87 | raise RuntimeError( 88 | 'bazel sha256 does not match, expected {} got {}'.format( 89 | BAZEL_VERSION_SHA, actual_sha256)) 90 | 91 | subprocess.check_call(["chmod", "+x", dist_tempfile.name]) 92 | shutil.move(dist_tempfile.name, dest) 93 | 94 | 95 | def main(): 96 | bazel_bin_loc = os.path.join(BAZEL_BIN_CACHE, BAZEL_VERSION) 97 | 98 | if not os.path.exists(bazel_bin_loc): 99 | os.makedirs(os.path.dirname(bazel_bin_loc), exist_ok=True) 100 | download_bazel(bazel_bin_loc) 101 | 102 | os.execv(bazel_bin_loc, ['bazel', ] + sys.argv[1:]) 103 | assert False 104 | 105 | 106 | if __name__ == '__main__': 107 | main() 108 | -------------------------------------------------------------------------------- /tools/workspace/mbed/rules.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | def mbed_binary(enable_wrappers=True, 18 | **kwargs): 19 | '''enable_wrappers if true, wraps all the standard library functions 20 | so that the mbed provided versions will be used instead. This may 21 | be disabled if you want to wrap them yourselves, or don't need all 22 | of them. 23 | ''' 24 | deps = kwargs.pop("deps", [])[:] 25 | 26 | linker_override = kwargs.pop("linker_script", None) 27 | 28 | deps += [ 29 | Label("//:mbed"), 30 | ] 31 | 32 | srcs = kwargs.pop("srcs", [])[:] 33 | linkopts = kwargs.pop("linkopts", [])[:] 34 | 35 | linkopts += [ 36 | "-L$(GENDIR)", 37 | ] 38 | 39 | # We always provide the mbed_script as a dependency, in case 40 | # someone wants to include it. 41 | mbed_script = Label("//:linker_script.ld") 42 | deps += [mbed_script] 43 | linkopts += ["-L$(GENDIR)"] 44 | 45 | if linker_override: 46 | script = linker_override 47 | linkopts += ["-T $(location {})".format(script)] 48 | deps += [script] 49 | else: 50 | # We need the linker script to be properly expanded when passed to 51 | # ld's "-T" option. bazel claims it will do that, but it doesn't 52 | # seem to work properly, maybe due to spanning an external 53 | # repository boundary? So for now, we just manually expand the 54 | # pieces using GENDIR to get to the right place. 55 | linkopts += [ 56 | "-T $(GENDIR)/{}/{}".format(mbed_script.workspace_root, 57 | mbed_script.name), 58 | ] 59 | 60 | if enable_wrappers: 61 | linkopts += [ 62 | # This will cause the mbed allocation wrapper object to not be 63 | # dropped on the floor. (the mbed toolchain links everything as .o 64 | # files, with no intermediate .a files, so this isn't a problem 65 | # there). 66 | "-Wl,--undefined=__wrap__free_r", 67 | 68 | # Hook in the mbed allocation wrappers. 69 | "-Wl,--wrap,main", 70 | "-Wl,--wrap,_malloc_r", 71 | "-Wl,--wrap,_free_r", 72 | "-Wl,--wrap,_realloc_r", 73 | "-Wl,--wrap,_memalign_r", 74 | "-Wl,--wrap,_calloc_r", 75 | "-Wl,--wrap,exit", 76 | "-Wl,--wrap,atexit", 77 | ] 78 | 79 | copts = kwargs.pop("copts", [])[:] 80 | 81 | # The mbed headers can't handle these warnings. 82 | copts += [ 83 | "-Wno-register", 84 | "-Wno-unused-parameter", 85 | ] 86 | 87 | name = kwargs.pop("name") 88 | 89 | native.cc_binary( 90 | name = "{}.elf".format(name), 91 | deps = deps, 92 | linkopts = linkopts, 93 | srcs = srcs, 94 | copts = copts, 95 | linkstatic = 1, 96 | **kwargs 97 | ) 98 | 99 | native.genrule( 100 | name = name, 101 | srcs = ["{}.elf".format(name)], 102 | outs = ["{}.bin".format(name)], 103 | tools = ["@com_arm_developer_gcc//:objcopy"], 104 | cmd = "$(location @com_arm_developer_gcc//:objcopy) -O binary $< $@", 105 | output_to_bindir = True 106 | ) 107 | -------------------------------------------------------------------------------- /tools/cc_toolchain/BUILD: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | package(default_visibility = ["//visibility:public"]) 18 | 19 | load(":cc_toolchain_config.bzl", "cc_toolchain_config_stm32") 20 | load("@rules_cc//cc:defs.bzl", "cc_toolchain") 21 | 22 | # We keep this around so that users can work around 23 | # https://github.com/bazelbuild/bazel/issues/12036 by specifying an 24 | # otherwise unused crosstool_top. 25 | cc_toolchain_suite( 26 | name = "toolchain", 27 | toolchains = { 28 | "stm32g4|compiler": "gcc-stm32g4", 29 | "stm32f4|compiler": "gcc-stm32f4", 30 | "stm32f0|compiler": "gcc-stm32f0", 31 | }, 32 | ) 33 | 34 | filegroup( 35 | name = "empty", 36 | srcs = [], 37 | ) 38 | 39 | filegroup( 40 | name = "arm_everything", 41 | srcs = [ 42 | "@com_arm_developer_gcc//:everything", 43 | ] + glob(["wrapper/arm-none-eabi-*"]), 44 | ) 45 | 46 | cc_toolchain_config_stm32( 47 | name = "gcc-stm32f0-config", 48 | cpu = "stm32f0", 49 | toolchain_identifier = "gcc-stm32f0", 50 | host_compiler_prefix = "wrapper", 51 | host_compiler_path = "wrapper/arm-none-eabi-g++", 52 | builtin_include_directories = [ 53 | "external/com_arm_developer_gcc/arm-none-eabi/include/", 54 | "external/com_arm_developer_gcc/arm-none-eabi/include/sys/", 55 | ], 56 | ) 57 | 58 | cc_toolchain( 59 | name = "gcc-stm32f0", 60 | all_files = ":arm_everything", 61 | compiler_files = ":arm_everything", 62 | dwp_files = ":arm_everything", 63 | linker_files = ":arm_everything", 64 | objcopy_files = ":arm_everything", 65 | strip_files = ":arm_everything", 66 | ar_files = ":arm_everything", 67 | as_files = ":arm_everything", 68 | supports_param_files = 0, 69 | toolchain_config = ":gcc-stm32f0-config", 70 | ) 71 | 72 | toolchain( 73 | name = "cc_toolchain_stm32f0", 74 | exec_compatible_with = [ 75 | "@platforms//cpu:x86_64", 76 | ], 77 | target_compatible_with = [ 78 | "//cpu:stm32f0", 79 | ], 80 | toolchain = ":gcc-stm32f0", 81 | toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 82 | ) 83 | 84 | cc_toolchain_config_stm32( 85 | name = "gcc-stm32f4-config", 86 | cpu = "stm32f4", 87 | toolchain_identifier = "gcc-stm32f4", 88 | host_compiler_prefix = "wrapper", 89 | host_compiler_path = "wrapper/arm-none-eabi-g++", 90 | builtin_include_directories = [ 91 | "external/com_arm_developer_gcc/arm-none-eabi/include/", 92 | "external/com_arm_developer_gcc/arm-none-eabi/include/sys/", 93 | ], 94 | ) 95 | 96 | cc_toolchain( 97 | name = "gcc-stm32f4", 98 | all_files = ":arm_everything", 99 | compiler_files = ":arm_everything", 100 | dwp_files = ":arm_everything", 101 | linker_files = ":arm_everything", 102 | objcopy_files = ":arm_everything", 103 | strip_files = ":arm_everything", 104 | ar_files = ":arm_everything", 105 | as_files = ":arm_everything", 106 | supports_param_files = 0, 107 | toolchain_config = ":gcc-stm32f4-config", 108 | ) 109 | 110 | toolchain( 111 | name = "cc_toolchain_stm32f4", 112 | exec_compatible_with = [ 113 | "@platforms//cpu:x86_64", 114 | ], 115 | target_compatible_with = [ 116 | "//cpu:stm32f4", 117 | ], 118 | toolchain = ":gcc-stm32f4", 119 | toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 120 | ) 121 | 122 | cc_toolchain_config_stm32( 123 | name = "gcc-stm32g4-config", 124 | cpu = "stm32g4", 125 | toolchain_identifier = "gcc-stm32g4", 126 | host_compiler_prefix = "wrapper", 127 | host_compiler_path = "wrapper/arm-none-eabi-g++", 128 | builtin_include_directories = [ 129 | "external/com_arm_developer_gcc/arm-none-eabi/include/", 130 | "external/com_arm_developer_gcc/arm-none-eabi/include/sys/", 131 | ], 132 | ) 133 | 134 | cc_toolchain( 135 | name = "gcc-stm32g4", 136 | all_files = ":arm_everything", 137 | compiler_files = ":arm_everything", 138 | dwp_files = ":arm_everything", 139 | linker_files = ":arm_everything", 140 | objcopy_files = ":arm_everything", 141 | strip_files = ":arm_everything", 142 | ar_files = ":arm_everything", 143 | as_files = ":arm_everything", 144 | supports_param_files = 0, 145 | toolchain_config = ":gcc-stm32g4-config", 146 | ) 147 | 148 | toolchain( 149 | name = "cc_toolchain_stm32g4", 150 | exec_compatible_with = [ 151 | "@platforms//cpu:x86_64", 152 | ], 153 | target_compatible_with = [ 154 | "//cpu:stm32g4", 155 | ], 156 | toolchain = ":gcc-stm32g4", 157 | toolchain_type = "@bazel_tools//tools/cpp:toolchain_type", 158 | ) 159 | -------------------------------------------------------------------------------- /example/stm32f411.ld: -------------------------------------------------------------------------------- 1 | /* 2 | GNU linker script for STM32F411 3 | */ 4 | 5 | /* Specify the memory areas */ 6 | MEMORY 7 | { 8 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x080000 /* entire flash, 512 KiB */ 9 | FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 0x004000 /* sector 0, 16 KiB */ 10 | FLASH_TEXT (rx) : ORIGIN = 0x08020000, LENGTH = 0x060000 /* sectors 5,6,7 4*128KiB = 384 KiB */ 11 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0x020000 /* 128 KiB */ 12 | } 13 | 14 | /* produce a link error if there is not this amount of RAM for these sections */ 15 | _minimum_stack_size = 2K; 16 | _minimum_heap_size = 16K; 17 | 18 | /* top end of the stack */ 19 | 20 | /*_stack_end = ORIGIN(RAM) + LENGTH(RAM);*/ 21 | _estack = ORIGIN(RAM) + LENGTH(RAM); 22 | 23 | /* RAM extents for the garbage collector */ 24 | _ram_end = ORIGIN(RAM) + LENGTH(RAM); 25 | _heap_end = 0x2001c000; /* tunable */ 26 | 27 | /* define output sections */ 28 | SECTIONS 29 | { 30 | /* The startup code goes first into FLASH */ 31 | .isr_vector : 32 | { 33 | . = ALIGN(4); 34 | KEEP(*(.isr_vector)) /* Startup code */ 35 | 36 | . = ALIGN(4); 37 | } >FLASH_ISR 38 | 39 | /* The program code and other data goes into FLASH */ 40 | .text : 41 | { 42 | . = ALIGN(4); 43 | *(.text) /* .text sections (code) */ 44 | *(.text*) /* .text* sections (code) */ 45 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 46 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 47 | *(.glue_7) */ /* glue arm to thumb code */ 48 | *(.glue_7t) */ /* glue thumb to arm code */ 49 | 50 | KEEP(*(.init)) 51 | KEEP(*(.fini)) 52 | 53 | . = ALIGN(4); 54 | _etext = .; /* define a global symbol at end of code */ 55 | } >FLASH_TEXT 56 | 57 | /* 58 | * Stack unwinding and exception handling sections. 59 | * 60 | * ARM compilers emit object files with .ARM.extab and .ARM.exidx sections 61 | * when using C++ exceptions. Also, at least GCC emits those sections when 62 | * dividing large numbers (64-bit) in C. So we have to handle them. 63 | * 64 | * (ARM uses .ARM.extab and .ARM.exidx instead of the .eh_frame section 65 | * used on x86.) 66 | */ 67 | .ARM.extab : 68 | { 69 | *(.ARM.extab* .gnu.linkonce.armextab.*) 70 | } >FLASH_TEXT 71 | 72 | .ARM : 73 | { 74 | __exidx_start = .; 75 | *(.ARM.exidx*) 76 | __exidx_end = .; 77 | } >FLASH_TEXT 78 | 79 | /* 80 | * Newlib and Eglibc (at least) need these for C++ support. 81 | * 82 | * (Copied from Sourcery CodeBench Lite: arm-none-eabi-gcc -V) 83 | */ 84 | .preinit_array : 85 | { 86 | PROVIDE_HIDDEN(__preinit_array_start = .); 87 | KEEP(*(.preinit_array*)) 88 | PROVIDE_HIDDEN(__preinit_array_end = .); 89 | } >FLASH_TEXT 90 | .init_array : 91 | { 92 | PROVIDE_HIDDEN(__init_array_start = .); 93 | KEEP(*(SORT(.init_array.*))) 94 | KEEP(*(.init_array*)) 95 | PROVIDE_HIDDEN(__init_array_end = .); 96 | } >FLASH_TEXT 97 | .fini_array : 98 | { 99 | PROVIDE_HIDDEN(__fini_array_start = .); 100 | KEEP(*(SORT(.fini_array.*))) 101 | KEEP(*(.fini_array*)) 102 | PROVIDE_HIDDEN(__fini_array_end = .); 103 | } >FLASH_TEXT 104 | 105 | /* used by the startup to initialize data */ 106 | _sidata = LOADADDR(.data); 107 | 108 | /* This is the initialized data section 109 | The program executes knowing that the data is in the RAM 110 | but the loader puts the initial values in the FLASH (inidata). 111 | It is one task of the startup to copy the initial values from FLASH to RAM. */ 112 | .data : 113 | { 114 | . = ALIGN(4); 115 | _sdata = .; /* create a global symbol at data start; used by startup code in order to initialise the .data section in RAM */ 116 | _ram_start = .; /* create a global symbol at ram start for garbage collector */ 117 | *(.data) /* .data sections */ 118 | *(.data*) /* .data* sections */ 119 | 120 | . = ALIGN(4); 121 | _edata = .; /* define a global symbol at data end; used by startup code in order to initialise the .data section in RAM */ 122 | } >RAM AT> FLASH_TEXT 123 | 124 | /* Uninitialized data section */ 125 | .bss : 126 | { 127 | . = ALIGN(4); 128 | __bss_start__ = .; 129 | _sbss = .; /* define a global symbol at bss start; used by startup code */ 130 | *(.bss) 131 | *(.bss*) 132 | *(COMMON) 133 | 134 | . = ALIGN(4); 135 | _ebss = .; /* define a global symbol at bss end; used by startup code and GC */ 136 | __bss_end__ = .; 137 | } >RAM 138 | 139 | /* this is to define the start of the heap, and make sure we have a minimum size */ 140 | .heap : 141 | { 142 | . = ALIGN(4); 143 | PROVIDE ( end = . ); 144 | PROVIDE ( _end = . ); 145 | _heap_start = .; /* define a global symbol at heap start */ 146 | . = . + _minimum_heap_size; 147 | } >RAM 148 | 149 | /* this just checks there is enough RAM for the stack */ 150 | .stack : 151 | { 152 | . = ALIGN(4); 153 | . = . + _minimum_stack_size; 154 | . = ALIGN(4); 155 | } >RAM 156 | 157 | /* Remove information from the standard libraries */ 158 | /DISCARD/ : 159 | { 160 | libc.a ( * ) 161 | libm.a ( * ) 162 | libgcc.a ( * ) 163 | } 164 | 165 | .ARM.attributes 0 : { *(.ARM.attributes) } 166 | } 167 | -------------------------------------------------------------------------------- /tools/workspace/mbed/json.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | # bazel and starlark, in their infinite wisdom, do not allow use of 19 | # the python standard library, or even recursion. (I think this 20 | # limitation was made before repository rules were a thing). Thus, I 21 | # get to reimplement a crude form of json parsing here purely 22 | # iteratively. 23 | 24 | _TYPE_OBJECT_KEY = 1 25 | _TYPE_OBJECT_POST_KEY = 2 26 | _TYPE_OBJECT_VALUE = 3 27 | _TYPE_OBJECT_POST_VALUE = 4 28 | _TYPE_ARRAY = 5 29 | _TYPE_ARRAY_POST_VALUE = 6 30 | _TYPE_STRING = 7 31 | _TYPE_NUMBER = 8 32 | _TYPE_TRUE = 9 33 | _TYPE_FALSE = 10 34 | _TYPE_NULL = 11 35 | 36 | _WHITESPACE = [' ', '\r', '\n', '\t'] 37 | _DIGITS = ['0', '1', '2', '3', '4', 38 | '5', '6', '7', '8', '9', '.', 'e', 'E', '-', '+'] 39 | 40 | 41 | def _require_next(result, element, expected_total): 42 | """We are parsing a literal. Require that the next character exactly 43 | match the next character in the literal.""" 44 | 45 | current = result[-1][1] 46 | expected_char = expected_total[len(current)] 47 | if element != expected_char: 48 | fail("unexpected '" + element + "' when reading: " + expected_total) 49 | 50 | result[-1][1] = result[-1][1] + element 51 | 52 | 53 | def _incorporate_value(result): 54 | """The top value of the stack is complete. Merge it into its 55 | parent.""" 56 | 57 | latest_value = result[-1][1] 58 | latest_type = result[-1][0] 59 | result.pop() 60 | 61 | if latest_type == _TYPE_TRUE: 62 | latest_value = True 63 | elif latest_type == _TYPE_FALSE: 64 | latest_value = False 65 | elif latest_type == _TYPE_NULL: 66 | latest_value = None 67 | elif latest_type == _TYPE_NUMBER: 68 | # Starlark does not support floating point numbers. We'll 69 | # just leave these as strings for now. 70 | # 71 | # We would like to do: latest_value = float(latest_value) 72 | pass 73 | 74 | if len(result) == 0: 75 | fail("value with no parent type") 76 | 77 | current_type = result[-1][0] 78 | 79 | if current_type == _TYPE_OBJECT_KEY: 80 | if len(result[-1]) != 2: 81 | fail("unexpected object length") 82 | result[-1].append(latest_value) 83 | result[-1][0] = _TYPE_OBJECT_POST_KEY 84 | elif current_type == _TYPE_OBJECT_VALUE: 85 | if len(result[-1]) != 3: 86 | fail("unexpected object length") 87 | this_obj = result[-1][1] 88 | this_obj[result[-1][2]] = latest_value 89 | result[-1].pop() 90 | result[-1][0] = _TYPE_OBJECT_POST_VALUE 91 | elif current_type == _TYPE_ARRAY: 92 | result[-1][1].append(latest_value) 93 | result[-1][0] = _TYPE_ARRAY_POST_VALUE 94 | else: 95 | fail("unexpected parent of value") 96 | 97 | 98 | def parse_json(text): 99 | """Given JSON formatted text, parse it into a python dictionary and 100 | return the result. The top level entity *must* be a JSON object. 101 | 102 | This is not very efficient, but it is just intended to be used 103 | within bazel repository rules for one time configuration. 104 | 105 | It just follows the BNF described at json.org 106 | """ 107 | 108 | begin = True 109 | 110 | # Yay. Starlark doesn't let us have classes or anything else 111 | # nice. So, this stack will be just a perl style list of lists of 112 | # lists of stuff. 113 | # 114 | # The stack describes the current parse tree: 115 | # [ parent, 116 | # child, 117 | # grandchild, 118 | # .... etc ... 119 | # 120 | # Each element is a list of the form: 121 | # [ TYPE, CURRENT_DATA ] + (maybe more things) 122 | # 123 | # The "maybe more things" is type specific: 124 | # _TYPE_OBJECT_POST_KEY/_TYPE_OBJECT_POST_VALUE: 125 | # Here the extra is the key string which has already been parsed. 126 | # _TYPE_STRING 127 | # If None is here, that means we are processing an escape 128 | # sequence. If the list is only 2 long, ([type, data]), then we 129 | # are not processing an escape. 130 | result_stack = [] 131 | 132 | for index in range(len(text)): 133 | element = text[index] 134 | if begin: 135 | # Skip until we get the first open brace. 136 | if element != '{': 137 | continue 138 | result_stack.append([_TYPE_OBJECT_KEY, {}]) 139 | begin = False 140 | continue 141 | 142 | current_type = result_stack[-1][0] 143 | 144 | if current_type == _TYPE_OBJECT_KEY: 145 | if element != '"': 146 | continue 147 | result_stack.append([_TYPE_STRING, ""]) 148 | continue 149 | elif current_type == _TYPE_OBJECT_POST_KEY: 150 | if element in _WHITESPACE: 151 | continue 152 | elif element == ':': 153 | result_stack[-1][0] = _TYPE_OBJECT_VALUE 154 | else: 155 | fail("unexpected value after key: " + element) 156 | elif current_type == _TYPE_STRING: 157 | if len(result_stack[-1]) > 2: 158 | # We have an outstanding escape backslash. For now, 159 | # we only support single escape sequences (no 160 | # unicode). 161 | result_stack[-1].pop() 162 | c = None 163 | if element == '"': 164 | c = '"' 165 | elif element == '\\': 166 | c = '\\' 167 | elif element == '/': 168 | c = '/' 169 | elif element == 'b': 170 | fail("starlark does not support \\b") 171 | elif element == 'f': 172 | fail("starlark does not support \\f") 173 | elif element == 'n': 174 | c = '\n' 175 | elif element == 'r': 176 | c = '\r' 177 | elif element == 't': 178 | c = '\t' 179 | elif element == 'u': 180 | fail("unicode is not supported") 181 | else: 182 | fail("unsupported escape: " + element) 183 | result_stack[-1][1] = result_stack[-1][1] + c 184 | else: 185 | if element == '"': 186 | # This ends our string, strings are always a part of a 187 | # parent. 188 | _incorporate_value(result_stack) 189 | elif element == '\\': 190 | result_stack[-1].append(None) 191 | else: 192 | result_stack[-1][1] = result_stack[-1][1] + element 193 | elif current_type == _TYPE_NUMBER: 194 | # Numbers are special, in that they can end directly with 195 | # another token. So our state machine is constructed that 196 | # if we are here, then the element *must* be a number 197 | # already. 198 | if element not in _DIGITS: 199 | fail("logic error") 200 | 201 | result_stack[-1][1] = result_stack[-1][1] + element 202 | 203 | # And then we look *ahead* to see if we should stop 204 | # processing the number. This way when we go through the 205 | # loop the next time, we can properly process the next 206 | # token. 207 | if text[index + 1] not in _DIGITS: 208 | # This ends our number. 209 | _incorporate_value(result_stack) 210 | elif current_type == _TYPE_TRUE: 211 | _require_next(result_stack, element, "true") 212 | if result_stack[-1][1] == "true": 213 | _incorporate_value(result_stack) 214 | elif current_type == _TYPE_FALSE: 215 | _require_next(result_stack, element, "false") 216 | if result_stack[-1][1] == "false": 217 | _incorporate_value(result_stack) 218 | elif current_type == _TYPE_NULL: 219 | _require_next(result_stack, element, "null") 220 | if result_stack[-1][1] == "null": 221 | _incorporate_value(result_stack) 222 | elif current_type == _TYPE_OBJECT_VALUE or current_type == _TYPE_ARRAY: 223 | # We are looking for the beginning of a new value. 224 | if element in _WHITESPACE: 225 | pass 226 | elif element == '"': 227 | result_stack.append([_TYPE_STRING, ""]) 228 | elif element == '[': 229 | result_stack.append([_TYPE_ARRAY, []]) 230 | elif element == '{': 231 | result_stack.append([_TYPE_OBJECT_KEY, {}]) 232 | elif element == 't': 233 | result_stack.append([_TYPE_TRUE, "t"]) 234 | elif element == 'f': 235 | result_stack.append([_TYPE_FALSE, "f"]) 236 | elif element == 'n': 237 | result_stack.append([_TYPE_NULL, "n"]) 238 | elif element in _DIGITS: 239 | result_stack.append([_TYPE_NUMBER, element]) 240 | # This might be the sole digit. 241 | if text[index + 1] not in _DIGITS: 242 | _incorporate_value(result_stack) 243 | elif element == ']' and current_type == _TYPE_ARRAY: 244 | _incorporate_value(result_stack) 245 | else: 246 | fail("Unexpected character: " + element) 247 | elif current_type == _TYPE_OBJECT_POST_VALUE: 248 | if element in _WHITESPACE: 249 | pass 250 | elif element == '}': 251 | if len(result_stack) == 1: 252 | # We're done! 253 | return result_stack[0][1] 254 | _incorporate_value(result_stack) 255 | elif element == ',': 256 | result_stack[-1][0] = _TYPE_OBJECT_KEY 257 | else: 258 | fail("Unexpected character: " + element) 259 | elif current_type == _TYPE_ARRAY_POST_VALUE: 260 | if element in _WHITESPACE: 261 | pass 262 | elif element == ']': 263 | _incorporate_value(result_stack) 264 | elif element == ',': 265 | result_stack[-1][0] = _TYPE_ARRAY 266 | else: 267 | fail("Unexpected character: " + element) 268 | -------------------------------------------------------------------------------- /tools/workspace/mbed/repository.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | 3 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | load("@bazel_tools//tools/build_defs/repo:utils.bzl", "patch") 18 | load("//tools/workspace/mbed:json.bzl", "parse_json") 19 | 20 | 21 | DEFAULT_CONFIG = { 22 | "CLOCK_SOURCE": "USE_PLL_HSE_EXTC|USE_PLL_HSI", 23 | "LPTICKER_DELAY_TICKS": "1", 24 | "MBED_CONF_DRIVERS_UART_SERIAL_RXBUF_SIZE": "256", 25 | "MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE": "256", 26 | "MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION": "1", 27 | "MBED_CONF_EVENTS_SHARED_EVENTSIZE": "256", 28 | "MBED_CONF_EVENTS_SHARED_HIGHPRIO_EVENTSIZE": "256", 29 | "MBED_CONF_EVENTS_SHARED_HIGHPRIO_STACKSIZE": "1024", 30 | "MBED_CONF_EVENTS_SHARED_STACKSIZE": "1024", 31 | "MBED_CONF_EVENTS_USE_LOWPOWER_TIMER_TICKER": "0", 32 | "MBED_CONF_PLATFORM_CTHUNK_COUNT_MAX": "4", 33 | "MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE": "9600", 34 | "MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO": "0", 35 | "MBED_CONF_PLATFORM_ERROR_DECODE_HTTP_URL_STR": r'"%d"', 36 | "MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED": "0", 37 | "MBED_CONF_PLATFORM_ERROR_HIST_ENABLED": "0", 38 | "MBED_CONF_PLATFORM_ERROR_HIST_SIZE": "4", 39 | "MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR": "0", 40 | "MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN": "16", 41 | "MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER": "0", 42 | "MBED_CONF_PLATFORM_STDIO_BAUD_RATE": "9600", 43 | "MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL": "0", 44 | "MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES": "0", 45 | "MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT": "1", 46 | "MBED_CONF_RTOS_IDLE_THREAD_STACK_SIZE": "512", 47 | "MBED_CONF_RTOS_MAIN_THREAD_STACK_SIZE": "4096", 48 | "MBED_CONF_RTOS_PRESENT" : "1", 49 | "MBED_CONF_RTOS_THREAD_STACK_SIZE": "4096", 50 | "MBED_CONF_RTOS_TIMER_THREAD_STACK_SIZE": "768", 51 | "MBED_CONF_TARGET_LPUART_CLOCK_SOURCE": "USE_LPUART_CLK_LSE|USE_LPUART_CLK_PCLK1", 52 | "MBED_CONF_TARGET_LSE_AVAILABLE": "1", 53 | "MEM_ALLOC": "malloc", 54 | "MEM_FREE": "free", 55 | } 56 | 57 | 58 | def _escape(item): 59 | return item.replace('"', r'\\\"') 60 | 61 | 62 | def _render_list(data): 63 | result = "[\n" 64 | for item in data: 65 | result += ' "{}",\n'.format(_escape(item)) 66 | result += "]\n" 67 | return result 68 | 69 | 70 | def _get_target_defines(repository_ctx, target_path): 71 | target_name = target_path.rsplit('/', 1)[1] 72 | if not target_name.startswith("TARGET_"): 73 | fail("Final target directory does not start with TARGET_") 74 | 75 | first_target = target_name.split("TARGET_")[1] 76 | 77 | 78 | targets_results = repository_ctx.execute(["cat", "targets/targets.json"]) 79 | if targets_results.return_code != 0: 80 | fail("error reading targets.json") 81 | 82 | targets = parse_json(targets_results.stdout) 83 | 84 | to_query = [first_target] 85 | 86 | # This aggregation would be natural to do recursively. However, 87 | # Starlark of course does not support that. Thus, we'll just 88 | # emulate the recursion with a local stack that we collapse at the 89 | # end. 90 | 91 | # Contains length 2 lists, where the first element are things to 92 | # add, and the second element are things to remove. 93 | stack = [] 94 | 95 | for i in range(100): 96 | if len(to_query) == 0: 97 | break 98 | 99 | target = to_query[0] 100 | to_query = to_query[1:] 101 | 102 | if target not in targets: 103 | fail("Could not find '{}' in targets.json".format(target)) 104 | 105 | stack = stack + [[[], []]] 106 | this_stack = stack[-1] 107 | 108 | this_stack[0] += ["TARGET_{}".format(target)] 109 | 110 | item = targets[target] 111 | 112 | this_stack[0] += ["DEVICE_{}".format(x) for x in item.get("device_has", [])] 113 | this_stack[0] += ["DEVICE_{}".format(x) for x in item.get("device_has_add", [])] 114 | this_stack[1] += ["DEVICE_{}".format(x) for x in item.get("device_has_remove", [])] 115 | 116 | this_stack[0] += ["TARGET_{}".format(x) for x in item.get("extra_labels", [])] 117 | this_stack[0] += ["TARGET_{}".format(x) for x in item.get("extra_labels_add", [])] 118 | this_stack[1] += ["TARGET_{}".format(x) for x in item.get("extra_labels_remove", [])] 119 | 120 | if "device_name" in item: 121 | this_stack[0] += ["TARGET_{}".format(item["device_name"])] 122 | 123 | if "core" in item: 124 | core = item.get("core") 125 | if core == 'Cortex-M4F' or core == 'Cortex-M4': 126 | this_stack[0] += [ 127 | "ARM_MATH_CM4", 128 | "__CORTEX_M4", 129 | "TARGET_RTOS_M4_M7", 130 | "TARGET_LIKE_CORTEX_M4", 131 | "TARGET_M4", 132 | "TARGET_CORTEX_M", 133 | "TARGET_CORTEX", 134 | ] 135 | elif core == 'Cortex-M0': 136 | this_stack[0] += [ 137 | "ARM_MATH_CM0", 138 | "__CORTEX_M0", 139 | "TARGET_LIKE_CORTEX_M0", 140 | "TARGET_M0", 141 | "TARGET_CORTEX_M", 142 | "TARGET_CORTEX", 143 | ] 144 | elif core != None: 145 | fail("Unknown core:" + core) 146 | 147 | 148 | this_stack[0] += item.get("macros", []) 149 | this_stack[0] += item.get("macros_add", []) 150 | this_stack[1] += item.get("macros_remove", []) 151 | 152 | this_stack[0] += ["TARGET_FF_{}".format(x) for x in item.get("supported_form_factors", [])] 153 | 154 | to_query += item.get("inherits", []) 155 | 156 | result = {} 157 | for to_add, to_remove in reversed(stack): 158 | for item in to_add: 159 | result[item] = None 160 | for item in to_remove: 161 | result.pop(item) 162 | 163 | # I have no clue what this is, but we don't support it. 164 | if "TARGET_PSA" in result: 165 | result.pop("TARGET_PSA") 166 | 167 | return sorted(result.keys()) 168 | 169 | 170 | def _impl(repository_ctx): 171 | PREFIX = "external/{}".format(repository_ctx.name) 172 | 173 | repository_ctx.download_and_extract( 174 | url = [ 175 | "https://github.com/ARMmbed/mbed-os/archive/mbed-os-5.13.4.tar.gz", 176 | ], 177 | sha256 = "5c291c1df779834224437043e2274bd1b54216b01e145c1754ac6cd8890cb12e", 178 | stripPrefix = "mbed-os-mbed-os-5.13.4", 179 | ) 180 | patch(repository_ctx) 181 | 182 | 183 | my_config = {} 184 | # It is annoying that bazel does not give us full featured dicts. 185 | for key, value in DEFAULT_CONFIG.items(): 186 | my_config[key] = value 187 | for key, value in repository_ctx.attr.config.items(): 188 | my_config[key] = value 189 | 190 | 191 | # Since mbed is full of circular dependencies, we just construct 192 | # the full set of headers and sources here, then pass it down into 193 | # the BUILD file verbatim for using in a single bazel label. 194 | 195 | target = repository_ctx.attr.target 196 | 197 | defines = ["{}={}".format(key, value) 198 | for key, value in my_config.items() 199 | if value != "0"] 200 | 201 | defines += _get_target_defines(repository_ctx, target) 202 | 203 | for key, value in my_config.items(): 204 | if value != "0": 205 | continue 206 | 207 | if key in defines: 208 | defines.remove(key) 209 | 210 | 211 | hdr_globs = [ 212 | "mbed.h", 213 | "platform/**/*.h", 214 | "drivers/*.h", 215 | "cmsis/*.h", 216 | "cmsis/TARGET_CORTEX_M/*.h", 217 | "events/*.h", 218 | "events/equeue/*.h", 219 | "hal/*.h", 220 | ] 221 | 222 | enable_rtos = int(my_config["MBED_CONF_RTOS_PRESENT"]) != 0 223 | 224 | if enable_rtos: 225 | hdr_globs += [ 226 | "rtos/*.h", 227 | "rtos/TARGET_CORTEX/**/*.h", 228 | ] 229 | 230 | src_globs = [ 231 | "platform/**/*.c", 232 | "platform/**/*.cpp", 233 | "drivers/*.cpp", 234 | "cmsis/TARGET_CORTEX_M/*.c", 235 | "hal/*.c", 236 | "hal/*.cpp", 237 | ] 238 | 239 | if enable_rtos: 240 | src_globs += [ 241 | "events/*.cpp", 242 | "events/equeue/equeue.c", 243 | "events/equeue/equeue_mbed.cpp", 244 | "rtos/TARGET_CORTEX/*.c", 245 | "rtos/TARGET_CORTEX/*.cpp", 246 | "rtos/TARGET_CORTEX/rtx5/RTX/Source/*.c", 247 | "rtos/TARGET_CORTEX/rtx5/Source/*.c", 248 | "rtos/TARGET_CORTEX/TOOLCHAIN_GCC_ARM/*.c", 249 | "rtos/*.cpp", 250 | ] 251 | if "TARGET_M4" in defines: 252 | src_globs += [ 253 | "rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M4_M7/*.S", 254 | ] 255 | elif "TARGET_M0" in defines: 256 | src_globs += [ 257 | "rtos/TARGET_CORTEX/rtx5/RTX/Source/TOOLCHAIN_GCC/TARGET_RTOS_M0/*.S", 258 | ] 259 | else: 260 | fail("Unknown core") 261 | 262 | 263 | includes = [ 264 | ".", 265 | "platform", 266 | "drivers", 267 | "cmsis/TARGET_CORTEX_M", 268 | "cmsis".format(PREFIX), 269 | "hal".format(PREFIX), 270 | ] 271 | 272 | if enable_rtos: 273 | includes += [ 274 | "events", 275 | "rtos".format(PREFIX), 276 | "rtos/TARGET_CORTEX", 277 | "rtos/TARGET_CORTEX/rtx4", 278 | "rtos/TARGET_CORTEX/rtx5/Include", 279 | "rtos/TARGET_CORTEX/rtx5/Source", 280 | "rtos/TARGET_CORTEX/rtx5/RTX/Include", 281 | "rtos/TARGET_CORTEX/rtx5/RTX/Source", 282 | "rtos/TARGET_CORTEX/rtx5/RTX/Config", 283 | ] 284 | 285 | copts = [ 286 | "-Wno-unused-parameter", 287 | "-Wno-missing-field-initializers", 288 | "-Wno-register", 289 | "-Wno-deprecated-declarations", 290 | "-Wno-sized-deallocation", 291 | "-Wno-shift-negative-value", 292 | ] 293 | 294 | linker_script = "" 295 | 296 | # Walk up the target path adding directories as we go. 297 | remaining_target = target 298 | 299 | # This would naturally be expressed as a 'while' loop. Instead 300 | # we'll just encode a maximum size that is way more than enough. 301 | # Go Starlark. 302 | for i in range(1000): 303 | hdr_globs += [ 304 | "{}/*.h".format(remaining_target), 305 | "{}/device/*.h".format(remaining_target), 306 | ] 307 | src_globs += [ 308 | "{}/*.c".format(remaining_target), 309 | "{}/*.cpp".format(remaining_target), 310 | "{}/device/*.c".format(remaining_target), 311 | "{}/device/TOOLCHAIN_GCC_ARM/*.S".format(remaining_target), 312 | ] 313 | includes += [ 314 | remaining_target, 315 | "{}/device".format(remaining_target), 316 | ] 317 | 318 | # Does this directory contain the linker script? 319 | 320 | linker_search_path = "{}/device/TOOLCHAIN_GCC_ARM/".format(remaining_target) 321 | find_result = repository_ctx.execute(["find", linker_search_path, '-name', '*.ld']) 322 | if find_result.return_code == 0 and len(find_result.stdout) > 0: 323 | linker_script = find_result.stdout.strip() 324 | 325 | items = remaining_target.rsplit('/', 1) 326 | if len(items) == 1: 327 | break 328 | 329 | remaining_target = items[0] 330 | 331 | if linker_script == "": 332 | fail("Could not find linker script") 333 | 334 | 335 | substitutions = { 336 | '@HDR_GLOBS@': _render_list(hdr_globs), 337 | '@SRC_GLOBS@': _render_list(src_globs), 338 | '@INCLUDES@': _render_list(includes), 339 | '@COPTS@': _render_list(copts), 340 | '@DEFINES@': _render_list(defines), 341 | } 342 | 343 | repository_ctx.template( 344 | 'rules.bzl', 345 | repository_ctx.attr.rules_file, 346 | ) 347 | 348 | repository_ctx.template( 349 | 'BUILD', 350 | repository_ctx.attr.build_file_template, 351 | substitutions = substitutions, 352 | ) 353 | 354 | repository_ctx.symlink(linker_script, "linker_script.ld.in") 355 | 356 | _mbed_repository = repository_rule( 357 | implementation = _impl, 358 | attrs = { 359 | "build_file_template" : attr.label(allow_single_file = True), 360 | "rules_file" : attr.label(allow_single_file = True), 361 | "target" : attr.string(), 362 | "config" : attr.string_dict(), 363 | "patches": attr.label_list(default = []), 364 | "patch_tool": attr.string(default = "patch"), 365 | "patch_args": attr.string_list(default = ["-p0"]), 366 | "patch_cmds": attr.string_list(default = []), 367 | } 368 | ) 369 | 370 | def mbed_repository( 371 | name, 372 | target, 373 | config = None): 374 | 375 | _mbed_repository( 376 | name = name, 377 | build_file_template = Label("//tools/workspace/mbed:package.BUILD"), 378 | rules_file = Label("//tools/workspace/mbed:rules.bzl"), 379 | target = target, 380 | config = config or DEFAULT_CONFIG, 381 | patches = [ 382 | Label("//tools/workspace/mbed:mbed.patch"), 383 | Label("//tools/workspace/mbed:stm32g4.patch"), 384 | ], 385 | patch_args = ["-p1"], 386 | ) 387 | -------------------------------------------------------------------------------- /tools/cc_toolchain/cc_toolchain_config.bzl: -------------------------------------------------------------------------------- 1 | # -*- python -*- 2 | # Copyright 2023 mjbots Robotic Systems, LLC. info@mjbots.com 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | load( 17 | "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", 18 | "action_config", 19 | "env_entry", 20 | "env_set", 21 | "feature", 22 | "feature_set", 23 | "flag_group", 24 | "flag_set", 25 | "tool", 26 | "tool_path", 27 | "variable_with_value", 28 | "with_feature_set", 29 | ) 30 | 31 | load( 32 | "@bazel_tools//tools/build_defs/cc:action_names.bzl", 33 | "ASSEMBLE_ACTION_NAME", 34 | "CC_FLAGS_MAKE_VARIABLE_ACTION_NAME", 35 | "CLIF_MATCH_ACTION_NAME", 36 | "CPP_COMPILE_ACTION_NAME", 37 | "CPP_HEADER_PARSING_ACTION_NAME", 38 | "CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME", 39 | "CPP_LINK_EXECUTABLE_ACTION_NAME", 40 | "CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME", 41 | "CPP_LINK_STATIC_LIBRARY_ACTION_NAME", 42 | "CPP_MODULE_CODEGEN_ACTION_NAME", 43 | "CPP_MODULE_COMPILE_ACTION_NAME", 44 | "C_COMPILE_ACTION_NAME", 45 | "LINKSTAMP_COMPILE_ACTION_NAME", 46 | "LTO_BACKEND_ACTION_NAME", 47 | "LTO_INDEXING_ACTION_NAME", 48 | "PREPROCESS_ASSEMBLE_ACTION_NAME", 49 | "STRIP_ACTION_NAME", 50 | ) 51 | 52 | ACTION_NAMES = struct( 53 | c_compile = C_COMPILE_ACTION_NAME, 54 | cpp_compile = CPP_COMPILE_ACTION_NAME, 55 | linkstamp_compile = LINKSTAMP_COMPILE_ACTION_NAME, 56 | cc_flags_make_variable = CC_FLAGS_MAKE_VARIABLE_ACTION_NAME, 57 | cpp_module_codegen = CPP_MODULE_CODEGEN_ACTION_NAME, 58 | cpp_header_parsing = CPP_HEADER_PARSING_ACTION_NAME, 59 | cpp_module_compile = CPP_MODULE_COMPILE_ACTION_NAME, 60 | assemble = ASSEMBLE_ACTION_NAME, 61 | preprocess_assemble = PREPROCESS_ASSEMBLE_ACTION_NAME, 62 | lto_indexing = LTO_INDEXING_ACTION_NAME, 63 | lto_backend = LTO_BACKEND_ACTION_NAME, 64 | cpp_link_executable = CPP_LINK_EXECUTABLE_ACTION_NAME, 65 | cpp_link_dynamic_library = CPP_LINK_DYNAMIC_LIBRARY_ACTION_NAME, 66 | cpp_link_nodeps_dynamic_library = CPP_LINK_NODEPS_DYNAMIC_LIBRARY_ACTION_NAME, 67 | cpp_link_static_library = CPP_LINK_STATIC_LIBRARY_ACTION_NAME, 68 | strip = STRIP_ACTION_NAME, 69 | clif_match = CLIF_MATCH_ACTION_NAME, 70 | objcopy_embed_data = "objcopy_embed_data", 71 | ld_embed_data = "ld_embed_data", 72 | ) 73 | 74 | ALL_COMPILE_ACTIONS = [ 75 | ACTION_NAMES.c_compile, 76 | ACTION_NAMES.cpp_compile, 77 | ACTION_NAMES.linkstamp_compile, 78 | ACTION_NAMES.cc_flags_make_variable, 79 | ACTION_NAMES.cpp_module_codegen, 80 | ACTION_NAMES.cpp_header_parsing, 81 | ACTION_NAMES.cpp_module_compile, 82 | ACTION_NAMES.assemble, 83 | ACTION_NAMES.preprocess_assemble, 84 | ACTION_NAMES.lto_indexing, 85 | ACTION_NAMES.lto_backend, 86 | ACTION_NAMES.strip, 87 | ACTION_NAMES.clif_match, 88 | ] 89 | 90 | ALL_LINK_ACTIONS = [ 91 | ACTION_NAMES.cpp_link_executable, 92 | ACTION_NAMES.cpp_link_dynamic_library, 93 | ACTION_NAMES.cpp_link_nodeps_dynamic_library, 94 | ] 95 | 96 | ALL_CPP_ACTIONS = [ 97 | ACTION_NAMES.cpp_compile, 98 | ACTION_NAMES.cpp_module_codegen, 99 | ACTION_NAMES.cpp_header_parsing, 100 | ACTION_NAMES.cpp_module_compile, 101 | ACTION_NAMES.cpp_link_executable, 102 | ACTION_NAMES.cpp_link_dynamic_library, 103 | ACTION_NAMES.cpp_link_nodeps_dynamic_library, 104 | ] 105 | 106 | def _make_common_features(ctx): 107 | result = {} 108 | 109 | result['static_link_cpp_runtimes'] = feature( 110 | name = "static_link_cpp_runtimes", 111 | implies = ["no-unused-command-line-argument"]) 112 | 113 | result['unfiltered_compile_flags_feature'] = feature( 114 | name = "unfiltered_compile_flags", 115 | flag_sets = ([ 116 | flag_set( 117 | actions = [ 118 | ACTION_NAMES.preprocess_assemble, 119 | ACTION_NAMES.c_compile, 120 | ACTION_NAMES.cpp_compile, 121 | ACTION_NAMES.cpp_header_parsing, 122 | ACTION_NAMES.cpp_module_compile, 123 | ACTION_NAMES.cpp_module_codegen, 124 | ], 125 | flag_groups = [ 126 | flag_group( 127 | flags = ctx.attr.host_unfiltered_compile_flags, 128 | ), 129 | ], 130 | ), 131 | ] if ctx.attr.host_unfiltered_compile_flags else []), 132 | ) 133 | 134 | result['determinism_feature'] = feature( 135 | name = "determinism", 136 | flag_sets = [ 137 | flag_set( 138 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 139 | flag_groups = [ 140 | flag_group( 141 | flags = [ 142 | "-Wno-builtin-macro-redefined", 143 | "-D__DATE__=\"redacted\"", 144 | "-D__TIMESTAMP__=\"redacted\"", 145 | "-D__TIME__=\"redacted\"", 146 | ], 147 | ), 148 | ], 149 | ), 150 | ], 151 | ) 152 | 153 | result['hardening_feature'] = feature( 154 | name = "hardening", 155 | flag_sets = [ 156 | flag_set( 157 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 158 | flag_groups = [ 159 | flag_group( 160 | flags = [ 161 | "-U_FORTIFY_SOURCE", 162 | "-D_FORTIFY_SOURCE=1", 163 | ], 164 | ), 165 | ], 166 | ), 167 | flag_set( 168 | actions = [ 169 | ACTION_NAMES.cpp_link_dynamic_library, 170 | ACTION_NAMES.cpp_link_nodeps_dynamic_library, 171 | ], 172 | flag_groups = [flag_group(flags = ["-Wl,-z,relro,-z,now"])], 173 | ), 174 | flag_set( 175 | actions = [ACTION_NAMES.cpp_link_executable], 176 | flag_groups = [flag_group(flags = ["-Wl,-z,relro,-z,now"])], 177 | ), 178 | ], 179 | ) 180 | 181 | result['supports_dynamic_linker_feature'] = feature( 182 | name = "supports_dynamic_linker", enabled = True) 183 | 184 | result['warnings_feature'] = feature( 185 | name = "warnings", 186 | flag_sets = [ 187 | flag_set( 188 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 189 | flag_groups = [ 190 | flag_group( 191 | flags = ["-Wall", "-Wextra", "-Wvla"] + ctx.attr.host_compiler_warnings, 192 | ), 193 | ], 194 | ), 195 | ], 196 | ) 197 | 198 | result['dbg_feature'] = feature( 199 | name = "dbg", 200 | flag_sets = [ 201 | flag_set( 202 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 203 | flag_groups = [flag_group(flags = [ 204 | "-O0", 205 | "-g3", 206 | ])], 207 | ), 208 | ], 209 | implies = ["common"], 210 | ) 211 | 212 | result['disable_assertions_feature'] = feature( 213 | name = "disable-assertions", 214 | flag_sets = [ 215 | flag_set( 216 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 217 | flag_groups = [flag_group(flags = ["-DNDEBUG"])], 218 | ), 219 | ], 220 | ) 221 | 222 | result['fastbuild_feature'] = feature(name = "fastbuild", implies = ["dbg"]) 223 | 224 | result['user_compile_flags_feature'] = feature( 225 | name = "user_compile_flags", 226 | flag_sets = [ 227 | flag_set( 228 | actions = [ 229 | ACTION_NAMES.preprocess_assemble, 230 | ACTION_NAMES.c_compile, 231 | ACTION_NAMES.cpp_compile, 232 | ACTION_NAMES.cpp_header_parsing, 233 | ACTION_NAMES.cpp_module_compile, 234 | ACTION_NAMES.cpp_module_codegen, 235 | ], 236 | flag_groups = [ 237 | flag_group( 238 | flags = ["%{user_compile_flags}"], 239 | iterate_over = "user_compile_flags", 240 | expand_if_available = "user_compile_flags", 241 | ), 242 | ], 243 | ), 244 | ], 245 | ) 246 | 247 | result['frame_pointer_feature'] = feature( 248 | name = "frame-pointer", 249 | flag_sets = [ 250 | flag_set( 251 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 252 | flag_groups = [flag_group(flags = ["-fno-omit-frame-pointer"])], 253 | ), 254 | ], 255 | ) 256 | 257 | result['build_id_feature'] = feature( 258 | name = "build-id", 259 | flag_sets = [ 260 | flag_set( 261 | actions = ALL_LINK_ACTIONS, 262 | flag_groups = [ 263 | flag_group( 264 | flags = ["-Wl,--build-id=md5", "-Wl,--hash-style=gnu"], 265 | ), 266 | ], 267 | ), 268 | ], 269 | ) 270 | 271 | result['no_stripping_feature'] = feature(name = "no_stripping") 272 | 273 | result['no_canonical_prefixes_feature'] = feature( 274 | name = "no-canonical-prefixes", 275 | flag_sets = [ 276 | flag_set( 277 | actions = [ 278 | ACTION_NAMES.c_compile, 279 | ACTION_NAMES.cpp_compile, 280 | ], 281 | flag_groups = [ 282 | flag_group( 283 | flags = [ 284 | "-no-canonical-prefixes", 285 | ] + ctx.attr.extra_no_canonical_prefixes_flags, 286 | ), 287 | ], 288 | ), 289 | ], 290 | ) 291 | 292 | result['no_canonical_system_headers'] = feature( 293 | name = "no-canonical-system-headers", 294 | flag_sets = [ 295 | flag_set( 296 | actions = [ 297 | ACTION_NAMES.c_compile, 298 | ACTION_NAMES.cpp_compile, 299 | ], 300 | flag_groups = [ 301 | flag_group( 302 | flags = [ 303 | "-fno-canonical-system-headers", 304 | ], 305 | ), 306 | ], 307 | ), 308 | ], 309 | ) 310 | 311 | result['has_configured_linker_path_feature'] = feature(name = "has_configured_linker_path") 312 | 313 | result['copy_dynamic_libraries_to_binary_feature'] = feature(name = "copy_dynamic_libraries_to_binary") 314 | 315 | result['user_link_flags_feature'] = feature( 316 | name = "user_link_flags", 317 | flag_sets = [ 318 | flag_set( 319 | actions = ALL_LINK_ACTIONS, 320 | flag_groups = [ 321 | flag_group( 322 | flags = ["%{user_link_flags}"], 323 | iterate_over = "user_link_flags", 324 | expand_if_available = "user_link_flags", 325 | ), 326 | ], 327 | ), 328 | ], 329 | ) 330 | 331 | result['cpp17_feature'] = feature( 332 | name = "c++17", 333 | flag_sets = [ 334 | flag_set( 335 | actions = ALL_CPP_ACTIONS, 336 | flag_groups = [flag_group(flags = ["-std=c++17"])], 337 | ), 338 | ], 339 | ) 340 | 341 | result['cpp20_feature'] = feature( 342 | name = "c++20", 343 | flag_sets = [ 344 | flag_set( 345 | actions = ALL_CPP_ACTIONS, 346 | flag_groups = [flag_group(flags = ["-std=c++2a"])], 347 | ), 348 | ], 349 | ) 350 | 351 | result['no-rtti'] = feature( 352 | name = "no-rtti", 353 | flag_sets = [ 354 | flag_set( 355 | actions = ALL_CPP_ACTIONS, 356 | flag_groups = [flag_group(flags = ["-fno-rtti"])], 357 | ), 358 | ], 359 | ) 360 | 361 | result['no-exceptions'] = feature( 362 | name = "no-exceptions", 363 | flag_sets = [ 364 | flag_set( 365 | actions = ALL_CPP_ACTIONS, 366 | flag_groups = [flag_group(flags = ["-fno-exceptions"])], 367 | ), 368 | ], 369 | ) 370 | 371 | result['no-unused-command-line-argument'] = feature( 372 | name = "no-unused-command-line-argument", 373 | flag_sets = [ 374 | flag_set( 375 | actions = ALL_COMPILE_ACTIONS + ALL_LINK_ACTIONS, 376 | flag_groups = [flag_group(flags = ["-Wno-unused-command-line-argument"])], 377 | ), 378 | ], 379 | ) 380 | 381 | return result 382 | 383 | def _stm32_impl(ctx): 384 | host_system_name = "k8" 385 | 386 | action_configs = [] 387 | 388 | common = _make_common_features(ctx) 389 | 390 | stdlib_feature = feature( 391 | name = "stdlib", 392 | flag_sets = [ 393 | flag_set( 394 | actions = ALL_LINK_ACTIONS, 395 | flag_groups = [flag_group(flags = [ 396 | "-Wl,--start-group", 397 | "-lstdc++", 398 | "-lsupc++", 399 | "-lm", 400 | "-lc", 401 | "-lgcc", 402 | "-lnosys", 403 | "-Wl,--end-group", 404 | ])], 405 | ), 406 | ], 407 | ) 408 | 409 | speedopt_feature = feature( 410 | name = "speedopt", 411 | flag_sets = [ 412 | flag_set( 413 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 414 | flag_groups = [ 415 | flag_group( 416 | flags = ["-O3"], 417 | ), 418 | ], 419 | ), 420 | ], 421 | ) 422 | 423 | sizeopt_feature = feature( 424 | name = "sizeopt", 425 | flag_sets = [ 426 | flag_set( 427 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 428 | flag_groups = [ 429 | flag_group( 430 | flags = ["-Os"], 431 | ), 432 | ], 433 | with_features = [ 434 | with_feature_set( 435 | not_features = ['speedopt'], 436 | ), 437 | ], 438 | ), 439 | ], 440 | ) 441 | 442 | noimplicitfunction_feature = feature( 443 | name = "noimplicitfunction", 444 | flag_sets = [ 445 | flag_set( 446 | actions = [ACTION_NAMES.c_compile], 447 | flag_groups = [ 448 | flag_group( 449 | flags = ["-Wno-implicit-function-declaration"], 450 | ), 451 | ], 452 | ), 453 | ], 454 | ) 455 | 456 | nostdlib_feature = feature( 457 | name = "nostdlib", 458 | flag_sets = [ 459 | flag_set( 460 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 461 | flag_groups = [ 462 | flag_group( 463 | flags = ["-nostdlib"], 464 | ), 465 | ], 466 | ), 467 | ], 468 | ) 469 | 470 | novolatileerror_feature = feature( 471 | name = "novolatileerror", 472 | flag_sets = [ 473 | flag_set( 474 | actions = [ACTION_NAMES.cpp_compile], 475 | flag_groups = [ 476 | flag_group( 477 | flags = ["-Wno-volatile"], 478 | ), 479 | ], 480 | ), 481 | ], 482 | ) 483 | 484 | notypelimits_feature = feature( 485 | name = "no-type-limits", 486 | flag_sets = [ 487 | flag_set( 488 | actions = [ACTION_NAMES.cpp_compile], 489 | flag_groups = [ 490 | flag_group( 491 | flags = ["-Wno-type-limits"], 492 | ), 493 | ], 494 | ), 495 | ], 496 | ) 497 | 498 | nomaybe_uninitialized_feature = feature( 499 | name = "nomaybe_uninitialized", 500 | flag_sets = [ 501 | flag_set( 502 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 503 | flag_groups = [ 504 | flag_group( 505 | flags = ["-Wno-error=maybe-uninitialized"], 506 | ), 507 | ], 508 | ), 509 | ], 510 | ) 511 | 512 | opt_feature = feature( 513 | name = "opt", 514 | flag_sets = [ 515 | flag_set( 516 | actions = [ACTION_NAMES.c_compile, ACTION_NAMES.cpp_compile], 517 | flag_groups = [ 518 | flag_group( 519 | flags = ["-g", 520 | "-ffunction-sections", 521 | "-fdata-sections"], 522 | ), 523 | ], 524 | ), 525 | flag_set( 526 | actions = [ 527 | ACTION_NAMES.cpp_link_dynamic_library, 528 | ACTION_NAMES.cpp_link_nodeps_dynamic_library, 529 | ACTION_NAMES.cpp_link_executable, 530 | ], 531 | flag_groups = [flag_group(flags = ["-Wl,--gc-sections"])], 532 | ), 533 | ], 534 | implies = ["common", "sizeopt"], 535 | ) 536 | 537 | nanospecs_feature = feature( 538 | name = "nanospecs", 539 | flag_sets = [ 540 | flag_set( 541 | actions = ALL_LINK_ACTIONS, 542 | flag_groups = [flag_group(flags= [ 543 | "--specs=nano.specs", 544 | "--specs=nosys.specs", 545 | ])], 546 | ), 547 | ], 548 | ) 549 | 550 | stm32_feature = feature( 551 | name = "stm32", 552 | flag_sets = [ 553 | flag_set( 554 | actions = ALL_COMPILE_ACTIONS + ALL_LINK_ACTIONS, 555 | flag_groups = [flag_group(flags= [ 556 | "-mthumb", 557 | "-mfloat-abi=softfp", 558 | ])], 559 | ), 560 | ], 561 | implies = [ 562 | "no-canonical-system-headers", 563 | "no-rtti", 564 | "no-exceptions", 565 | ], 566 | ) 567 | 568 | stm32f0_feature = feature( 569 | name = "stm32f0", 570 | flag_sets = [ 571 | flag_set( 572 | actions = ALL_COMPILE_ACTIONS + ALL_LINK_ACTIONS, 573 | flag_groups = [flag_group(flags = [ 574 | "-mcpu=cortex-m0", 575 | ])], 576 | ), 577 | ], 578 | implies = ["stm32"], 579 | ) 580 | 581 | stm32f4_feature = feature( 582 | name = "stm32f4", 583 | flag_sets = [ 584 | flag_set( 585 | actions = ALL_COMPILE_ACTIONS + ALL_LINK_ACTIONS, 586 | flag_groups = [flag_group(flags = [ 587 | "-mcpu=cortex-m4", 588 | "-mfpu=fpv4-sp-d16", 589 | ])], 590 | ), 591 | ], 592 | implies = ["stm32"], 593 | ) 594 | 595 | stm32g4_feature = feature( 596 | name = "stm32g4", 597 | flag_sets = [ 598 | flag_set( 599 | actions = ALL_COMPILE_ACTIONS + ALL_LINK_ACTIONS, 600 | flag_groups = [flag_group(flags = [ 601 | "-mcpu=cortex-m4", 602 | "-mfpu=fpv4-sp-d16", 603 | ])], 604 | ), 605 | ], 606 | implies = ["stm32"], 607 | ) 608 | 609 | common_feature = feature( 610 | name = "common", 611 | implies = [ 612 | "stdlib", 613 | "c++20", 614 | "determinism", 615 | "warnings", 616 | "no-canonical-prefixes", 617 | "novolatileerror", 618 | "no-type-limits", 619 | ] + (["stm32f0"] if ctx.attr.cpu == "stm32f0" else []) + ( 620 | ["stm32f4"] if ctx.attr.cpu == "stm32f4" else []) + ( 621 | ["stm32g4"] if ctx.attr.cpu == "stm32g4" else []) 622 | ) 623 | 624 | features = common.values() + [ 625 | speedopt_feature, 626 | sizeopt_feature, 627 | opt_feature, 628 | nomaybe_uninitialized_feature, 629 | noimplicitfunction_feature, 630 | novolatileerror_feature, 631 | notypelimits_feature, 632 | stdlib_feature, 633 | common_feature, 634 | stm32_feature, 635 | stm32f0_feature, 636 | stm32f4_feature, 637 | stm32g4_feature, 638 | nanospecs_feature, 639 | nostdlib_feature, 640 | ] 641 | 642 | cxx_builtin_include_directories = ctx.attr.builtin_include_directories 643 | 644 | tool_paths = [ 645 | tool_path(name = "gcc", path = ctx.attr.host_compiler_path), 646 | tool_path(name = "ar", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-ar"), 647 | tool_path(name = "compat-ld", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-ld"), 648 | tool_path(name = "cpp", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-cpp"), 649 | # tool_path(name = "dwp", path = ctx.attr.host_compiler_prefix + "/clang-dwp"), 650 | tool_path(name = "gcov", path = "/arm-none-eabi-gcov"), 651 | tool_path(name = "ld", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-ld"), 652 | tool_path(name = "nm", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-nm"), 653 | tool_path(name = "objcopy", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-objcopy"), 654 | tool_path(name = "objdump", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-objdump"), 655 | tool_path(name = "strip", path = ctx.attr.host_compiler_prefix + "/arm-none-eabi-strip"), 656 | ] 657 | 658 | out = ctx.actions.declare_file(ctx.label.name) 659 | ctx.actions.write(out, "Fake executable") 660 | 661 | return [ 662 | cc_common.create_cc_toolchain_config_info( 663 | ctx = ctx, 664 | features = features, 665 | action_configs = action_configs, 666 | artifact_name_patterns = [], 667 | cxx_builtin_include_directories = cxx_builtin_include_directories, 668 | toolchain_identifier = ctx.attr.toolchain_identifier, 669 | host_system_name = host_system_name, 670 | target_system_name = ctx.attr.target_system_name, 671 | target_cpu = ctx.attr.target_cpu, 672 | target_libc = "libc", 673 | compiler = "gcc", 674 | abi_version = "local", 675 | abi_libc_version = "local", 676 | tool_paths = tool_paths, 677 | make_variables = [], 678 | builtin_sysroot = None, 679 | cc_target_os = None, 680 | ), 681 | DefaultInfo( 682 | executable = out, 683 | ), 684 | ] 685 | 686 | cc_toolchain_config_stm32 = rule( 687 | implementation = _stm32_impl, 688 | attrs = { 689 | "cpu": attr.string(mandatory = True, values = [ 690 | "stm32f0", 691 | "stm32f4", 692 | "stm32g4", 693 | ]), 694 | "builtin_include_directories": attr.string_list(), 695 | "extra_no_canonical_prefixes_flags": attr.string_list(), 696 | "host_compiler_path": attr.string(), 697 | "host_compiler_prefix": attr.string(), 698 | "host_compiler_warnings": attr.string_list(), 699 | "host_unfiltered_compile_flags": attr.string_list(), 700 | "target_cpu": attr.string(), 701 | "target_system_name": attr.string(), 702 | "toolchain_identifier": attr.string(), 703 | "extra_features": attr.string_list(), 704 | }, 705 | provides = [CcToolchainConfigInfo], 706 | executable = True, 707 | ) 708 | --------------------------------------------------------------------------------