workspace: Adds support for Bazel facades/backends

This makes use of Bazel's configuration feature 'label_flag' to create
a set of configurations that have overridable defaults from the command
line.

No-Docs-Update-Reason: Docs further up the stack in 41561.
Change-Id: Id4064c8f11bc6ec468aad18ef4d02fa472fdc590
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/41560
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Reviewed-by: Akira Baruah <akirabaruah@google.com>
Commit-Queue: Keir Mierle <keir@google.com>
diff --git a/WORKSPACE b/WORKSPACE
index b87d7dd..a34cacf 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -215,3 +215,11 @@
     strip_prefix = "buildtools-4.0.1",
     url = "https://github.com/bazelbuild/buildtools/archive/4.0.1.tar.gz",
 )
+
+load("//pw_build:target_config.bzl", "pigweed_config")
+
+# Configure Pigweeds backend.
+pigweed_config(
+    name = "pigweed_config",
+    build_file = "//targets:default_config.BUILD",
+)
diff --git a/pw_build/pigweed.bzl b/pw_build/pigweed.bzl
index 3cc0de1..2b16982 100644
--- a/pw_build/pigweed.bzl
+++ b/pw_build/pigweed.bzl
@@ -12,6 +12,8 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+load("@rules_cc//cc:defs.bzl", "cc_library")
+
 """Pigweed build environment for bazel."""
 
 DEBUGGING = [
@@ -104,7 +106,7 @@
     cc_kwargs, c_kwargs = _default_cc_and_c_kwargs(kwargs)
 
     if c_kwargs:
-        native.cc_library(**c_kwargs)
+        cc_library(**c_kwargs)
 
     target(**cc_kwargs)
 
@@ -117,3 +119,15 @@
 def pw_cc_test(**kwargs):
     kwargs["deps"] = kwargs.get("deps", []) + ["//pw_unit_test:main"]
     _add_cc_and_c_targets(native.cc_test, kwargs)
+
+def pw_cc_facade(**kwargs):
+    # Bazel facades should be source only cc_library's this is to simplify
+    # lazy header evaluation. Bazel headers are not 'precompiled' so the build
+    # system does not check to see if the build has the right dependant headers
+    # in the sandbox. If a source file is declared here and includes a header
+    # file the toolchain will compile as normal and complain about the missing
+    # backend headers.
+    if "srcs" in kwargs.keys():
+        fail("'srcs' attribute does not exist in pw_cc_facade, please use \
+        main implementing target.")
+    _add_cc_and_c_targets(native.cc_library, kwargs)
diff --git a/pw_build/target_config.bzl b/pw_build/target_config.bzl
new file mode 100644
index 0000000..ebd6e74
--- /dev/null
+++ b/pw_build/target_config.bzl
@@ -0,0 +1,59 @@
+# 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.
+
+def _pigweed_config_impl(repository_ctx):
+    if repository_ctx.attr.build_file_content and \
+       repository_ctx.attr.build_file:
+        fail("Attributes 'build_file_content' and 'build_file' cannot both be \
+        defined at the same time.")
+    if not repository_ctx.attr.build_file_content and \
+       not repository_ctx.attr.build_file:
+        fail("Either 'build_file_content' or 'build_file' must be defined.")
+
+    if repository_ctx.name != "pigweed_config":
+        fail("This repository should be name 'pigweed_config'")
+
+    if repository_ctx.attr.build_file_content:
+        repository_ctx.file("BUILD", repository_ctx.attr.build_file_content)
+
+    if repository_ctx.attr.build_file:
+        repository_ctx.template("BUILD", repository_ctx.attr.build_file, {})
+
+pigweed_config = repository_rule(
+    _pigweed_config_impl,
+    attrs = {
+        "build_file_content": attr.string(
+            doc = "The build file content to configure Pigweed.",
+            mandatory = False,
+            default = "",
+        ),
+        "build_file": attr.label(
+            doc = "The label for the Pigweed config build file to use.",
+            mandatory = False,
+            default = "@pigweed//targets/host:host_config.BUILD",
+        ),
+    },
+    doc = """
+Configure Pigweeds backend implementations.
+
+Example:
+    # WORKSPACE
+    pigweed_config(
+        # This must use the exact name specified here otherwise this
+        # remote repository will not function as expected.
+        name = "pigweed_config",
+        build_file = "//path/to/config.BUILD",
+    )
+""",
+)
diff --git a/targets/BUILD b/targets/BUILD
new file mode 100644
index 0000000..486d1ed
--- /dev/null
+++ b/targets/BUILD
@@ -0,0 +1,13 @@
+# 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.
diff --git a/targets/default_config.BUILD b/targets/default_config.BUILD
new file mode 100644
index 0000000..d6287ef
--- /dev/null
+++ b/targets/default_config.BUILD
@@ -0,0 +1,100 @@
+# 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"])
+
+label_flag(
+    name = "pw_log_backend",
+    build_setting_default = "@pigweed//pw_log:backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_assert_backend",
+    build_setting_default = "@pigweed//pw_assert:backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_chrono_backend",
+    build_setting_default = "@pigweed//pw_chrono:backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_sync_binary_semaphore_backend",
+    build_setting_default = "@pigweed//pw_sync:binary_semaphore_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_sync_counting_semaphore_backend",
+    build_setting_default = "@pigweed//pw_sync:counting_semaphore_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_sync_mutex_backend",
+    build_setting_default = "@pigweed//pw_sync:mutex_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_sync_timed_mutex_backend",
+    build_setting_default = "@pigweed//pw_sync:timed_mutex_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_sync_interrupt_spin_lock_backend",
+    build_setting_default = "@pigweed//pw_sync:interrupt_spin_lock_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_interrupt_backend",
+    build_setting_default = "@pigweed//pw_interrupt:backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_malloc_backend",
+    build_setting_default = "@pigweed//pw_malloc:backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_thread_id_backend",
+    build_setting_default = "@pigweed//pw_thread:id_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_thread_sleep_backend",
+    build_setting_default = "@pigweed//pw_thread:sleep_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_thread_thread_backend",
+    build_setting_default = "@pigweed//pw_thread:thread_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_thread_yield_backend",
+    build_setting_default = "@pigweed//pw_thread:yield_backend_multiplexer",
+)
+
+label_flag(
+    name = "pw_tokenizer_global_handler_backend",
+    build_setting_default = "@pigweed//pw_tokenizer:test_backend",
+)
+
+label_flag(
+    name = "pw_tokenizer_global_handler_with_payload_backend",
+    build_setting_default = "@pigweed//pw_tokenizer:test_backend",
+)
+
+label_flag(
+    name = "pw_sys_io_backend",
+    build_setting_default = "@pigweed//pw_sys_io:backend_multiplexer",
+)