workspace: Switches Bazel builds to using facades

Switches over all packages that were previously working with Bazel
to use the new facades API. In the process of doing this a few new
modules where newly compatible with Bazel. This is reflected in the
changes to the presubmit.

Change-Id: I12aa67fa43b9ac2b947f33814f901dd00f929543
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/41561
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Akira Baruah <akirabaruah@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Commit-Queue: Keir Mierle <keir@google.com>
diff --git a/WORKSPACE b/WORKSPACE
index a34cacf..6aa2053 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -56,6 +56,12 @@
 # Set up build_bazel_rules_nodejs.
 # Required by: pigweed.
 # Used in modules: //pw_web_ui.
+git_repository(
+    name = "platforms",
+    commit = "d4c9d7f51a7c403814b60f66d20eeb425fbaaacb",
+    remote = "https://github.com/bazelbuild/platforms.git",
+)
+
 http_archive(
     name = "build_bazel_rules_nodejs",
     sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef",
@@ -104,7 +110,7 @@
 # Used in modules: //pw_polyfill, //pw_build (all pw_cc* targets).
 git_repository(
     name = "bazel_embedded",
-    commit = "b8e1b66067ac54e86784479e5cde57c2ed88d099",
+    commit = "d4717a6e33b88cb9fe1b6663d78656728c49b5c8",
     remote = "https://github.com/silvergasp/bazel-embedded.git",
 )
 
diff --git a/docs/build_system.rst b/docs/build_system.rst
index 46aca57..54b7e65 100644
--- a/docs/build_system.rst
+++ b/docs/build_system.rst
@@ -154,6 +154,15 @@
 Of the supported build systems, GN is the most full-featured, followed by CMake,
 and finally Bazel.
 
+.. note::
+  A quick note on terminology: the word "target" is overloaded within GN/Bazel (and
+  Pigweed)---it can refer to either a GN/Bazel build target, such as a ``source_set``
+  or ``executable``, or to an output platform (e.g. a specific board, device, or
+  system).
+
+  To avoid confusing the two, we refer to the former as "GN/Bazel targets" and the
+  latter as "Pigweed targets".
+
 GN
 --
 A perhaps unfamiliar name, `GN (Generate Ninja)`_ is a meta-build system that
@@ -178,15 +187,6 @@
 
 .. _GN reference: https://gn.googlesource.com/gn/+/master/docs/reference.md
 
-.. note::
-  A quick note on terminology: the word "target" is overloaded within GN (and
-  Pigweed)---it can refer to either a GN build target, such as a ``source_set``
-  or ``executable``, or to an output platform (e.g. a specific board, device, or
-  system).
-
-  To avoid confusing the two, we refer to the former as "GN targets" and the
-  latter as "Pigweed targets".
-
 Entrypoint: .gn
 ---------------
 The entrypoint to a GN build is the ``.gn`` file, which defines a project's root
@@ -510,7 +510,6 @@
 
      out/stm32f429i_disc1_debug/obj/foo/bin/foo
 
-
 CMake
 -----
 A well-known name in C/C++ development, `CMake`_ is widely used by all kinds of
@@ -525,6 +524,10 @@
 various proprietary projects. Its modular structure makes it a great fit for
 à la carte usage.
 
+.. note::
+  Bazel support is experimental and only for the brave for now. If you are
+  looking for stable set of build API's please use GN.
+
 The Bazel build
 ===============
 This section describes Pigweed's Bazel build structure, how it is used upstream,
@@ -609,3 +612,423 @@
   .. code:: sh
 
     lcov --list bazel-out/_coverage/_coverage_report.dat
+
+Configuration
+-------------
+Generally speaking there are three primary concepts that make up Bazel's
+configuration API.
+
+1. Selects
+2. Compatibility lists
+3. Flags/Build settings
+
+Selects
+^^^^^^^
+Selects are useful for specifying different dependencies/source depending on the
+platform that is currently being targeted. For more information on this please
+see the `Bazel selects reference`_. e.g.
+
+.. code:: py
+
+  pw_cc_library(
+    name = "some_platform_dependant_library",
+    deps = select({
+      "@platforms//cpu:armv7e-m": [":arm_libs"],
+      "//conditions:default": [":host_libs"],
+    }),
+  )
+
+Compatibility lists
+^^^^^^^^^^^^^^^^^^^
+Compatibility lists allow you to specify which platforms your targets are
+compatible with. Consider an example where you want to specify that a target is
+compatible with only a host os;
+
+.. code:: py
+
+  pw_cc_library(
+    name = "some_host_only_lib",
+    srcs = ["host.cc"],
+    target_compatible_with = select({
+      "@platforms//os:windows": [],
+      "@platforms//os:linux": [],
+      "@platforms//os:macos": [],
+      "//conditions:default": ["@platforms//:incompatible"],
+    }),
+  )
+
+In this case building from or for either Windows/Linux/Mac will be supported, but
+other OS's will fail if this target is explicitly depended on. However if
+building with a wild card for a non-host platform this target will be skipped
+and the build will continue. e.g.
+
+.. code:: sh
+
+  bazel build //... --platforms=@pigweed//pw_build/platforms:cortex_m0
+
+This allows for you to easily create compatibility matricies without adversely
+affecting your ability build your entire repo for a given Pigweed target.
+For more detailed information on how to use the target_compatible_with attribute
+please see `Bazel target_compatible_with reference`_.
+
+Flags/build settings
+^^^^^^^^^^^^^^^^^^^^
+Flags/build settings are particularly useful in scenarios where you may want to
+be able to quickly inject a dependency from the command line but don't
+necessarily want to create an entirely new set of constraints to use with a
+select statement.
+
+.. note::
+  The scope for what is possible with build flags/settings goes well beyond
+  what will be described here. For more detailed information on flags/settings
+  please see `Bazel config reference`_.
+
+A simple example of when it is useful to use a label_flag is when you want to
+swap out a single dependency from the command line. e.g.
+
+.. code:: py
+
+  pw_cc_library(
+    name = "some_default_io",
+    srcs = ["default_io.cc"],
+  )
+
+  pw_cc_library(
+    name = "some_other_io",
+    srcs = ["other_io.cc"],
+  )
+
+  label_flag(
+    name = "io",
+    default_build_setting = ":some_default_io",
+  )
+
+  pw_cc_library(
+    name = "some_target_that_needs_io",
+    deps = [":io"],
+  )
+
+From here the label_flag by default redirects to the target ":some_default_io",
+however it is possible to override this from the command line. e.g.
+
+.. code:: sh
+
+  bazel build //:some_target_that_needs_io --//:io=//:some_other_io
+
+
+
+.. _Bazel selects reference: https://docs.bazel.build/versions/master/configurable-attributes.html#select-and-dependencies
+
+.. _Bazel target_compatible_with reference: https://docs.bazel.build/versions/master/platforms.html#skipping-incompatible-targets
+
+.. _Bazel config reference: https://docs.bazel.build/versions/master/skylark/config.html
+
+
+Pigweeds configuration
+^^^^^^^^^^^^^^^^^^^^^^
+Pigweeds Bazel configuration API is designed to be distributed across the
+Pigweed repository and/or your downstream repository. If you are coming from
+GN's centralized configuration API it might be useful to think about
+Pigweed+Bazel's configuration as the transpose of GN's configuration. The
+configuration interface that is supported by Pigweed is designed to start simple
+and then grow with your project.
+
+.. note::
+  There are plans to extend the configuration API for Bazel. However,
+  currently the only configurations that are available under the Bazel+Pigweed
+  configuration API is the ability to switch facade backends. For more
+  information on what this is please see the
+  :ref:`docs-module-structure-facades` section of :ref:`docs-module-structure`.
+
+Consider a scenario that you are building a flight controller for a
+spacecraft. But have very little experience with Pigweed and you have just
+landed here. First things first you would;
+
+1. Set up your WORKSPACE to fetch the Pigweeds repository. Then add the
+   dependencies that you need from Pigweeds WORKSPACE.
+
+2. Add a pigweed_config rule to your WORKSPACE, using Pigweed's default
+   configuration.
+
+  .. code:: py
+
+    # WORKSPACE ...
+    load("//pw_build:target_config.bzl", "pigweed_config")
+
+    # Configure Pigweeds backend.
+    pigweed_config(
+        name = "pigweed_config",
+        build_file = "@pigweed//targets:default_config.BUILD",
+    )
+
+.. note::
+  We are aware, that the experience of setting up your WORKSPACE file to work
+  with pigweed is less than ideal. This API is under construction, but we are
+  working on this!
+
+..
+  TODO: Add in a better way to pull down WORKSPACE dependencies in Bazel then
+  add docs in here.
+
+Now to explain what is going on here. Housed under the "pigweed_config" remote
+repository is a set of configuration flags. These can be used to inject
+dependencies into facades to override the default backend.
+
+Continuing on with our scenario, consider that you maybe want to try using the
+'//pw_chrono' module. So you create a target in your repository like so;
+
+.. code::
+
+  # BUILD
+  pw_cc_library(
+    name = "time_is_relative",
+    srcs = ["relative_time_on_earth.cc"],
+    deps = ["@pigweed//pw_chrono"],
+  )
+
+Now this should work out of the box for any host operating system. e.g. Running;
+
+.. code::
+
+  bazel build //:time_is_relative
+
+will produce a working library. But as your probably here because Pigweed offers
+a set of embedded libraries you might be interested in running your code on some
+random micro-controller/FPGA combined with an RTOS. For now let's assume that by
+some coincidence you are using FreeRTOS and are happy to make use
+of our default '//pw_chrono' backend for FreeRTOS. You could build the following
+with;
+
+.. code:: sh
+
+  bazel build //:time_is_relative \
+  --platforms=@pigweed//pw_build/platforms:freertos
+
+There is a fair bit to unpack here in terms of how our configuration system
+is determining which dependencies to choose for your build. The dependency
+tree (that is important for configuration) in a project such as this would
+look like.
+
+.. code::
+
+  @pigweed//pw_chrono:pw_chrono_facade <-----------.
+   ^                                               |
+   |                            @pigweed//pw_chrono_freertos:system_clock
+   |                            (Actual backend)
+   |                                               ^
+   |                                               |
+   |                            @pigweed//pw_chrono:backend_multiplexer
+   |                            Select backend based on OS:
+   |                            [FreeRTOS (X), Embos ( ), STL ( ), Threadx ( )]
+   |                                               ^
+   |                                               |
+  @pigweed//pw_chrono  -------> @pigweed_config//:pw_chrono_backend
+   ^                            (Injectable)
+   |
+  //:time_is_relative
+
+So when evaluating this setup Bazel checks the dependencies for '//pw_chrono'
+and finds that it depends on "@pigweed_config//:pw_chrono_backend" which looks
+like this;
+
+.. code:: py
+
+  # pw_chrono config.
+  label_flag(
+      name = "pw_chrono_backend",
+      build_setting_default = "@pigweed//pw_chrono:backend_multiplexer",
+  )
+
+Looking at the 'build_setting_default' we can see that by default it depends
+back on the target "@pigweed//pw_chrono:backend_multiplexer". If you only had one
+backend you could actually just change the 'build_setting_default' to point
+directly to your backend. However because we have four different backends we
+have to use the select semantics to choose the right one. In this case it looks
+like;
+
+.. code:: py
+
+  pw_cc_library(
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@pigweed//pw_build/constraints/rtos:freertos":
+            ["//pw_chrono_freertos:system_clock"],
+        "@pigweed//pw_build/constraints/rtos:embos":
+            ["//pw_chrono_embos:system_clock"],
+        "@pigweed//pw_build/constraints/rtos:threadx":
+            ["//pw_chrono_threadx:system_clock"],
+        "//conditions:default": ["//pw_chrono_stl:system_clock"],
+    }),
+  )
+
+Intuitively you can see that the first option was selected, which terminates
+the configuration chain.
+
+Continuing on with our scenario let's say that you have read
+:ref:`docs-module-structure` and now want to implement your own backend for
+'//pw_chrono' using a hardware RTC. In this case you would create a new
+directory 'pw_chrono_my_hardware_rtc'. To ensure that your new backend compiles
+with the facade an easy and temporary way to override the dependency tree is
+to override the label flag in '@pigweed_config'. For example;
+
+.. code:: sh
+
+  bazel build //:time_is_relative \
+    --@pigweed_config//pw_chrono_backend=//pw_chrono_my_hardware_rtc:system_clock
+
+This temporarily modifies the build graph to look something like this;
+
+.. code::
+
+  @pigweed//pw_chrono:pw_chrono_facade <-----.
+   ^                                         |
+   |                      @your_workspace//pw_chrono_my_hardware_rtc:system_clock
+   |                      (Actual backend)
+   |                                         ^
+   |                                         |
+  @pigweed//pw_chrono  -> @pigweed_config//:pw_chrono_backend
+   ^                      (Injectable)
+   |
+  //:time_is_relative
+
+Now while this is a nice temporary change, but you might find yourself in need
+of a more permanent configuration. Particularly if you want to override multiple
+different backends. In other words if you had several backends to override, that
+would translate to several different command line flags (one for each override).
+This problem further compounds as you have multiple Pigweed targets all
+requiring different combinations of different backends as you can't even reuse
+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,
+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: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;
+
+1. Create a constraint_setting and a set of constraint_value's for the flight
+   computer. For example;
+
+  .. code:: py
+
+    # //platforms/flight_computer/BUILD
+    constraint_setting(
+      name = "flight_computer",
+    )
+
+    constraint_value(
+      name = "primary",
+      constraint_setting = ":flight_computer",
+    )
+
+    constraint_value(
+      name = "backup",
+      constraint_setting = ":flight_computer",
+    )
+
+2. Create a set of platforms that can be used to switch constraint_value's.
+   For example;
+
+  .. code:: py
+
+    # //platforms/BUILD
+    platform(
+      name = "primary_computer",
+      constraint_values = ["//platforms/flight_computer:primary"],
+    )
+
+    platform(
+      name = "backup_computer",
+      constraint_values = ["//platforms/flight_computer:backup"],
+    )
+
+3. Create a target multiplexer that will select the right backend depending on
+   which computer you are using. For example;
+
+  .. code:: py
+
+    # //pw_chrono/BUILD
+    load("//pw_build:pigweed.bzl", "pw_cc_library")
+
+    pw_cc_library(
+      name = "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. Copy and paste across the target/default_config.BUILD across from the
+   Pigweed repository and modifying the build_setting_default for the target
+   'pw_chrono_backend' to point to your new backend_multiplexer target. For example;
+
+   This;
+
+  .. code:: py
+
+    # @pigweed//target:default_config.BUILD
+    label_flag(
+        name = "pw_chrono_backend",
+        build_setting_default = "@pigweed//pw_chrono:backend_multiplexer",
+    )
+
+  Becomes this;
+
+  .. code:: py
+
+    # @your_workspace//target:your_config.BUILD
+    label_flag(
+      name = "pw_chrono_backend",
+      build_setting_default =
+        "@your_workspace//pw_chrono:backend_multiplexer",
+    )
+
+5. Switch your workspace 'pigweed_config' rule over to use your custom config.
+
+  .. code:: py
+
+    # WORKSPACE
+    pigweed_config(
+      name = "pigweed_config",
+      build_file = "//target/your_config.BUILD",
+    )
+
+Building your target now will result in slightly different build graph. For
+example, running;
+
+.. code:: sh
+
+  bazel build //:time_is_relative --platforms=//platforms:primary_computer
+
+Will result in a build graph that looks like;
+
+.. code::
+
+  @pigweed//pw_chrono:pw_chrono_facade <---.
+   ^                                        |
+   |                     @your_workspace//pw_chrono_my_hardware_rtc:system_clock
+   |                     (Actual backend)
+   |                                        ^
+   |                                        |
+   |                     @your_workspace//pw_chrono:backend_multiplexer
+   |                     Select backend based on OS:
+   |                     [Primary (X), Backup ( ), Host only default ( )]
+   |                                        ^
+   |                                        |
+  @pigweed//pw_chrono -> @pigweed_config//:pw_chrono_backend
+   ^                     (Injectable)
+   |
+  //:time_is_relative
\ No newline at end of file
diff --git a/pw_allocator/BUILD b/pw_allocator/BUILD
index 8492751..1d36d76 100644
--- a/pw_allocator/BUILD
+++ b/pw_allocator/BUILD
@@ -32,6 +32,7 @@
     ],
     includes = ["public"],
     deps = [
+        "//pw_assert",
         "//pw_span",
         "//pw_status",
     ],
