pw_sys_io: Add facade constraint_setting, docs
Adds a constraint_setting associated with the pw_sys_io facade, and
constraint_values for the backends for this facade provided by Pigweed.
Also documents how this mechanism should be used.
pw_sys_io is just the first facade to receive this treatment: the rest
will be handled in followup CLs.
Bug: b/272090220
Change-Id: Id1f670ce194757f4ccfe489e0f29ac936f36a1ab
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/133290
Reviewed-by: Erik Gilling <konkers@google.com>
Commit-Queue: Ted Pudlik <tpudlik@google.com>
Reviewed-by: Kayce Basques <kayce@google.com>
diff --git a/docs/build_system.rst b/docs/build_system.rst
index 0e20ae7..549f003 100644
--- a/docs/build_system.rst
+++ b/docs/build_system.rst
@@ -923,11 +923,11 @@
name = "system_clock_backend_multiplexer",
visibility = ["@pigweed_config//:__pkg__"],
deps = select({
- "@pigweed//pw_build/constraints/rtos:freertos":
+ "@pigweed//pw_chrono_freertos:system_clock_backend":
["//pw_chrono_freertos:system_clock"],
- "@pigweed//pw_build/constraints/rtos:embos":
+ "@pigweed//pw_chrono_embos:system_clock_backend":
["//pw_chrono_embos:system_clock"],
- "@pigweed//pw_build/constraints/rtos:threadx":
+ "@pigweed//pw_chrono_threadx:system_clock_backend":
["//pw_chrono_threadx:system_clock"],
"//conditions:default": ["//pw_chrono_stl:system_clock"],
}),
@@ -972,83 +972,72 @@
your command line entries. Instead you would have to memorize the correct
combination of backends for each of your targets.
-So continuing on with our scenario, let's say we add a backup micro-controller,
+So continuing on with our scenario, let's say we add a backup microcontroller
to our spacecraft. But this backup computer doesn't have a hardware RTC. We
still want to share the bulk of the code between the two computers but now we
need two separate implementations for our pw_chrono facade. Let's say we choose
-to keep the primary flight computer using the hardware RTC and switch the backup
-computer over to use Pigweeds default FreeRTOS backend. In this case we might,
-want to do something similar to
-'@pigweed//pw_chrono:system_clock_backend_multiplexer' and create selectable
-dependencies for the two different computers. Now because there are no default
-constraint_setting's that meet our requirements we are going to have to;
+to keep the primary flight computer using the hardware RTC and switch the
+backup computer over to use Pigweed's default FreeRTOS backend. In this case we
+might want to do something similar to
+``@pigweed//pw_chrono:system_clock_backend_multiplexer`` and create selectable
+dependencies for the two different computers:
-1. Create a constraint_setting and a set of constraint_value's for the flight
- computer. For example;
+#. Create a constraint value corresponding to your custom backend:
- .. code:: py
+ .. code-block:: python
- # //platforms/flight_computer/BUILD
- constraint_setting(
- name = "flight_computer",
- )
+ # //pw_chrono_my_hardware_rtc/BUILD.bazel
+ constraint_value(
+ name = "system_clock_backend",
+ constraint_setting = "//pw_chrono:system_clock_constraint_setting",
+ )
- constraint_value(
- name = "primary",
- constraint_setting = ":flight_computer",
- )
+#. Create a set of platforms that can be used to switch constraint values.
+ For example:
- constraint_value(
- name = "backup",
- constraint_setting = ":flight_computer",
- )
+ .. code-block:: python
-2. Create a set of platforms that can be used to switch constraint_value's.
- For example;
+ # //platforms/BUILD.bazel
+ platform(
+ name = "primary_computer",
+ constraint_values = ["//pw_chrono_my_hardware_rtc:system_clock_backend"],
+ )
- .. code:: py
+ platform(
+ name = "backup_computer",
+ constraint_values = ["@pigweed//pw_chrono_freertos:system_clock_backend"],
+ )
- # //platforms/BUILD
- platform(
- name = "primary_computer",
- constraint_values = ["//platforms/flight_computer:primary"],
- )
+#. Create a target multiplexer that will select the right backend depending on
+ which computer you are using. For example:
- platform(
- name = "backup_computer",
- constraint_values = ["//platforms/flight_computer:backup"],
- )
+ .. code-block:: python
-3. Create a target multiplexer that will select the right backend depending on
- which computer you are using. For example;
+ # //pw_chrono/BUILD
+ load("//pw_build:pigweed.bzl", "pw_cc_library")
- .. code:: py
+ pw_cc_library(
+ name = "system_clock_backend_multiplexer",
+ deps = select({
+ "//pw_chrono_my_hardware_rtc:system_clock_backend": [
+ "//pw_chrono_my_hardware_rtc:system_clock",
+ ],
+ "@pigweed//pw_chrono_freertos:system_clock_backend": [
+ "@pigweed//pw_chrono_freertos:system_clock",
+ ],
+ "//conditions:default": [
+ "@pigweed//pw_chrono_stl:system_clock",
+ ],
+ }),
+ )
- # //pw_chrono/BUILD
- load("//pw_build:pigweed.bzl", "pw_cc_library")
-
- pw_cc_library(
- name = "system_clock_backend_multiplexer",
- deps = select({
- "//platforms/flight_computer:primary": [
- "//pw_chrono_my_hardware_rtc:system_clock",
- ],
- "//platforms/flight_computer:backup": [
- "@pigweed//pw_chrono_freertos:system_clock",
- ],
- "//conditions:default": [
- "@pigweed//pw_chrono_stl:system_clock",
- ],
- }),
- )
-
-4. Add a build setting override for the ``pw_chrono_system_clock_backend`` label
+#. Add a build setting override for the ``pw_chrono_system_clock_backend`` label
flag to your ``.bazelrc`` file that points to your new target multiplexer.
- .. code:: py
+ .. code-block:: python
- # //.bazelrc
- build --@pigweed_config//:pw_chrono_system_clock_backend=@your_workspace//pw_chrono:system_clock_backend_multiplexer
+ # //.bazelrc
+ build --@pigweed_config//:pw_chrono_system_clock_backend=@your_workspace//pw_chrono:system_clock_backend_multiplexer
Building your target now will result in slightly different build graph. For
example, running;
diff --git a/pw_build/BUILD.bazel b/pw_build/BUILD.bazel
index 4d84665..d1690dd 100644
--- a/pw_build/BUILD.bazel
+++ b/pw_build/BUILD.bazel
@@ -47,3 +47,16 @@
"PW_BUILD_EXPECTED_SOURCE_PATH=\\\"pw_build/file_prefix_map_test.cc\\\"",
],
)
+
+# Special target that may be used instead of a cc_library as the default
+# condition in backend multiplexer select statements. This produces better
+# error messages than e.g. using an invalid label.
+#
+# If you're a user whose build errored out because a library transitively
+# depended on this target: the platform you're targeting did not specify which
+# backend to use for some facade. Look at the previous step in the dependency
+# chain (printed with the error) to figure out which one.
+cc_library(
+ name = "unspecified_backend",
+ target_compatible_with = ["@platforms//:incompatible"],
+)
diff --git a/pw_build/docs.rst b/pw_build/docs.rst
index ee98663..3c74013 100644
--- a/pw_build/docs.rst
+++ b/pw_build/docs.rst
@@ -1484,11 +1484,52 @@
If a project uses only one backend for a given facade, the backend label
flag should point at that backend target.
+#. The **facade constraint setting** and **backend constraint values**. Every
+ facade has an associated `constraint setting
+ <https://bazel.build/concepts/platforms#api-review>`_ (enum used in platform
+ definition), and each backend for this facade has an associated
+ ``constraint_value`` (enum value). Example:
+
+ .. code-block:: python
+
+ # //pw_sync/BUILD.bazel
+ constraint_setting(
+ name = "binary_semaphore_backend_constraint_setting",
+ )
+
+ # //pw_sync_stl/BUILD.bazel
+ constraint_value(
+ name = "binary_semaphore_backend",
+ constraint_setting = "//pw_sync:binary_semaphore_backend_constraint_setting",
+ )
+
+ # //pw_sync_freertos/BUILD.bazel
+ constraint_value(
+ name = "binary_semaphore_backend",
+ constraint_setting = "//pw_sync:binary_semaphore_backend_constraint_setting",
+ )
+
+ `Target platforms <https://bazel.build/extending/platforms>`_ for Pigweed
+ projects should indicate which backend they select for each facade by
+ listing the corresponding ``constraint_value`` in their definition. This can
+ be used in a couple of ways:
+
+ #. It allows projects to switch between multiple backends based only on the
+ `target platform <https://bazel.build/extending/platforms>`_ using a
+ *backend multiplexer* (see below) instead of setting label flags in
+ their ``.bazelrc``.
+
+ #. It allows tests or libraries that only support a particular backend to
+ express this through the `target_compatible_with
+ <https://bazel.build/reference/be/common-definitions#common.target_compatible_with>`_
+ attribute. Bazel will use this to `automatically skip incompatible
+ targets in wildcard builds
+ <https://bazel.build/extending/platforms#skipping-incompatible-targets>`_.
+
#. The **backend multiplexer**. If a project uses more than one backend for a
given facade (e.g., it uses different backends for host and embedded target
builds), the backend label flag will point to a target that resolves to the
- correct backend based on the `target platform
- <https://bazel.build/extending/platforms>`_. This will typically be an
+ correct backend based on the target platform. This will typically be an
`alias <https://bazel.build/reference/be/general#alias>`_ with a ``select``
statement mapping constraint values to the appropriate backend targets. For
example,
@@ -1500,6 +1541,15 @@
actual = select({
"//pw_sync_stl:binary_semaphore_backend": "@pigweed//pw_sync_stl:binary_semaphore",
"//pw_sync_freertos:binary_semaphore_backend": "@pigweed//pw_sync_freertos:binary_semaphore_backend",
+ # If we're building for a host OS, use the STL backend.
+ "@platforms//os:macos": "@pigweed//pw_sync_stl:binary_semaphore",
+ "@platforms//os:linux": "@pigweed//pw_sync_stl:binary_semaphore",
+ "@platforms//os:windows": "@pigweed//pw_sync_stl:binary_semaphore",
+ # Unless the target platform is the host platform, it must
+ # explicitly specify which backend to use. The unspecified_backend
+ # is not compatible with any platform; taking this branch will produce
+ # an informative error.
+ "//conditions:default": "@pigweed//pw_build:unspecified_backend",
}),
)
diff --git a/pw_build/platforms/BUILD.bazel b/pw_build/platforms/BUILD.bazel
index c0a688d..744cc48 100644
--- a/pw_build/platforms/BUILD.bazel
+++ b/pw_build/platforms/BUILD.bazel
@@ -98,6 +98,7 @@
constraint_values = [
"//pw_build/constraints/chipset:lm3s6965evb",
"@rust_crates//:no_std",
+ "//pw_sys_io_baremetal_lm3s6965evb:backend",
],
parents = [":cortex_m3"],
)
@@ -115,11 +116,14 @@
parents = [":stm32f429"],
)
+# Primarily a QEMU supported m0 target for rust development, based on the
+# nRF51822.
platform(
name = "microbit",
constraint_values = [
"//pw_build/constraints/board:microbit",
"@rust_crates//:no_std",
+ # We have no pw_sys_io backend for this platform.
],
parents = [":nrf52833"],
)
@@ -137,9 +141,9 @@
"//targets/stm32f429i_disc1_stm32cube:freertos_config_cv",
# Use the ARM_CM4F port of FreeRTOS.
"@freertos//:port_ARM_CM4F",
- # Specify this chipset to use the baremetal pw_sys_io backend (because
- # the default pw_sys_io_stdio backend is not compatible with FreeRTOS).
- "//pw_build/constraints/chipset:stm32f429",
+ # Use the baremetal pw_sys_io backend (because the default
+ # pw_sys_io_stdio backend is not compatible with FreeRTOS).
+ "//pw_sys_io_baremetal_stm32f429:backend",
# os:none means, we're not building for any host platform (Windows,
# Linux, or Mac). The pw_sys_io_baremetal_stm32f429 backend is only
# compatible with os:none.
diff --git a/pw_sys_io/BUILD.bazel b/pw_sys_io/BUILD.bazel
index 7e6eee2..1cfd15f 100644
--- a/pw_sys_io/BUILD.bazel
+++ b/pw_sys_io/BUILD.bazel
@@ -22,6 +22,10 @@
licenses(["notice"])
+constraint_setting(
+ name = "backend_constraint_setting",
+)
+
pw_cc_facade(
name = "facade",
hdrs = ["public/pw_sys_io/sys_io.h"],
@@ -53,13 +57,21 @@
],
)
-pw_cc_library(
+alias(
name = "backend_multiplexer",
- visibility = ["@pigweed_config//:__pkg__"],
- deps = select({
- "//pw_build/constraints/board:mimxrt595_evk": ["@pigweed//pw_sys_io_mcuxpresso"],
- "//pw_build/constraints/chipset:stm32f429": ["@pigweed//pw_sys_io_baremetal_stm32f429"],
- "//pw_build/constraints/chipset:lm3s6965evb": ["@pigweed//pw_sys_io_baremetal_lm3s6965evb"],
- "//conditions:default": ["@pigweed//pw_sys_io_stdio"],
+ actual = select({
+ "//pw_sys_io_arduino:backend": "@pigweed//pw_sys_io_arduino",
+ "//pw_sys_io_baremetal_lm3s6965evb:backend": "@pigweed//pw_sys_io_baremetal_lm3s6965evb",
+ "//pw_sys_io_baremetal_stm32f429:backend": "@pigweed//pw_sys_io_baremetal_stm32f429",
+ "//pw_sys_io_emcraft_sf2:backend": "@pigweed//pw_sys_io_emcraft_sf2",
+ "//pw_sys_io_mcuxpresso:backend": "@pigweed//pw_sys_io_mcuxpresso",
+ "//pw_sys_io_pico:backend": "@pigweed//pw_sys_io_pico",
+ "//pw_sys_io_stm32cube:backend": "@pigweed//pw_sys_io_stm32cube",
+ "//pw_sys_io_stdio:backend": "@pigweed//pw_sys_io_stdio",
+ "@platforms//os:macos": "@pigweed//pw_sys_io_stdio",
+ "@platforms//os:linux": "@pigweed//pw_sys_io_stdio",
+ "@platforms//os:windows": "@pigweed//pw_sys_io_stdio",
+ "//conditions:default": "@pigweed//pw_build:unspecified_backend",
}),
+ visibility = ["@pigweed_config//:__pkg__"],
)
diff --git a/pw_sys_io_arduino/BUILD.bazel b/pw_sys_io_arduino/BUILD.bazel
index dafbb9b..5b29974 100644
--- a/pw_sys_io_arduino/BUILD.bazel
+++ b/pw_sys_io_arduino/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_arduino",
srcs = ["sys_io_arduino.cc"],
diff --git a/pw_sys_io_baremetal_lm3s6965evb/BUILD.bazel b/pw_sys_io_baremetal_lm3s6965evb/BUILD.bazel
index b3ea1c2..909feee 100644
--- a/pw_sys_io_baremetal_lm3s6965evb/BUILD.bazel
+++ b/pw_sys_io_baremetal_lm3s6965evb/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_baremetal_lm3s6965evb",
srcs = ["sys_io_baremetal.cc"],
diff --git a/pw_sys_io_baremetal_stm32f429/BUILD.bazel b/pw_sys_io_baremetal_stm32f429/BUILD.bazel
index 248d987..8147ce1 100644
--- a/pw_sys_io_baremetal_stm32f429/BUILD.bazel
+++ b/pw_sys_io_baremetal_stm32f429/BUILD.bazel
@@ -21,13 +21,17 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_baremetal_stm32f429",
srcs = ["sys_io_baremetal.cc"],
hdrs = ["public/pw_sys_io_baremetal_stm32f429/init.h"],
includes = ["public"],
target_compatible_with = [
- "//pw_build/constraints/chipset:stm32f429",
"@platforms//os:none",
],
deps = [
diff --git a/pw_sys_io_emcraft_sf2/BUILD.bazel b/pw_sys_io_emcraft_sf2/BUILD.bazel
index fb10a78..3643727 100644
--- a/pw_sys_io_emcraft_sf2/BUILD.bazel
+++ b/pw_sys_io_emcraft_sf2/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_emcraft_sf2",
srcs = [
diff --git a/pw_sys_io_mcuxpresso/BUILD.bazel b/pw_sys_io_mcuxpresso/BUILD.bazel
index 726e5aa..7c91d7b 100644
--- a/pw_sys_io_mcuxpresso/BUILD.bazel
+++ b/pw_sys_io_mcuxpresso/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_mcuxpresso",
srcs = ["sys_io.cc"],
diff --git a/pw_sys_io_pico/BUILD.bazel b/pw_sys_io_pico/BUILD.bazel
index 91d4242..caa77f5 100644
--- a/pw_sys_io_pico/BUILD.bazel
+++ b/pw_sys_io_pico/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_pico",
srcs = [
diff --git a/pw_sys_io_stdio/BUILD.bazel b/pw_sys_io_stdio/BUILD.bazel
index 23d5103..381ce98 100644
--- a/pw_sys_io_stdio/BUILD.bazel
+++ b/pw_sys_io_stdio/BUILD.bazel
@@ -25,6 +25,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_stdio",
srcs = ["sys_io.cc"],
diff --git a/pw_sys_io_stm32cube/BUILD.bazel b/pw_sys_io_stm32cube/BUILD.bazel
index 39c863d..7a9f2f8 100644
--- a/pw_sys_io_stm32cube/BUILD.bazel
+++ b/pw_sys_io_stm32cube/BUILD.bazel
@@ -21,6 +21,11 @@
licenses(["notice"])
+constraint_value(
+ name = "backend",
+ constraint_setting = "//pw_sys_io:backend_constraint_setting",
+)
+
pw_cc_library(
name = "pw_sys_io_stm32cube",
srcs = [