Skip to content

Commit 338f99f

Browse files
Initial Pico/2 W Bazel support (#2049)
* Initial Pico 2 W Bazel support Improves compatibility with Pico W and Pico 2 W by fixing issues that prevented correct linking of wireless libraries. * Improve correctness and configurability * Require newer rules_python * Require [email protected] * Fix missing compatibility expressions * Minor tweaks * Minor cleanup * Update suggested version in Bazel README * More README tweaks * Improve Bazel btstack build correctness
1 parent 08ea1d8 commit 338f99f

File tree

21 files changed

+535
-87
lines changed

21 files changed

+535
-87
lines changed

MODULE.bazel

+17-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module(
55

66
bazel_dep(name = "platforms", version = "0.0.9")
77
bazel_dep(name = "bazel_skylib", version = "1.6.1")
8-
bazel_dep(name = "rules_python", version = "0.22.1")
8+
bazel_dep(name = "rules_python", version = "0.36.0")
99
bazel_dep(name = "picotool", version = "2.0.0")
1010
bazel_dep(name = "rules_cc", version = "0.0.10")
1111

@@ -132,3 +132,19 @@ register_toolchains(
132132
# Require users to opt-in to the Pico SDK's toolchains.
133133
dev_dependency = True,
134134
)
135+
136+
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
137+
python.toolchain(
138+
configure_coverage_tool = True,
139+
python_version = "3.9",
140+
)
141+
142+
use_repo(python, "pythons_hub")
143+
register_toolchains(
144+
"@pythons_hub//:all",
145+
dev_dependency = True,
146+
)
147+
register_toolchains(
148+
"@rules_python//python/runtime_env_toolchains:all",
149+
dev_dependency = True,
150+
)

bazel/README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
First, in your `MODULE.bazel` file, add a dependency on the Pico SDK and
77
`rules_cc`:
88
```python
9-
bazel_dep(name = "pico-sdk", version = "2.0.1")
9+
bazel_dep(name = "pico-sdk", version = "2.1.0")
1010
```
1111

1212
### Register toolchains
@@ -92,11 +92,12 @@ you encounter along the way.
9292

9393
Currently, the following features are not supported:
9494

95+
* Pico W wireless libraries work, but may not have complete feature parity with
96+
the CMake build.
97+
* Bazel does not yet provide RISC-V support for Pico 2/RP2350.
9598
* The pioasm parser cannot be built from source via Bazel.
9699
* Windows MSVC wildcard build (`bazel build //...`) does not work when targeting
97100
host.
98-
* Bazel does not yet provide RISC-V support for Pico 2/RP2350.
99-
* Pico W wireless libraries have link issues.
100101

101102
## Contributing
102103
When making changes to the Bazel build, please run the Bazel validation script

bazel/config/BUILD.bazel

+29
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,17 @@ string_flag(
151151
],
152152
)
153153

154+
# PICO_BAZEL_CONFIG: PICO_ASYNC_CONTEXT_IMPL, The default implementation for pico_async_context to link, type=string, default=threadsafe_background, group=build
155+
string_flag(
156+
name = "PICO_ASYNC_CONTEXT_IMPL",
157+
build_setting_default = "threadsafe_background",
158+
values = [
159+
"poll",
160+
"threadsafe_background",
161+
"freertos",
162+
],
163+
)
164+
154165
# PICO_BAZEL_CONFIG: PICO_BINARY_INFO_ENABLED, Whether to include binary info in final firmware, type=bool, default=1, group=pico_stdlib
155166
bool_flag(
156167
name = "PICO_BINARY_INFO_ENABLED",
@@ -248,6 +259,24 @@ label_flag(
248259
build_setting_default = "//bazel:empty_cc_lib",
249260
)
250261

262+
# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_BLE, [Bazel only] Whether or not to link in BLE portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_BLE=1, type=bool, default=False, group=wireless
263+
bool_flag(
264+
name = "PICO_BT_ENABLE_BLE",
265+
build_setting_default = False,
266+
)
267+
268+
# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_CLASSIC, [Bazel only] Whether or not to link in classic BT portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_CLASSIC=1, type=bool, default=False, group=wireless
269+
bool_flag(
270+
name = "PICO_BT_ENABLE_CLASSIC",
271+
build_setting_default = False,
272+
)
273+
274+
# PICO_BAZEL_CONFIG: PICO_BT_ENABLE_MESH, [Bazel only] Whether or not to link in mesh BT portions of the btstack as part of //src/rp2_common/pico_btstack. Also defines ENABLE_MESH=1, type=bool, default=False, group=wireless
275+
bool_flag(
276+
name = "PICO_BT_ENABLE_MESH",
277+
build_setting_default = False,
278+
)
279+
251280
# PICO_BAZEL_CONFIG: PICO_LWIP_CONFIG, [Bazel only] The cc_library that provides lwipopts.h, default=//bazel:empty_cc_lib, group=wireless
252281
label_flag(
253282
name = "PICO_LWIP_CONFIG",

bazel/constraint/BUILD.bazel

+45-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
load("//bazel/util:label_flag_matches.bzl", "label_flag_matches")
2+
13
package(default_visibility = ["//visibility:public"])
24

35
# This constraint represents the dimension that guides the Pico SDK build. This
@@ -48,6 +50,11 @@ config_setting(
4850
flag_values = {"//bazel/config:PICO_BOARD": "pico_w"},
4951
)
5052

53+
config_setting(
54+
name = "is_pico2_w",
55+
flag_values = {"//bazel/config:PICO_BOARD": "pico2_w"},
56+
)
57+
5158
config_setting(
5259
name = "pico_toolchain_clang_enabled",
5360
flag_values = {"//bazel/config:PICO_TOOLCHAIN": "clang"},
@@ -173,6 +180,21 @@ config_setting(
173180
flag_values = {"//bazel/config:PICO_DEFAULT_PRINTF_IMPL": "compiler"},
174181
)
175182

183+
config_setting(
184+
name = "pico_async_context_poll_enabled",
185+
flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "poll"},
186+
)
187+
188+
config_setting(
189+
name = "pico_async_context_threadsafe_background_enabled",
190+
flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "threadsafe_background"},
191+
)
192+
193+
config_setting(
194+
name = "pico_async_context_freertos_enabled",
195+
flag_values = {"//bazel/config:PICO_ASYNC_CONTEXT_IMPL": "freertos"},
196+
)
197+
176198
config_setting(
177199
name = "pico_use_default_max_page_size_enabled",
178200
flag_values = {"//bazel/config:PICO_USE_DEFAULT_MAX_PAGE_SIZE": "True"},
@@ -199,16 +221,34 @@ config_setting(
199221
)
200222

201223
config_setting(
202-
name = "pico_btstack_config_unset",
203-
flag_values = {"//bazel/config:PICO_BTSTACK_CONFIG": "//bazel:empty_cc_lib"},
224+
name = "pico_bt_enable_ble_enabled",
225+
flag_values = {"//bazel/config:PICO_BT_ENABLE_BLE": "True"},
204226
)
205227

206228
config_setting(
207-
name = "pico_lwip_config_unset",
208-
flag_values = {"//bazel/config:PICO_LWIP_CONFIG": "//bazel:empty_cc_lib"},
229+
name = "pico_bt_enable_classic_enabled",
230+
flag_values = {"//bazel/config:PICO_BT_ENABLE_CLASSIC": "True"},
209231
)
210232

211233
config_setting(
234+
name = "pico_bt_enable_mesh_enabled",
235+
flag_values = {"//bazel/config:PICO_BT_ENABLE_MESH": "True"},
236+
)
237+
238+
label_flag_matches(
239+
name = "pico_lwip_config_unset",
240+
flag = "//bazel/config:PICO_LWIP_CONFIG",
241+
value = "//bazel:empty_cc_lib",
242+
)
243+
244+
label_flag_matches(
245+
name = "pico_btstack_config_unset",
246+
flag = "//bazel/config:PICO_BTSTACK_CONFIG",
247+
value = "//bazel:empty_cc_lib",
248+
)
249+
250+
label_flag_matches(
212251
name = "pico_freertos_unset",
213-
flag_values = {"//bazel/config:PICO_FREERTOS_LIB": "//bazel:empty_cc_lib"},
252+
flag = "//bazel/config:PICO_FREERTOS_LIB",
253+
value = "//bazel:empty_cc_lib",
214254
)

bazel/defs.bzl

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def compatible_with_pico_w():
8888
return select({
8989
"@pico-sdk//bazel/constraint:cyw43_wireless": [],
9090
"@pico-sdk//bazel/constraint:is_pico_w": [],
91+
"@pico-sdk//bazel/constraint:is_pico2_w": [],
9192
"//conditions:default": ["@platforms//:incompatible"],
9293
})
9394

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain", "use_cc_toolchain")
2+
3+
def _pico_btstack_make_gatt_header_impl(ctx):
4+
cc_toolchain = find_cpp_toolchain(ctx)
5+
feature_configuration = cc_common.configure_features(
6+
ctx = ctx,
7+
cc_toolchain = cc_toolchain,
8+
requested_features = ctx.features,
9+
unsupported_features = ctx.disabled_features,
10+
)
11+
12+
out = ctx.actions.declare_file(
13+
"{}_gatt_generated/{}.h".format(ctx.label.name, ctx.file.src.basename.removesuffix(".gatt")),
14+
)
15+
16+
ctx.actions.run(
17+
executable = ctx.executable._make_gat_header_tool,
18+
arguments = [
19+
ctx.file.src.path,
20+
out.path,
21+
"-I",
22+
ctx.file._btstack_hdr.dirname,
23+
] + [
24+
25+
],
26+
inputs = [
27+
ctx.file.src,
28+
ctx.file._btstack_hdr,
29+
],
30+
outputs = [out],
31+
)
32+
33+
cc_ctx = cc_common.create_compilation_context(
34+
headers = depset(direct = [out]),
35+
includes = depset(direct = [out.dirname]),
36+
)
37+
38+
return [
39+
DefaultInfo(files = depset(direct = [out])),
40+
CcInfo(compilation_context = cc_ctx)
41+
]
42+
43+
pico_btstack_make_gatt_header = rule(
44+
implementation = _pico_btstack_make_gatt_header_impl,
45+
attrs = {
46+
"src": attr.label(mandatory = True, allow_single_file = True),
47+
"_btstack_hdr": attr.label(
48+
default = "@btstack//:src/bluetooth_gatt.h",
49+
allow_single_file = True,
50+
),
51+
"_make_gat_header_tool": attr.label(
52+
default = "@btstack//:compile_gatt",
53+
cfg = "exec",
54+
executable = True,
55+
),
56+
},
57+
fragments = ["cpp"],
58+
toolchains = use_cc_toolchain(),
59+
)

bazel/util/label_flag_matches.bzl

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""A wrapper that enables a `config_setting` matcher for label_flag flags."""
2+
3+
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
4+
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain", "use_cpp_toolchain")
5+
6+
def _match_label_flag_impl(ctx):
7+
matches = str(ctx.attr.expected_value.label) == str(ctx.attr.flag.label)
8+
return [
9+
config_common.FeatureFlagInfo(value = str(matches)),
10+
BuildSettingInfo(value = matches),
11+
]
12+
13+
_match_label_flag = rule(
14+
implementation = _match_label_flag_impl,
15+
attrs = {
16+
"expected_value": attr.label(
17+
mandatory = True,
18+
doc = "The expected flag value",
19+
),
20+
"flag": attr.label(
21+
mandatory = True,
22+
doc = "The flag to extract a value from",
23+
),
24+
},
25+
)
26+
27+
def label_flag_matches(*, name, flag, value):
28+
_match_label_flag(
29+
name = name + "._impl",
30+
expected_value = native.package_relative_label(value),
31+
flag = flag,
32+
)
33+
34+
native.config_setting(
35+
name = name,
36+
flag_values = {":{}".format(name + "._impl"): "True"},
37+
)

bazel/util/transition.bzl

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
def _normalize_flag_value(val):
2+
"""Converts flag values to transition-safe primitives."""
3+
if type(val) == "label":
4+
return str(val)
5+
return val
6+
17
def declare_transtion(attrs, flag_overrides = None, append_to_flags = None, executable = True):
28
"""A helper that drastically simplifies declaration of a transition.
39
@@ -31,7 +37,7 @@ def declare_transtion(attrs, flag_overrides = None, append_to_flags = None, exec
3137
final_overrides = {}
3238
if flag_overrides != None:
3339
final_overrides = {
34-
key: str(getattr(attrs, value))
40+
key: _normalize_flag_value(getattr(attrs, value))
3541
for key, value in flag_overrides.items()
3642
}
3743
if append_to_flags != None:
@@ -108,6 +114,8 @@ kitchen_sink_test_binary = declare_transtion(
108114
attrs = {
109115
"bt_stack_config": attr.label(mandatory = True),
110116
"lwip_config": attr.label(mandatory = True),
117+
"enable_ble": attr.bool(default = False),
118+
"enable_bt_classic": attr.bool(default = False),
111119
# This could be shared, but we don't in order to make it clearer that
112120
# a transition is in use.
113121
"_allowlist_function_transition": attr.label(
@@ -117,6 +125,8 @@ kitchen_sink_test_binary = declare_transtion(
117125
flag_overrides = {
118126
"@pico-sdk//bazel/config:PICO_BTSTACK_CONFIG": "bt_stack_config",
119127
"@pico-sdk//bazel/config:PICO_LWIP_CONFIG": "lwip_config",
128+
"@pico-sdk//bazel/config:PICO_BT_ENABLE_BLE": "enable_ble",
129+
"@pico-sdk//bazel/config:PICO_BT_ENABLE_CLASSIC": "enable_bt_classic",
120130
},
121131
)
122132

src/rp2_common/pico_async_context/BUILD.bazel

+14-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,18 @@ load("//bazel:defs.bzl", "compatible_with_rp2", "incompatible_with_config")
22

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

5-
cc_library(
5+
alias(
66
name = "pico_async_context",
7+
actual = select({
8+
"//bazel/constraint:pico_async_context_poll_enabled": ":pico_async_context_poll",
9+
"//bazel/constraint:pico_async_context_threadsafe_background_enabled": ":pico_async_context_threadsafe_background",
10+
"//bazel/constraint:pico_async_context_freertos_enabled": ":pico_async_context_freertos",
11+
"//conditions:default": "//bazel:incompatible_cc_lib",
12+
}),
13+
)
14+
15+
cc_library(
16+
name = "pico_async_context_base",
717
srcs = ["async_context_base.c"],
818
hdrs = [
919
"include/pico/async_context.h",
@@ -26,7 +36,7 @@ cc_library(
2636
"//bazel/constraint:pico_freertos_unset",
2737
),
2838
deps = [
29-
":pico_async_context",
39+
":pico_async_context_base",
3040
"//bazel/config:PICO_FREERTOS_LIB",
3141
"//src/common/pico_sync",
3242
"//src/common/pico_time",
@@ -42,7 +52,7 @@ cc_library(
4252
includes = ["include"],
4353
target_compatible_with = compatible_with_rp2(),
4454
deps = [
45-
":pico_async_context",
55+
":pico_async_context_base",
4656
"//src/common/pico_sync",
4757
"//src/common/pico_time",
4858
"//src/rp2_common:pico_platform",
@@ -56,7 +66,7 @@ cc_library(
5666
includes = ["include"],
5767
target_compatible_with = compatible_with_rp2(),
5868
deps = [
59-
":pico_async_context",
69+
":pico_async_context_base",
6070
"//src/common/pico_sync",
6171
"//src/common/pico_time",
6272
"//src/rp2_common:pico_platform",

0 commit comments

Comments
 (0)