@@ -61,9 +62,11 @@
     hdrs = [
         "public/pw_allocator/freelist_heap.h",
     ],
+    includes = ["public"],
     deps = [
         ":block",
         ":freelist",
+        "//pw_log",
     ],
 )
 
diff --git a/pw_assert/BUILD b/pw_assert/BUILD
index d5af164..dff4701 100644
--- a/pw_assert/BUILD
+++ b/pw_assert/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
     "pw_cc_test",
 )
@@ -22,10 +23,7 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_ASSERT_BACKEND = "//pw_assert_basic"
-
-pw_cc_library(
+pw_cc_facade(
     name = "facade",
     hdrs = [
         "public/pw_assert/assert.h",
@@ -36,7 +34,6 @@
     ],
     includes = ["public"],
     deps = [
-        PW_ASSERT_BACKEND + ":headers",
         "//pw_preprocessor",
     ],
 )
@@ -45,16 +42,14 @@
     name = "pw_assert",
     deps = [
         ":facade",
-        PW_ASSERT_BACKEND + ":headers",
-        PW_ASSERT_BACKEND,
+        "@pigweed_config//:pw_assert_backend",
     ],
 )
 
 pw_cc_library(
-    name = "backend",
-    deps = [
-        PW_ASSERT_BACKEND,
-    ],
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = ["@pigweed//pw_assert_basic"],
 )
 
 pw_cc_test(
@@ -63,16 +58,16 @@
         "assert_facade_test.cc",
         "assert_test.cc",
         "fake_backend.cc",
-        "public/pw_assert/internal/assert_impl.h",
+        "public/pw_assert/internal/check_impl.h",
         "pw_assert_test/fake_backend.h",
     ],
     deps = [
         ":facade",
+        ":pw_assert",
         "//pw_preprocessor",
         "//pw_span",
         "//pw_string",
         "//pw_unit_test",
-        PW_ASSERT_BACKEND,
     ],
 )
 
