Skip to content

Commit abce1d4

Browse files
Introduce initial Bazel build (#1705)
* Build boot_stage2 with Bazel Introduces the initial foundations of a Bazel build, including a toolchain, critical generated headers, platform patterns, and enough BUILD files to build boot_stage2. * Bazel libraries to support picotool * Move SDK defines to toolchain * Switch to `archive_override` in MODULE.bazel Uses archive_override where applicable to allow transitive bzlmod deps to propagate. * Multiplatform objcopy selection in Bazel build Makes an objcopy alias that redirects to the objcopy tool for the current exec platform, which allows boot_stage2 to build on Linux, macOS, and Windows. * Generate Bazel build files Adds initial set of generated Bazel build files. Note that these do not yet build, as dependency cycles are present. * Fix dependency cycles in Bazel build Fixes many dependency cycles, some were unintentionally created by the build file generator, others are true dependency cycles that require manual workarounds. * Silence warning in pico_stdio Bazel build Silences a stray warning in the Bazel build. * Fix wildcard Bazel build This makes `bazel build //...` succeed, and also prevents the fetching of toolchains that aren't compatible with the current execution environment (i.e. Windows computers will no longer try to download macOS toolchains). * Get the SDK working Finishes out the remainder of the work required to successfully compile a working blinky example. * Fix UART stdio dependencies in Bazel build Fixes some dependencies around pico_stdlib so that pico_stdlib links properly and UART stdio works. * Add linux support to Bazel build * Get Bazel deps from registry Adds external an external registry for resolving Bazel module dependencies. * Fix host configuration for picotool Provides the appropriate defines for host builds to support the picotool build. * Remove -ffreestanding from Bazel toolchain The -ffreestanding toolchain flag is quite strict, so remove it from the Bazel toolchain. * Remove unused .bzl file * Reduce Bazel compiler flags Cuts out most of the Bazel toolchain flags and only specifies the bare-minimum set of flags. Also, adds wrapper linker flags for functions the SDK wraps. * Get USB serial working Adds initial TinyUSB support and enough integration to get USB serial working. * Remove "Generated build file" Removes comments that indicates BUILD.bazel files are generated. This was used during initial bringup to indicate hand-crafted vs automatically generated BUILD.bazel files. * Do not build USB libraries unless configured Prevents USB libraries from being built unless the build is properly configured to use them. * Switch to rules_cc toolchains Moves toolchain configuration to use the new rules in rules_cc. * Minor cleanup in parse_version.py Cleans up trailing whitespace and runs the black formatter on parse_version.py. * Simplify constraint dimensions in Bazel build Consolidates the class/chip constraint settings to be a single constraint_setting with a config_setting that represents the rp2 class. * Update pin of rules_cc in Bazel build Includes a necessary fix for the target_compatible_with expression in the cc_toolchain to work as intended. * Move toolchains from pico.bzl to BUILD.bazel Moves toolchain definitions from pico.bzl to BUILD.bazel to make them easier to find and read. * Run buildifier on Bazel build files Fix trivial formatting issues by running buildifier on all BUILD.bazel files. * Make objcopy rule Makes a simple objcopy rule to remove direct references to the ARM toolchains. * Fix link flags in Bazel build Critical flags were not being applied to link steps. This applies -mcpu and -mthumb to the link steps to make the produced binaries work again. * Mention missing host build support * Fix various Bazel library rules * pico_bit_ops was incomplete. * pico_double and pico_float were trying to link in the "none" implementation. * Extend Bazel build documentation Improves documentation and comments across the Bazel build. * Clean up auxilary tools in Bazel build Switches genrules to use skylib rules to simplify things. Reworks version header generation to use the Bazel module version rather than parsing CMake. * Update boot_stage2 Bazel build file Moves `includes` to be enumerated on the correct library. * Add WORKSPACE version fallback WORKSPACE Bazel projects don't support querying module version, so add a fallback of '0.0.1-WORKSPACE' so the build can succeed. * Fix malloc handling in Bazel build * Fix Bazel dependency cycle in pico_malloc * Prevent malloc from being linked into boot_stage2 Prevents Bazel from ever trying to link malloc into the boot_stage2 binary. * Remove custom bootloader platform A dedicated boot_stage2 platform introduces a lot of complexity that needs to be more thought-through.
1 parent 23dec9d commit abce1d4

File tree

92 files changed

+2836
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+2836
-0
lines changed

.bazelrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Required for new toolchain resolution API.
2+
build --incompatible_enable_cc_toolchain_resolution
3+
build --@rules_cc//cc/toolchains:experimental_enable_rule_based_toolchains
4+
5+
# Produce useful output when the build fails.
6+
common --verbose_failures

.bazelversion

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7.0.2

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@
33
cmake-*
44
.DS_Store
55
build
6+
7+
bazel-*
8+
9+
# Ignore until https://github.com/bazelbuild/bazel/issues/20369 is fixed.
10+
MODULE.bazel.lock

BUILD.bazel

Whitespace-only changes.

MODULE.bazel

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
module(name = "pico-sdk", version = "1.6.0-rc1")
2+
3+
bazel_dep(name = "platforms", version = "0.0.8")
4+
5+
bazel_dep(name = "bazel_skylib", version = "1.6.1")
6+
7+
# Note: rules_cc is special-cased repository; a dependency on rules_cc in a
8+
# module will not ensure that the root Bazel module has that same version of
9+
# rules_cc. For that reason, this primarily acts as a FYI. You'll still need
10+
# to explicitly list this dependency in your own project's MODULE.bazel file.
11+
bazel_dep(name = "rules_cc", version = "0.0.10")
12+
13+
# rules_cc v0.0.10 is not yet cut, so manually pull in the desired version.
14+
# This does not apply to dependent projects, so it needs to be copied to your
15+
# project's MODULE.bazel too.
16+
archive_override(
17+
module_name = "rules_cc",
18+
urls = "https://github.com/bazelbuild/rules_cc/archive/1acf5213b6170f1f0133e273cb85ede0e732048f.zip",
19+
strip_prefix = "rules_cc-1acf5213b6170f1f0133e273cb85ede0e732048f",
20+
integrity = "sha256-NddP6xi6LzsIHT8bMSVJ2NtoURbN+l3xpjvmIgB6aSg=",
21+
)
22+
23+
http_archive = use_repo_rule("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
24+
25+
http_archive(
26+
name = "arm_gcc_linux-x86_64",
27+
url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz",
28+
strip_prefix = "arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi",
29+
build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
30+
sha256 = "6cd1bbc1d9ae57312bcd169ae283153a9572bd6a8e4eeae2fedfbc33b115fdbb",
31+
)
32+
33+
http_archive(
34+
name = "arm_gcc_win-x86_64",
35+
url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-mingw-w64-i686-arm-none-eabi.zip",
36+
strip_prefix = "arm-gnu-toolchain-13.2.Rel1-mingw-w64-i686-arm-none-eabi",
37+
build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
38+
sha256 = "51d933f00578aa28016c5e3c84f94403274ea7915539f8e56c13e2196437d18f",
39+
)
40+
41+
http_archive(
42+
name = "arm_gcc_mac-x86_64",
43+
url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-darwin-x86_64-arm-none-eabi.tar.xz",
44+
strip_prefix = "arm-gnu-toolchain-13.2.Rel1-darwin-x86_64-arm-none-eabi",
45+
build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
46+
sha256 = "075faa4f3e8eb45e59144858202351a28706f54a6ec17eedd88c9fb9412372cc",
47+
)
48+
49+
http_archive(
50+
name = "arm_gcc_mac-aarch64",
51+
url = "https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-darwin-arm64-arm-none-eabi.tar.xz",
52+
strip_prefix = "arm-gnu-toolchain-13.2.Rel1-darwin-arm64-arm-none-eabi",
53+
build_file = "//bazel/toolchain:gcc_arm_none_eabi.BUILD",
54+
sha256 = "39c44f8af42695b7b871df42e346c09fee670ea8dfc11f17083e296ea2b0d279",
55+
)
56+
57+
# TODO: Provide tinyusb as a proper Bazel module.
58+
http_archive(
59+
name = "tinyusb",
60+
url = "https://github.com/hathach/tinyusb/archive/86c416d4c0fb38432460b3e11b08b9de76941bf5.zip",
61+
strip_prefix = "tinyusb-86c416d4c0fb38432460b3e11b08b9de76941bf5",
62+
build_file = "//src/rp2_common/tinyusb:tinyusb.BUILD",
63+
sha256 = "ac57109bba00d26ffa33312d5f334990ec9a9a4d82bf890ed8b825b4610d1da2",
64+
)
65+
66+
register_toolchains(
67+
"//bazel/toolchain:arm_gcc_linux-x86_64",
68+
"//bazel/toolchain:arm_gcc_win-x86_64",
69+
"//bazel/toolchain:arm_gcc_mac-x86_64",
70+
"//bazel/toolchain:arm_gcc_mac-aarch64",
71+
)

bazel/BUILD.bazel

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
py_binary(
4+
name = "generate_version_header",
5+
srcs = ["generate_version_header.py"],
6+
visibility = ["//:__subpackages__"],
7+
)
8+
9+
# This isn't actually generated, it just uses the same name
10+
# to make it show up easier in searches.
11+
#
12+
# Rather than generating lists of headers to match CMake, the Bazel build
13+
# opts to have a static header that transitively include two known headers.
14+
# By default, empty header files are included, and users/platforms are expected
15+
# to specify an appropriate `cc_library` to replace them.
16+
#
17+
# You tell bazel which `cc_library` provides the respective headers by
18+
# configuring these `label_flag`s:
19+
#
20+
# # Specify the library that provides "pico_config_extra_headers.h"
21+
# --@pico-sdk//bazel/config:pico_config_extra_headers=//my_proj:my_custom_headers
22+
#
23+
# # Specify the library that provides "pico_config_platform_headers.h"
24+
# --@pico-sdk//bazel/config:pico_config_platform_headers=//my_proj:my_custom_platform_headers
25+
cc_library(
26+
name = "generate_config_header",
27+
hdrs = ["include/pico/config_autogen.h"],
28+
includes = ["include"],
29+
visibility = ["//:__subpackages__"],
30+
deps = [
31+
"//bazel/config:pico_config_extra_headers",
32+
"//bazel/config:pico_config_platform_headers",
33+
],
34+
)

bazel/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Bazel build
2+
The Bazel build for the Pico SDK is currently community-maintained, and should
3+
be considered an experimental work-in-progress. There are missing features,
4+
and you may encounter significant breakages with future versions.
5+
6+
You are welcome and encouraged to file issues for any problems you encounter
7+
along the way.
8+
9+
## Using the Pico SDK in a Bazel project.
10+
11+
### Add pico-sdk as a dependency
12+
First, in your `MODULE.bazel` file, add a dependency on the Pico SDK:
13+
```python
14+
bazel_dep(
15+
name = "pico-sdk",
16+
version = "1.6.0-rc1",
17+
)
18+
```
19+
Second, in the same file you'll need to add an explicit dependency on
20+
`rules_cc`, as it's a special-cased Bazel module:
21+
```python
22+
# Note: rules_cc is special-cased repository; a dependency on rules_cc in a
23+
# module will not ensure that the root Bazel module has that same version of
24+
# rules_cc. For that reason, this primarily acts as a FYI. You'll still need
25+
# to explicitly list this dependency in your own project's MODULE.bazel file.
26+
bazel_dep(name = "rules_cc", version = "0.0.10")
27+
28+
# rules_cc v0.0.10 is not yet cut, so manually pull in the desired version.
29+
# This does not apply to dependent projects, so it needs to be copied to your
30+
# project's MODULE.bazel too.
31+
archive_override(
32+
module_name = "rules_cc",
33+
urls = "https://github.com/bazelbuild/rules_cc/archive/1acf5213b6170f1f0133e273cb85ede0e732048f.zip",
34+
strip_prefix = "rules_cc-1acf5213b6170f1f0133e273cb85ede0e732048f",
35+
integrity = "sha256-NddP6xi6LzsIHT8bMSVJ2NtoURbN+l3xpjvmIgB6aSg=",
36+
)
37+
```
38+
39+
### Register toolchains
40+
These toolchains tell Bazel how to compile for ARM cores. Add the following
41+
to the `MODULE.bazel` for your project:
42+
```python
43+
register_toolchains(
44+
"@pico-sdk//bazel/toolchain:arm_gcc_linux-x86_64",
45+
"@pico-sdk//bazel/toolchain:arm_gcc_win-x86_64",
46+
"@pico-sdk//bazel/toolchain:arm_gcc_mac-x86_64",
47+
"@pico-sdk//bazel/toolchain:arm_gcc_mac-aarch64",
48+
)
49+
```
50+
51+
### Enable required .bazelrc flags
52+
To use the toolchains provided by the Pico SDK, you'll need to enable a few
53+
new features. In your project's `.bazelrc`, add the following
54+
```
55+
# Required for new toolchain resolution API.
56+
build --incompatible_enable_cc_toolchain_resolution
57+
build --@rules_cc//cc/toolchains:experimental_enable_rule_based_toolchains
58+
```
59+
60+
### Ready to build!
61+
You're now ready to start building Pico Projects in Bazel! When building,
62+
don't forget to specify `--platforms` so Bazel knows you're targeting the
63+
Raspberry Pi Pico:
64+
```console
65+
$ bazelisk build --platforms=@pico-sdk//bazel/platform:rp2040 //...
66+
```
67+
68+
## SDK configuration [experimental]
69+
These configuration options are a work in progress and may see significant
70+
breaking changes in future versions.
71+
72+
### Selecting a different board
73+
Currently there are three configurable flags for targeting a different board:
74+
1. `pico_config_extra_headers`: This should always point to a `cc_library `that
75+
provides a `"pico_config_extra_headers.h"` header. You can configure this
76+
by including a flag like the following in your build invocation:
77+
```
78+
--@pico-sdk//bazel/config:pico_config_extra_headers=//path/to:custom_extra_headers
79+
```
80+
2. `pico_config_platform_headers`: This should always point to a `cc_library`
81+
that provides a `"pico_config_platform_headers.h"` header.
82+
```
83+
--@pico-sdk//bazel/config:pico_config_platform_headers=//path/to:custom_platform_headers
84+
```
85+
3. `pico_config_header`: This should point to a `cc_library` that sets all
86+
necessary SDK defines. Most notably, `PICO_BOARD`, `PICO_CONFIG_HEADER`,
87+
`PICO_ON_DEVICE`, `PICO_NO_HARDWARE`, and `PICO_BUILD`. See
88+
`//src/boards:BUILD.bazel` for working examples. Any `defines` set on this
89+
library will propagate to the rest of the Pico SDK. To set this configuration
90+
option, pass a flag like the following in your Bazel build invocation:
91+
```
92+
--@pico-sdk//bazel/config:pico_config_platform_headers=//path/to:pico_board_config
93+
```
94+
95+
### Selecting a stdio mode
96+
To select a different stdio mode, add it to your `platform` definition. For
97+
example:
98+
```python
99+
platform(
100+
name = "rp2040",
101+
constraint_values = [
102+
"@pico-sdk//bazel/constraint:rp2040",
103+
"@pico-sdk//bazel/constraint:stdio_usb", # Configures stdio_mode.
104+
"@platforms//cpu:armv6-m",
105+
],
106+
)
107+
```
108+
109+
## Building the Pico SDK itself
110+
111+
### First time setup
112+
You'll need Bazel (v7.0.0 or higher) or Bazelisk (a self-updating Bazel
113+
launcher) to build the Pico SDK.
114+
115+
We strongly recommend you set up
116+
[Bazelisk](https://bazel.build/install/bazelisk).
117+
118+
### Building
119+
To build all of the Pico SDK, run the following command:
120+
```console
121+
$ bazelisk build --platforms=//bazel/platform:rp2040 //...
122+
```
123+
124+
**Note:** Since the Bazel build does not yet have any `cc_binary` rules with a
125+
`main()` function, there won't be any binaries to flash on your board. For now,
126+
this only builds the SDK as a collection of libraries.
127+
128+
## Known issues and limitations
129+
The Bazel build is currently experimental and incomplete. At this time, only the
130+
stock Pi Pico board is supported, and the only configuration options are
131+
changing the STDIO mode between UART and USB serial.
132+
133+
Keep in mind the following limitations:
134+
* Pico-W is not yet supported.
135+
* Selecting an alternative board is not yet supported.
136+
* Nearly all preexisting CMake configuration options are not yet supported.
137+
* Targeting the host build of the Pico SDK is not yet supported.

bazel/config/BUILD.bazel

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
# This should always point to a cc_library that provides
4+
# a "pico_config_extra_headers.h".
5+
label_flag(
6+
name = "pico_config_extra_headers",
7+
build_setting_default = ":no_extra_headers",
8+
)
9+
10+
# This should always point to a cc_library that provides
11+
# a "pico_config_platform_headers.h".
12+
label_flag(
13+
name = "pico_config_platform_headers",
14+
build_setting_default = ":no_platform_headers",
15+
)
16+
17+
# This should always point to a cc_library that defines PICO_CONFIG_HEADER and
18+
# any other defines that should be applied when building the SDK.
19+
label_flag(
20+
name = "pico_config_header",
21+
build_setting_default = "//src/boards:default",
22+
)
23+
24+
genrule(
25+
name = "empty_extra_headers_file",
26+
outs = ["generated_include/pico_config_extra_headers.h"],
27+
cmd = "echo > $@",
28+
cmd_bat = "copy NUL $@",
29+
visibility = ["//visibility:private"],
30+
)
31+
32+
genrule(
33+
name = "empty_platform_headers_file",
34+
outs = ["generated_include/pico_config_platform_headers.h"],
35+
cmd = "echo > $@",
36+
cmd_bat = "copy NUL $@",
37+
visibility = ["//visibility:private"],
38+
)
39+
40+
cc_library(
41+
name = "no_extra_headers",
42+
hdrs = ["generated_include/pico_config_extra_headers.h"],
43+
includes = ["generated_include"],
44+
visibility = ["//visibility:private"],
45+
)
46+
47+
cc_library(
48+
name = "no_platform_headers",
49+
hdrs = ["generated_include/pico_config_platform_headers.h"],
50+
includes = ["generated_include"],
51+
visibility = ["//visibility:private"],
52+
)

bazel/constraint/BUILD.bazel

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
# This constraint represents the dimension that guides the Pico SDK build. This
4+
# constraint will only ever enumerate specific MCUs (and the host), and does NOT
5+
# cover the differences from board-to-board.
6+
constraint_setting(
7+
name = "sdk_target",
8+
default_constraint_value = "host",
9+
)
10+
11+
# This constraint value is used to guide the host build.
12+
constraint_value(
13+
name = "host",
14+
constraint_setting = ":sdk_target",
15+
)
16+
17+
# This constraint value is used to guide parts of the build that are specific
18+
# to the rp2040.
19+
constraint_value(
20+
name = "rp2040",
21+
constraint_setting = ":sdk_target",
22+
)
23+
24+
# This constraint value is used to guide parts of the build that apply to all
25+
# rp2-class chips.
26+
config_setting(
27+
name = "rp2",
28+
constraint_values = [
29+
":rp2040",
30+
],
31+
)
32+
33+
# This constraint setting guides Bazel's build file evaluation differences
34+
# across different stdio configurations (e.g. stdio_usb needs TinyUSB).
35+
constraint_setting(
36+
name = "stdio_mode",
37+
default_constraint_value = "stdio_uart",
38+
)
39+
40+
# When this constraint value is active, stdio is built against a hardware UART.
41+
constraint_value(
42+
name = "stdio_uart",
43+
constraint_setting = ":stdio_mode",
44+
)
45+
46+
# When this constraint value is active, stdio is built against TinyUSB-based
47+
# USB serial.
48+
constraint_value(
49+
name = "stdio_usb",
50+
constraint_setting = ":stdio_mode",
51+
)
52+
53+
# When this constraint value is active, stdio is built against an ARM
54+
# semihosting library.
55+
constraint_value(
56+
name = "stdio_semihosting",
57+
constraint_setting = ":stdio_mode",
58+
)

0 commit comments

Comments
 (0)