@@ -83,8 +78,6 @@
         "assert_backend_compile_test_c.c",
     ],
     deps = [
-        ":backend",
-        ":facade",
         ":pw_assert",
         "//pw_unit_test",
     ],
diff --git a/pw_build/constraints/rtos/BUILD b/pw_build/constraints/rtos/BUILD
new file mode 100644
index 0000000..c1a49cf
--- /dev/null
+++ b/pw_build/constraints/rtos/BUILD
@@ -0,0 +1,68 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+package(default_visibility = ["//visibility:public"])
+
+constraint_setting(
+    name = "rtos",
+    default_constraint_value = "none",
+)
+
+constraint_value(
+    name = "none",
+    constraint_setting = ":rtos",
+)
+
+config_setting(
+    name = "none_setting",
+    flag_values = {
+        "@pigweed_config//:target_os": ":none",
+    },
+)
+
+constraint_value(
+    name = "embos",
+    constraint_setting = ":rtos",
+)
+
+config_setting(
+    name = "embos_setting",
+    flag_values = {
+        "@pigweed_config//:target_os": ":embos",
+    },
+)
+
+constraint_value(
+    name = "freertos",
+    constraint_setting = ":rtos",
+)
+
+config_setting(
+    name = "freertos_setting",
+    flag_values = {
+        "@pigweed_config//:target_os": ":freertos",
+    },
+)
+
+constraint_value(
+    name = "threadx",
+    constraint_setting = ":rtos",
+)
+
+config_setting(
+    name = "threadx_setting",
+    flag_values = {
+        "@pigweed_config//:target_os": ":threadx",
+    },
+)
diff --git a/pw_build/platforms/BUILD b/pw_build/platforms/BUILD
index a19a462..7bbc6a3 100644
--- a/pw_build/platforms/BUILD
+++ b/pw_build/platforms/BUILD
@@ -13,40 +13,77 @@
 # the License.
 package(default_visibility = ["//visibility:public"])
 
+# --- OS's ---
+platform(
+    name = "freertos",
+    constraint_values = [
+        "//pw_build/constraints/rtos:freertos",
+        "@platforms//os:none",
+    ],
+)
+
+platform(
+    name = "embos",
+    constraint_values = [
+        "//pw_build/constraints/rtos:embos",
+        "@platforms//os:none",
+    ],
+)
+
+platform(
+    name = "threadx",
+    constraint_values = [
+        "//pw_build/constraints/rtos:threadx",
+        "@platforms//os:none",
+    ],
+)
+
+platform(
+    name = "none",
+    constraint_values = ["@platforms//os:none"],
+)
+
 # --- CPU's ---
-alias(
+platform(
     name = "cortex_m0",
-    actual = "@bazel_embedded//platforms:cortex_m0",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m0"],
 )
 
-alias(
+platform(
     name = "cortex_m1",
-    actual = "@bazel_embedded//platforms:cortex_m1",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m1"],
 )
 
-alias(
+platform(
     name = "cortex_m3",
-    actual = "@bazel_embedded//platforms:cortex_m3",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m3"],
 )
 
-alias(
+platform(
     name = "cortex_m4",
-    actual = "@bazel_embedded//platforms:cortex_m4",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m4"],
 )
 
-alias(
+platform(
     name = "cortex_m4_fpu",
-    actual = "@bazel_embedded//platforms:cortex_m4",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m4"],
 )
 
-alias(
+platform(
     name = "cortex_m7",
-    actual = "@bazel_embedded//platforms:cortex_m7",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m7"],
 )
 
-alias(
+platform(
     name = "cortex_m7_fpu",
-    actual = "@bazel_embedded//platforms:cortex_m7_fpu",
+    constraint_values = ["@pigweed_config//:target_rtos"],
+    parents = ["@bazel_embedded//platforms:cortex_m7_fpu"],
 )
 
 # --- Chipsets ---
diff --git a/pw_build/selects.bzl b/pw_build/selects.bzl
new file mode 100644
index 0000000..732ac32
--- /dev/null
+++ b/pw_build/selects.bzl
@@ -0,0 +1,31 @@
+# Copyright 2021 The Pigweed Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
+
+_RTOS_NONE = "//pw_build/constraints/rtos:none"
+
+# Common select for tagging a target as only compatible with host OS's. This
+# select implements the logic '(Windows or Macos or Linux) and not RTOS'.
+# Example usage:
+#   load("//pw_build:selects.bzl","TARGET_COMPATIBLE_WITH_HOST_SELECT")
+#   pw_cc_library(
+#       name = "some_host_only_lib",
+#       hdrs = ["host.h"],
+#       target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
+#   )
+TARGET_COMPATIBLE_WITH_HOST_SELECT = {
+    "@platforms//os:windows": [_RTOS_NONE],
+    "@platforms//os:macos": [_RTOS_NONE],
+    "@platforms//os:linux": [_RTOS_NONE],
+    "//conditions:default": ["@platforms//:incompatible"],
+}
diff --git a/pw_chrono/BUILD b/pw_chrono/BUILD
index cce73aa..d4d7860 100644
--- a/pw_chrono/BUILD
+++ b/pw_chrono/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
     "pw_cc_test",
 )
@@ -22,9 +23,6 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_CHRONO_SYSTEM_CLOCK_BACKEND = "//pw_chrono_stl:system_clock"
-
 pw_cc_library(
     name = "epoch",
     hdrs = [
@@ -33,11 +31,8 @@
     includes = ["public"],
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "system_clock_facade",
-    srcs = [
-        "system_clock.cc",
-    ],
     hdrs = [
         "public/pw_chrono/internal/system_clock_macros.h",
         "public/pw_chrono/system_clock.h",
@@ -45,24 +40,30 @@
     includes = ["public"],
     deps = [
         ":epoch",
-        PW_CHRONO_SYSTEM_CLOCK_BACKEND + "_headers",
         "//pw_preprocessor",
     ],
 )
 
 pw_cc_library(
     name = "system_clock",
+    srcs = [
+        "system_clock.cc",
+    ],
     deps = [
         ":system_clock_facade",
-        PW_CHRONO_SYSTEM_CLOCK_BACKEND + "_headers",
+        "@pigweed_config//:pw_chrono_backend",
     ],
 )
 
 pw_cc_library(
-    name = "system_clock_backend",
-    deps = [
-        PW_CHRONO_SYSTEM_CLOCK_BACKEND,
-    ],
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//pw_build/constraints/rtos:freertos": ["//pw_chrono_freertos:system_clock"],
+        "//pw_build/constraints/rtos:embos": ["//pw_chrono_embos:system_clock"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_chrono_threadx:system_clock"],
+        "//conditions:default": ["//pw_chrono_stl:system_clock"],
+    }),
 )
 
 pw_cc_library(
diff --git a/pw_chrono_embos/BUILD b/pw_chrono_embos/BUILD
index a65d083..f0d01a8 100644
--- a/pw_chrono_embos/BUILD
+++ b/pw_chrono_embos/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         "//pw_chrono:epoch",
     ],
@@ -43,10 +46,11 @@
     srcs = [
         "system_clock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":system_clock_headers",
         "//pw_chrono:system_clock_facade",
-        # TODO(pwbug/317): This should depend on embOS but our third parties
-        # currently do not have Bazel support.
     ],
 )
diff --git a/pw_chrono_freertos/BUILD b/pw_chrono_freertos/BUILD
index 6c65913..1b71337 100644
--- a/pw_chrono_freertos/BUILD
+++ b/pw_chrono_freertos/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         "//pw_chrono:epoch",
     ],
@@ -43,6 +46,9 @@
     srcs = [
         "system_clock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":system_clock_headers",
         "//pw_chrono:system_clock_facade",
diff --git a/pw_chrono_stl/BUILD b/pw_chrono_stl/BUILD
index e1abacf..a015e0f 100644
--- a/pw_chrono_stl/BUILD
+++ b/pw_chrono_stl/BUILD
@@ -16,6 +16,10 @@
     "//pw_build:pigweed.bzl",
     "pw_cc_library",
 )
+load(
+    "//pw_build:selects.bzl",
+    "TARGET_COMPATIBLE_WITH_HOST_SELECT",
+)
 
 package(default_visibility = ["//visibility:public"])
 
@@ -40,6 +44,7 @@
 
 pw_cc_library(
     name = "system_clock",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":system_clock_headers",
         "//pw_chrono:system_clock_facade",
diff --git a/pw_chrono_threadx/BUILD b/pw_chrono_threadx/BUILD
index 0920cfb..ad0d83d 100644
--- a/pw_chrono_threadx/BUILD
+++ b/pw_chrono_threadx/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         "//pw_chrono:epoch",
     ],
@@ -43,6 +46,9 @@
     srcs = [
         "system_clock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":system_clock_headers",
         "//pw_chrono:system_clock_facade",
diff --git a/pw_interrupt/BUILD b/pw_interrupt/BUILD
index b25443e..9b6135b 100644
--- a/pw_interrupt/BUILD
+++ b/pw_interrupt/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
 )
 
@@ -21,34 +22,42 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_INTERRUPT_CONTEXT_BACKEND = "//pw_interrupt_context_cortex_m:context_armv7m"
-
-pw_cc_library(
+pw_cc_facade(
     name = "context_facade",
-    srcs = [
-        "context.cc",
-    ],
     hdrs = [
         "public/pw_interrupt/context.h",
     ],
     includes = ["public"],
-    deps = [
-        PW_INTERRUPT_CONTEXT_BACKEND + "_headers",
-    ],
 )
 
 pw_cc_library(
     name = "context",
     deps = [
         ":context_facade",
-        PW_INTERRUPT_CONTEXT_BACKEND + "_headers",
+        "@pigweed_config//:pw_interrupt_backend",
     ],
 )
 
 pw_cc_library(
-    name = "context_backend",
-    deps = [
-        PW_INTERRUPT_CONTEXT_BACKEND,
-    ],
+    name = "backend_multiplexer",
+    # Normally this would be done in the backend packages but because there is
+    # no host implementation we have to define this here.
+    target_compatible_with = select({
+        "@platforms//cpu:armv7-m": [],
+        "@platforms//cpu:armv7e-m": [],
+        "@platforms//cpu:armv8-m": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//cpu:armv7-m": ["//pw_interrupt_cortex_m:context_armv7m"],
+        "@platforms//cpu:armv7e-m": ["//pw_interrupt_cortex_m:context_armv7m"],
+        "@platforms//cpu:armv8-m": ["//pw_interrupt_cortex_m:context_armv8m"],
+        # This is required for this to be a valid select when building for the
+        # host i.e. 'bazel build //pw_interrupt/...'. The
+        # target_compatible_with attribute is used to skip this target when
+        # built with a wildcard. If explicitly depended on for a host build
+        # the build will fail.
+        "//conditions:default": [],
+    }),
 )
diff --git a/pw_log/BUILD b/pw_log/BUILD
index 723f75d..d76a685 100644
--- a/pw_log/BUILD
+++ b/pw_log/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
     "pw_cc_test",
 )
@@ -22,10 +23,7 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_LOG_BACKEND = "//pw_log_basic"
-
-pw_cc_library(
+pw_cc_facade(
     name = "facade",
     hdrs = [
         "public/pw_log/levels.h",
@@ -36,7 +34,6 @@
     ],
     includes = ["public"],
     deps = [
-        PW_LOG_BACKEND + ":headers",
         "//pw_preprocessor",
     ],
 )
@@ -45,15 +42,14 @@
     name = "pw_log",
     deps = [
         ":facade",
-        PW_LOG_BACKEND + ":headers",
+        "@pigweed_config//:pw_log_backend",
     ],
 )
 
 pw_cc_library(
-    name = "backend",
-    deps = [
-        PW_LOG_BACKEND,
-    ],
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = ["//pw_log_basic"],
 )
 
 pw_cc_test(
@@ -63,7 +59,6 @@
         "basic_log_test_plain_c.c",
     ],
     deps = [
-        ":backend",
         ":facade",
         ":pw_log",
         "//pw_preprocessor",
diff --git a/pw_malloc/BUILD b/pw_malloc/BUILD
index b7548b0..d29726a 100644
--- a/pw_malloc/BUILD
+++ b/pw_malloc/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
 )
 
@@ -21,31 +22,24 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_MALLOC_BACKEND = "//pw_malloc_freelist"
-
-pw_cc_library(
+pw_cc_facade(
     name = "facade",
     hdrs = [
         "public/pw_malloc/malloc.h",
     ],
     includes = ["public"],
-    deps = [
-        PW_MALLOC_BACKEND + ":headers",
-    ],
 )
 
 pw_cc_library(
     name = "pw_malloc",
     deps = [
         ":facade",
-        PW_MALLOC_BACKEND + ":headers",
+        "@pigweed_config//:pw_malloc_backend",
     ],
 )
 
 pw_cc_library(
-    name = "backend",
-    deps = [
-        PW_MALLOC_BACKEND,
-    ],
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = ["//pw_malloc_freelist"],
 )
diff --git a/pw_malloc_freelist/BUILD b/pw_malloc_freelist/BUILD
index c3ca117..c0aaa11 100644
--- a/pw_malloc_freelist/BUILD
+++ b/pw_malloc_freelist/BUILD
@@ -39,21 +39,22 @@
     ],
     deps = [
         ":headers",
-        "//dir_pw_allocator:block",
-        "//dir_pw_allocator:freelist_heap",
-        "//dir_pw_boot_armv7m",
-        "//dir_pw_malloc:facade",
-        "//dir_pw_preprocessor",
+        "//pw_allocator:block",
+        "//pw_allocator:freelist_heap",
+        "//pw_boot_armv7m",
+        "//pw_malloc:facade",
+        "//pw_preprocessor",
     ],
 )
 
 pw_cc_test(
-    name = "freelist_malloctest",
+    name = "freelist_malloc_test",
     srcs = [
         "freelist_malloc_test.cc",
     ],
     deps = [
         ":headers",
+        ":pw_malloc_freelist",
         "//pw_unit_test",
     ],
 )
diff --git a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
index 1c5a917..10dcf1a 100755
--- a/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
+++ b/pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
@@ -214,27 +214,37 @@
 # TODO: Slowly add modules here that work with bazel until all
 # modules are added. Then replace with //...
 _MODULES_THAT_WORK_WITH_BAZEL = [
+    "//pw_allocator/...",
+    "//pw_assert/...",
     '//pw_assert_basic/...',
     '//pw_base64/...',
     '//pw_build/...',
+    '//pw_chrono/...',
     '//pw_chrono_stl/...',
     '//pw_containers/...',
     '//pw_cpu_exception/...',
     '//pw_docgen/...',
     '//pw_doctor/...',
     '//pw_i2c/...',
+    '//pw_interrupt/...',
     '//pw_log/...',
     '//pw_log_basic/...',
+    '//pw_malloc/...',
+    '//pw_malloc_freelist/...',
     '//pw_polyfill/...',
     '//pw_preprocessor/...',
     '//pw_protobuf_compiler/...',
     '//pw_span/...',
     '//pw_status/...',
     '//pw_stream/...',
+    "//pw_sync/...",
+    "//pw_sync_stl/...",
     '//pw_sys_io/...',
     '//pw_sys_io_baremetal_lm3s6965evb/...',
     '//pw_sys_io_stdio/...',
+    '//pw_thread/...',
     '//pw_thread_stl/...',
+    '//pw_tokenizer/...',
     '//pw_toolchain/...',
     '//pw_varint/...',
     '//pw_web_ui/...',
diff --git a/pw_sync/BUILD b/pw_sync/BUILD
index 11e793a..6b63e1f 100644
--- a/pw_sync/BUILD
+++ b/pw_sync/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
     "pw_cc_test",
 )
@@ -22,28 +23,13 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_SYNC_BINARY_SEMAPHORE_BACKEND = "//pw_sync_stl:binary_semaphore"
-
-PW_SYNC_COUNTING_SEMAPHORE_BACKEND = "//pw_sync_stl:counting_semaphore"
-
-PW_SYNC_MUTEX_BACKEND = "//pw_sync_stl:mutex"
-
-PW_SYNC_TIMED_MUTEX_BACKEND = "//pw_sync_stl:timed_mutex"
-
-PW_SYNC_INTERRUPT_SPIN_LOCK_BACKEND = "//pw_sync_stl:interrupt_spin_lock"
-
-pw_cc_library(
+pw_cc_facade(
     name = "binary_semaphore_facade",
-    srcs = [
-        "binary_semaphore.cc",
-    ],
     hdrs = [
         "public/pw_sync/binary_semaphore.h",
     ],
     includes = ["public"],
     deps = [
-        PW_SYNC_BINARY_SEMAPHORE_BACKEND + "_headers",
         "//pw_chrono:system_clock",
         "//pw_preprocessor",
     ],
@@ -51,30 +37,34 @@
 
 pw_cc_library(
     name = "binary_semaphore",
+    srcs = [
+        "binary_semaphore.cc",
+    ],
     deps = [
         ":binary_semaphore_facade",
-        PW_SYNC_BINARY_SEMAPHORE_BACKEND + "_headers",
+        "@pigweed_config//:pw_sync_binary_semaphore_backend",
     ],
 )
 
 pw_cc_library(
-    name = "binary_semaphore_backend",
-    deps = [
-        PW_SYNC_BINARY_SEMAPHORE_BACKEND,
-    ],
+    name = "binary_semaphore_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//os:none": ["//pw_sync_baremetal:binary_semaphore"],
+        "//pw_build/constraints/rtos:embos": ["//pw_sync_embos:binary_semaphore"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_sync_freertos:binary_semaphore"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_sync_threadx:binary_semaphore"],
+        "//conditions:default": ["//pw_sync_stl:binary_semaphore"],
+    }),
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "counting_semaphore_facade",
-    srcs = [
-        "counting_semaphore.cc",
-    ],
     hdrs = [
         "public/pw_sync/counting_semaphore.h",
     ],
     includes = ["public"],
     deps = [
-        PW_SYNC_COUNTING_SEMAPHORE_BACKEND + "_headers",
         "//pw_chrono:system_clock",
         "//pw_preprocessor",
     ],
@@ -82,17 +72,25 @@
 
 pw_cc_library(
     name = "counting_semaphore",
+    srcs = [
+        "counting_semaphore.cc",
+    ],
     deps = [
         ":counting_semaphore_facade",
-        PW_SYNC_COUNTING_SEMAPHORE_BACKEND + "_headers",
+        "@pigweed_config//:pw_sync_counting_semaphore_backend",
     ],
 )
 
 pw_cc_library(
-    name = "counting_semaphore_backend",
-    deps = [
-        PW_SYNC_COUNTING_SEMAPHORE_BACKEND,
-    ],
+    name = "counting_semaphore_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//os:none": ["//pw_sync_baremetal:counting_semaphore"],
+        "//pw_build/constraints/rtos:embos": ["//pw_sync_embos:counting_semaphore"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_sync_freertos:counting_semaphore"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_sync_threadx:counting_semaphore"],
+        "//conditions:default": ["//pw_sync_stl:counting_semaphore"],
+    }),
 )
 
 pw_cc_library(
@@ -106,11 +104,8 @@
     ],
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "mutex_facade",
-    srcs = [
-        "mutex.cc",
-    ],
     hdrs = [
         "public/pw_sync/mutex.h",
     ],
@@ -118,30 +113,34 @@
     deps = [
         ":lock_annotations",
         "//pw_preprocessor",
-        PW_SYNC_MUTEX_BACKEND + "_headers",
     ],
 )
 
 pw_cc_library(
     name = "mutex",
+    srcs = [
+        "mutex.cc",
+    ],
     deps = [
         ":mutex_facade",
-        PW_SYNC_MUTEX_BACKEND + "_headers",
+        "@pigweed_config//:pw_sync_mutex_backend",
     ],
 )
 
 pw_cc_library(
-    name = "mutex_backend",
-    deps = [
-        PW_SYNC_MUTEX_BACKEND,
-    ],
+    name = "mutex_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//os:none": ["//pw_sync_baremetal:mutex"],
+        "//pw_build/constraints/rtos:embos": ["//pw_sync_embos:mutex"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_sync_freertos:mutex"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_sync_threadx:mutex"],
+        "//conditions:default": ["//pw_sync_stl:mutex"],
+    }),
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "timed_mutex_facade",
-    srcs = [
-        "timed_mutex.cc",
-    ],
     hdrs = [
         "public/pw_sync/timed_mutex.h",
     ],
@@ -151,30 +150,35 @@
         ":mutex_facade",
         "//pw_chrono:system_clock",
         "//pw_preprocessor",
-        PW_SYNC_TIMED_MUTEX_BACKEND + "_headers",
     ],
 )
 
 pw_cc_library(
     name = "timed_mutex",
-    deps = [
-        ":timed_mutex_facade",
-        PW_SYNC_TIMED_MUTEX_BACKEND + "_headers",
-    ],
-)
-
-pw_cc_library(
-    name = "timed_mutex_backend",
-    deps = [
-        PW_SYNC_TIMED_MUTEX_BACKEND,
-    ],
-)
-
-pw_cc_library(
-    name = "interrupt_spin_lock_facade",
     srcs = [
-        "interrupt_spin_lock.cc",
+        "timed_mutex.cc",
     ],
+    deps = [
+        ":mutex",
+        ":timed_mutex_facade",
+        "@pigweed_config//:pw_sync_timed_mutex_backend",
+    ],
+)
+
+pw_cc_library(
+    name = "timed_mutex_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//os:none": ["//pw_sync_baremetal:timed_mutex"],
+        "//pw_build/constraints/rtos:embos": ["//pw_sync_embos:timed_mutex"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_sync_freertos:timed_mutex"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_sync_threadx:timed_mutex"],
+        "//conditions:default": ["//pw_sync_stl:timed_mutex"],
+    }),
+)
+
+pw_cc_facade(
+    name = "interrupt_spin_lock_facade",
     hdrs = [
         "public/pw_sync/interrupt_spin_lock.h",
     ],
@@ -182,23 +186,30 @@
     deps = [
         ":lock_annotations",
         "//pw_preprocessor",
-        PW_SYNC_INTERRUPT_SPIN_LOCK_BACKEND + "_headers",
     ],
 )
 
 pw_cc_library(
     name = "interrupt_spin_lock",
+    srcs = [
+        "interrupt_spin_lock.cc",
+    ],
     deps = [
         ":interrupt_spin_lock_facade",
-        PW_SYNC_INTERRUPT_SPIN_LOCK_BACKEND + "_headers",
+        "@pigweed_config//:pw_sync_interrupt_spin_lock_backend",
     ],
 )
 
 pw_cc_library(
-    name = "interrupt_spin_lock_backend",
-    deps = [
-        PW_SYNC_INTERRUPT_SPIN_LOCK_BACKEND,
-    ],
+    name = "interrupt_spin_lock_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "@platforms//os:none": ["//pw_sync_baremetal:interrupt_spin_lock"],
+        "//pw_build/constraints/rtos:embos": ["//pw_sync_embos:interrupt_spin_lock"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_sync_freertos:interrupt_spin_lock"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_sync_threadx:interrupt_spin_lock"],
+        "//conditions:default": ["//pw_sync_stl:interrupt_spin_lock"],
+    }),
 )
 
 pw_cc_library(
diff --git a/pw_sync_baremetal/BUILD b/pw_sync_baremetal/BUILD
index 16774df..69821e1 100644
--- a/pw_sync_baremetal/BUILD
+++ b/pw_sync_baremetal/BUILD
@@ -33,10 +33,12 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = ["@platforms//os:none"],
 )
 
 pw_cc_library(
     name = "interrupt_spin_lock",
+    target_compatible_with = ["@platforms//os:none"],
     deps = [
         ":interrupt_spin_lock_headers",
         "//pw_assert",
diff --git a/pw_sync_embos/BUILD b/pw_sync_embos/BUILD
index 1a18120..d03e39c 100644
--- a/pw_sync_embos/BUILD
+++ b/pw_sync_embos/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         # TODO(pwbug/317): This should depend on embOS but our third parties
         # currently do not have Bazel support.
@@ -46,6 +49,9 @@
     srcs = [
         "binary_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":binary_semaphore_headers",
         "//pw_interrupt:context",
@@ -65,6 +71,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         # TODO(pwbug/317): This should depend on embOS but our third parties
         # currently do not have Bazel support.
@@ -78,6 +87,9 @@
     srcs = [
         "counting_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":counting_semaphore_headers",
         "//pw_interrupt:context",
@@ -97,6 +109,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         # TODO(pwbug/317): This should depend on embOS but our third parties
         # currently do not have Bazel support.
@@ -106,6 +121,9 @@
 
 pw_cc_library(
     name = "mutex",
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":mutex_headers",
         "//pw_sync:mutex_facade",
@@ -122,6 +140,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         # TODO(pwbug/317): This should depend on embOS but our third parties
         # currently do not have Bazel support.
@@ -135,6 +156,9 @@
     srcs = [
         "timed_mutex.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":timed_mutex_headers",
         "//pw_chrono_embos:system_clock_headers",
@@ -155,6 +179,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     # TODO(pwbug/317): This should depend on embOS but our third parties
     # currently do not have Bazel support.
 )
@@ -164,6 +191,9 @@
     srcs = [
         "interrupt_spin_lock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:embos",
+    ],
     deps = [
         ":interrupt_spin_lock_headers",
         "//pw_sync:interrupt_spin_lock_facade",
diff --git a/pw_sync_freertos/BUILD b/pw_sync_freertos/BUILD
index 7ad2759..ed0c7c1 100644
--- a/pw_sync_freertos/BUILD
+++ b/pw_sync_freertos/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         # TODO: This should depend on FreeRTOS but our third parties currently
         # do not have Bazel support.
@@ -46,6 +49,9 @@
     srcs = [
         "binary_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":binary_semaphore_headers",
         "//pw_interrupt:context",
@@ -65,6 +71,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         # TODO: This should depend on FreeRTOS but our third parties currently
         # do not have Bazel support.
@@ -78,6 +87,9 @@
     srcs = [
         "counting_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":counting_semaphore_headers",
         "//pw_interrupt:context",
@@ -97,6 +109,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         # TODO: This should depend on FreeRTOS but our third parties currently
         # do not have Bazel support.
@@ -106,6 +121,9 @@
 
 pw_cc_library(
     name = "mutex",
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":mutex_headers",
         "//pw_sync:mutex_facade",
@@ -122,6 +140,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         # TODO: This should depend on FreeRTOS but our third parties currently
         # do not have Bazel support.
@@ -136,6 +157,9 @@
     srcs = [
         "timed_mutex.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":timed_mutex_headers",
         "//pw_interrupt:context",
@@ -155,6 +179,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     # TODO: This should depend on FreeRTOS but our third parties currently
     # do not have Bazel support.
 )
@@ -164,6 +191,9 @@
     srcs = [
         "interrupt_spin_lock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:freertos",
+    ],
     deps = [
         ":interrupt_spin_lock_headers",
         "//pw_interrupt:context",
diff --git a/pw_sync_stl/BUILD b/pw_sync_stl/BUILD
index c2f39a7..8235f15 100644
--- a/pw_sync_stl/BUILD
+++ b/pw_sync_stl/BUILD
@@ -16,6 +16,10 @@
     "//pw_build:pigweed.bzl",
     "pw_cc_library",
 )
+load(
+    "//pw_build:selects.bzl",
+    "TARGET_COMPATIBLE_WITH_HOST_SELECT",
+)
 
 package(default_visibility = ["//visibility:public"])
 
@@ -33,6 +37,7 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_chrono:system_clock",
     ],
@@ -43,8 +48,10 @@
     srcs = [
         "binary_semaphore.cc",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":binary_semaphore_headers",
+        "//pw_assert",
         "//pw_chrono:system_clock",
         "//pw_sync:binary_semaphore_facade",
     ],
@@ -62,6 +69,7 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_chrono:system_clock",
     ],
@@ -72,8 +80,10 @@
     srcs = [
         "counting_semaphore.cc",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":counting_semaphore_headers",
+        "//pw_assert",
         "//pw_chrono:system_clock",
         "//pw_sync:counting_semaphore_facade",
     ],
@@ -91,13 +101,12 @@
         "public",
         "public_overrides",
     ],
-    deps = [
-        "//pw_sync:mutex_facade",
-    ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
 )
 
 pw_cc_library(
     name = "mutex",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":mutex_headers",
         "//pw_sync:mutex_facade",
@@ -114,14 +123,15 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_chrono:system_clock",
-        "//pw_sync:timed_mutex_facade",
     ],
 )
 
 pw_cc_library(
     name = "timed_mutex",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":timed_mutex_headers",
         "//pw_sync:timed_mutex_facade",
@@ -140,10 +150,15 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
+    deps = [
+        "//pw_sync:yield_core",
+    ],
 )
 
 pw_cc_library(
     name = "interrupt_spin_lock",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":interrupt_spin_lock_headers",
         "//pw_sync:interrupt_spin_lock_facade",
diff --git a/pw_sync_threadx/BUILD b/pw_sync_threadx/BUILD
index b9129f9..ca58c46 100644
--- a/pw_sync_threadx/BUILD
+++ b/pw_sync_threadx/BUILD
@@ -33,6 +33,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         # TODO: This should depend on ThreadX but our third parties currently
         # do not have Bazel support.
@@ -45,6 +48,9 @@
     srcs = [
         "binary_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":binary_semaphore_headers",
         "//pw_chrono_threadx:system_clock_headers",
@@ -65,6 +71,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         # TODO: This should depend on ThreadX but our third parties currently
         # do not have Bazel support.
@@ -77,6 +86,9 @@
     srcs = [
         "counting_semaphore.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":counting_semaphore_headers",
         "//pw_chrono_threadx:system_clock_headers",
@@ -97,6 +109,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         # TODO: This should depend on ThreadX but our third parties currently
         # do not have Bazel support.
@@ -106,6 +121,9 @@
 
 pw_cc_library(
     name = "mutex",
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":mutex_headers",
         "//pw_sync:mutex_facade",
@@ -122,6 +140,9 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         # TODO: This should depend on ThreadX but our third parties currently
         # do not have Bazel support.
@@ -135,6 +156,9 @@
     srcs = [
         "timed_mutex.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":timed_mutex_headers",
         "//pw_chrono_threadx:system_clock_headers",
@@ -157,6 +181,9 @@
     ],
     # TODO: This should depend on ThreadX but our third parties currently
     # do not have Bazel support.
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
 )
 
 pw_cc_library(
@@ -164,6 +191,9 @@
     srcs = [
         "interrupt_spin_lock.cc",
     ],
+    target_compatible_with = [
+        "//pw_build/constraints/rtos:threadx",
+    ],
     deps = [
         ":interrupt_spin_lock_headers",
         "//pw_sync:interrupt_spin_lock_facade",
diff --git a/pw_sys_io/BUILD b/pw_sys_io/BUILD
index 11e8201..cf1ecc3 100644
--- a/pw_sys_io/BUILD
+++ b/pw_sys_io/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
 )
 
@@ -21,7 +22,7 @@
 
 licenses(["notice"])
 
-pw_cc_library(
+pw_cc_facade(
     name = "facade",
     hdrs = ["public/pw_sys_io/sys_io.h"],
     includes = ["public"],
@@ -48,8 +49,16 @@
         ":facade",
         "//pw_span",
         "//pw_status",
-        # For now, hard-code to depend on stdio until bazel build is updated
-        # to support multiple target configurations.
-        "//pw_sys_io_stdio",
+        "@pigweed_config//:pw_sys_io_backend",
     ],
 )
+
+pw_cc_library(
+    name = "backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//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"],
+    }),
+)
diff --git a/pw_sys_io_baremetal_lm3s6965evb/BUILD b/pw_sys_io_baremetal_lm3s6965evb/BUILD
index 78bb467..6e6dc73 100644
--- a/pw_sys_io_baremetal_lm3s6965evb/BUILD
+++ b/pw_sys_io_baremetal_lm3s6965evb/BUILD
@@ -25,8 +25,12 @@
     name = "pw_sys_io_baremetal_lm3s6965evb",
     srcs = ["sys_io_baremetal.cc"],
     hdrs = ["public/pw_sys_io_baremetal_lm3s6965evb/init.h"],
+    target_compatible_with = [
+        "//pw_build/constraints/chipset:lm3s6965evb",
+        "@platforms//os:none",
+    ],
     deps = [
         "//pw_preprocessor",
-        "//pw_sys_io",
+        "//pw_sys_io:facade",
     ],
 )
diff --git a/pw_sys_io_baremetal_stm32f429/BUILD b/pw_sys_io_baremetal_stm32f429/BUILD
index 80b0280..9edd4e6 100644
--- a/pw_sys_io_baremetal_stm32f429/BUILD
+++ b/pw_sys_io_baremetal_stm32f429/BUILD
@@ -26,7 +26,8 @@
     srcs = ["sys_io_baremetal.cc"],
     hdrs = ["public/pw_sys_io_baremetal_stm32f429/init.h"],
     target_compatible_with = [
-        "//pw_build/constraints/boards:stm32f429i-disc1",
+        "//pw_build/constraints/chipset:stm32f429",
+        "@platforms//os:none",
     ],
     deps = [
         "//pw_boot_armv7m",
diff --git a/pw_sys_io_stdio/BUILD b/pw_sys_io_stdio/BUILD
index 333bd54..6741bbb 100644
--- a/pw_sys_io_stdio/BUILD
+++ b/pw_sys_io_stdio/BUILD
@@ -16,6 +16,10 @@
     "//pw_build:pigweed.bzl",
     "pw_cc_library",
 )
+load(
+    "//pw_build:selects.bzl",
+    "TARGET_COMPATIBLE_WITH_HOST_SELECT",
+)
 
 package(default_visibility = ["//visibility:public"])
 
@@ -24,6 +28,7 @@
 pw_cc_library(
     name = "pw_sys_io_stdio",
     srcs = ["sys_io.cc"],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_sys_io:default_putget_bytes",
         "//pw_sys_io:facade",
diff --git a/pw_thread/BUILD b/pw_thread/BUILD
index c2b67b1..9c8c456 100644
--- a/pw_thread/BUILD
+++ b/pw_thread/BUILD
@@ -14,6 +14,7 @@
 
 load(
     "//pw_build:pigweed.bzl",
+    "pw_cc_facade",
     "pw_cc_library",
     "pw_cc_test",
 )
@@ -22,52 +23,40 @@
 
 licenses(["notice"])  # Apache License 2.0
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_THREAD_ID_BACKEND = "//pw_thread_stl:id"
-
-PW_THREAD_SLEEP_BACKEND = "//pw_thread_stl:sleep"
-
-PW_THREAD_THREAD_BACKEND = "//pw_thread_stl:thread"
-
-PW_THREAD_YIELD_BACKEND = "//pw_thread_stl:yield"
-
-pw_cc_library(
+pw_cc_facade(
     name = "id_facade",
     hdrs = [
         "public/pw_thread/id.h",
     ],
     includes = ["public"],
-    deps = [
-        PW_THREAD_ID_BACKEND + "_headers",
-    ],
 )
 
 pw_cc_library(
     name = "id",
     deps = [
         ":id_facade",
-        PW_THREAD_ID_BACKEND + "_headers",
+        "@pigweed_config//:pw_thread_id_backend",
     ],
 )
 
 pw_cc_library(
-    name = "id_backend",
-    deps = [
-        PW_THREAD_ID_BACKEND,
-    ],
+    name = "id_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//pw_build/constraints/rtos:embos": ["//pw_thread_embos:id"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_thread_freertos:id"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_thread_threadx:id"],
+        "//conditions:default": ["//pw_thread_stl:id"],
+    }),
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "sleep_facade",
-    srcs = [
-        "sleep.cc",
-    ],
     hdrs = [
         "public/pw_thread/sleep.h",
     ],
     includes = ["public"],
     deps = [
-        PW_THREAD_SLEEP_BACKEND + "_headers",
         "//pw_chrono:system_clock",
         "//pw_preprocessor",
     ],
@@ -75,20 +64,28 @@
 
 pw_cc_library(
     name = "sleep",
+    srcs = [
+        "sleep.cc",
+    ],
     deps = [
+        ":id",
         ":sleep_facade",
-        PW_THREAD_SLEEP_BACKEND + "_headers",
+        "@pigweed_config//:pw_thread_sleep_backend",
     ],
 )
 
 pw_cc_library(
-    name = "sleep_backend",
-    deps = [
-        PW_THREAD_SLEEP_BACKEND,
-    ],
+    name = "sleep_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//pw_build/constraints/rtos:embos": ["//pw_thread_embos:sleep"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_thread_freertos:sleep"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_thread_threadx:sleep"],
+        "//conditions:default": ["//pw_thread_stl:sleep"],
+    }),
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "thread_facade",
     hdrs = [
         "public/pw_thread/thread.h",
@@ -97,7 +94,6 @@
     includes = ["public"],
     deps = [
         ":id_facade",
-        PW_THREAD_THREAD_BACKEND + "_headers",
     ],
 )
 
@@ -107,17 +103,22 @@
         "thread.cc",
     ],
     deps = [
+        ":id",
         ":thread_core",
         ":thread_facade",
-        PW_THREAD_THREAD_BACKEND + "_headers",
+        "@pigweed_config//:pw_thread_thread_backend",
     ],
 )
 
 pw_cc_library(
-    name = "thread_backend",
-    deps = [
-        PW_THREAD_THREAD_BACKEND,
-    ],
+    name = "thread_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//pw_build/constraints/rtos:embos": ["//pw_thread_embos:thread"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_thread_freertos:thread"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_thread_threadx:thread"],
+        "//conditions:default": ["//pw_thread_stl:thread"],
+    }),
 )
 
 pw_cc_library(
@@ -128,34 +129,38 @@
     includes = ["public"],
 )
 
-pw_cc_library(
+pw_cc_facade(
     name = "yield_facade",
-    srcs = [
-        "yield.cc",
-    ],
     hdrs = [
         "public/pw_thread/yield.h",
     ],
     includes = ["public"],
     deps = [
-        PW_THREAD_YIELD_BACKEND + "_headers",
         "//pw_preprocessor",
     ],
 )
 
 pw_cc_library(
     name = "yield",
+    srcs = [
+        "yield.cc",
+    ],
     deps = [
+        ":id",
         ":yield_facade",
-        PW_THREAD_YIELD_BACKEND + "_headers",
+        "@pigweed_config//:pw_thread_yield_backend",
     ],
 )
 
 pw_cc_library(
-    name = "yield_backend",
-    deps = [
-        PW_THREAD_YIELD_BACKEND,
-    ],
+    name = "yield_backend_multiplexer",
+    visibility = ["@pigweed_config//:__pkg__"],
+    deps = select({
+        "//pw_build/constraints/rtos:embos": ["//pw_thread_embos:yield"],
+        "//pw_build/constraints/rtos:freertos": ["//pw_thread_freertos:yield"],
+        "//pw_build/constraints/rtos:threadx": ["//pw_thread_threadx:yield"],
+        "//conditions:default": ["//pw_thread_stl:yield"],
+    }),
 )
 
 pw_cc_library(
diff --git a/pw_thread_stl/BUILD b/pw_thread_stl/BUILD
index 6403ef2..0555a08 100644
--- a/pw_thread_stl/BUILD
+++ b/pw_thread_stl/BUILD
@@ -17,6 +17,10 @@
     "pw_cc_library",
     "pw_cc_test",
 )
+load(
+    "//pw_build:selects.bzl",
+    "TARGET_COMPATIBLE_WITH_HOST_SELECT",
+)
 
 package(default_visibility = ["//visibility:public"])
 
@@ -34,10 +38,12 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
 )
 
 pw_cc_library(
     name = "id",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":id_headers",
         "//pw_thread:id_facade",
@@ -54,6 +60,7 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_chrono:system_clock",
     ],
@@ -61,6 +68,7 @@
 
 pw_cc_library(
     name = "sleep",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":sleep_headers",
         "//pw_chrono:system_clock",
@@ -81,10 +89,12 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
 )
 
 pw_cc_library(
     name = "thread",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":thread_headers",
         "//pw_thread:thread_facade",
@@ -96,6 +106,7 @@
     srcs = [
         "test_threads.cc",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         "//pw_thread:test_threads_header",
         "//pw_thread:thread_facade",
@@ -104,6 +115,7 @@
 
 pw_cc_test(
     name = "thread_backend_test",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":test_threads",
         "//pw_thread:thread_facade_test",
@@ -120,10 +132,12 @@
         "public",
         "public_overrides",
     ],
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
 )
 
 pw_cc_library(
     name = "yield",
+    target_compatible_with = select(TARGET_COMPATIBLE_WITH_HOST_SELECT),
     deps = [
         ":yield_headers",
         "//pw_thread:yield_facade",
diff --git a/pw_tokenizer/BUILD b/pw_tokenizer/BUILD
index 4b288be..49d2eea 100644
--- a/pw_tokenizer/BUILD
+++ b/pw_tokenizer/BUILD
@@ -12,6 +12,7 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+load("@rules_cc//cc:defs.bzl", "cc_binary")
 load(
     "//pw_build:pigweed.bzl",
     "pw_cc_binary",
@@ -53,14 +54,9 @@
     ],
 )
 
-# TODO(pwbug/101): Need to add support for facades/backends to Bazel.
-PW_TOKENIZER_GLOBAL_HANDLER_BACKEND = "//pw_tokenizer:test_backend"
-
-PW_TOKENIZER_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND = "//pw_tokenizer:test_backend"
-
 pw_cc_library(
     name = "test_backend",
-    visibility = ["//visibility:private"],
+    visibility = ["@pigweed_config//:__pkg__"],
 )
 
 pw_cc_library(
@@ -69,7 +65,7 @@
     hdrs = ["public/pw_tokenizer/tokenize_to_global_handler.h"],
     deps = [
         ":pw_tokenizer",
-        PW_TOKENIZER_GLOBAL_HANDLER_BACKEND,
+        "@pigweed_config//:pw_tokenizer_global_handler_backend",
     ],
 )
 
@@ -79,7 +75,7 @@
     hdrs = ["public/pw_tokenizer/tokenize_to_global_handler_with_payload.h"],
     deps = [
         ":pw_tokenizer",
-        PW_TOKENIZER_GLOBAL_HANDLER_WITH_PAYLOAD_BACKEND,
+        "@pigweed_config//:pw_tokenizer_global_handler_with_payload_backend",
     ],
 )
 
@@ -93,6 +89,7 @@
     ],
     includes = ["public"],
     deps = [
+        ":pw_tokenizer",
         "//pw_base64",
         "//pw_preprocessor",
         "//pw_span",
@@ -124,8 +121,15 @@
     name = "generate_decoding_test_data",
     srcs = [
         "generate_decoding_test_data.cc",
-        "tokenize_test_fakes.cc",
     ],
+    target_compatible_with = select(
+        {
+            "@platforms//os:linux": [],
+            "@platforms//os:windows": [],
+            "@platforms//os:macos": [],
+            "//conditions:default": ["@platforms//:incompatible"],
+        },
+    ),
     deps = [
         ":decoder",
         ":pw_tokenizer",
@@ -155,7 +159,6 @@
         "argument_types_test.cc",
         "argument_types_test_c.c",
         "pw_tokenizer_private/argument_types_test.h",
-        "tokenize_test_fakes.cc",
     ],
     deps = [
         ":pw_tokenizer",
@@ -219,7 +222,6 @@
     srcs = [
         "hash_test.cc",
         "pw_tokenizer_private/generated_hash_test_cases.h",
-        "tokenize_test_fakes.cc",
     ],
     deps = [
         ":pw_tokenizer",
@@ -234,6 +236,8 @@
         "simple_tokenize_test.cc",
     ],
     deps = [
+        ":global_handler",
+        ":global_handler_with_payload",
         ":pw_tokenizer",
         "//pw_unit_test",
     ],
diff --git a/targets/default_config.BUILD b/targets/default_config.BUILD
index d6287ef..58fdba9 100644
--- a/targets/default_config.BUILD
+++ b/targets/default_config.BUILD
@@ -98,3 +98,8 @@
     name = "pw_sys_io_backend",
     build_setting_default = "@pigweed//pw_sys_io:backend_multiplexer",
 )
+
+label_flag(
+    name = "target_rtos",
+    build_setting_default = "@pigweed//pw_build/constraints/rtos:none",
+)