pw_build: Support specifying final link dependencies

- pw_build_LINK_DEPS is a list of build targets that are linked into
  all build artifacts produced by pw_executable, pw_static_library, and
  pw_shared_library.
- Add a ":deps" group to the pw_assert build interface. Require
  $dir_pw_assert:deps to be listed in pw_build_LINK_DEPS if
  pw_assert_BACKEND is set.

Change-Id: Icc01dbe86f95d971e76aa357c7b7174ce85546ba
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/43521
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
diff --git a/pw_assert/BUILD.gn b/pw_assert/BUILD.gn
index 2b78c00..0362da6 100644
--- a/pw_assert/BUILD.gn
+++ b/pw_assert/BUILD.gn
@@ -83,6 +83,46 @@
   public_deps = [ dir_pw_preprocessor ]
 }
 
+# pw_assert is low-level and ubiquitous. Because of this, it can often cause
+# circular dependencies. This target collects dependencies from the backend that
+# cannot be used because they would cause circular deps.
+#
+# This group ("$dir_pw_assert:deps") must listed in pw_build_LINK_DEPS if
+# pw_assert_BACKEND is set.
+#
+# pw_assert backends must provide their own "deps" group that collects their
+# actual dependencies. The backend "deps" group may be empty.
+group("deps") {
+  public_deps = []
+
+  if (pw_assert_BACKEND != "") {
+    public_deps += [ get_label_info(pw_assert_BACKEND, "dir") + ":deps" ]
+
+    # Make sure this target is listed in pw_build_LINK_DEPS. This
+    # ensures these dependencies are available during linking, even if nothing
+    # else in the build depends on them.
+    _deps_label = get_label_info(":$target_name", "label_no_toolchain")
+    _deps_is_in_link_dependencies = false
+
+    foreach(label, pw_build_LINK_DEPS) {
+      if (get_label_info(label, "label_no_toolchain") == _deps_label) {
+        _deps_is_in_link_dependencies = true
+      }
+    }
+
+    # TODO(pwbug/372): Update projects with pw_assert to link the :deps target.
+    _disable_this_check_for_now = true
+    not_needed([
+                 "_deps_is_in_link_dependencies",
+                 "_deps_label",
+               ])
+
+    assert(_disable_this_check_for_now || _deps_is_in_link_dependencies,
+           "\$dir_pw_assert:$target_name must be listed in " +
+               "pw_build_LINK_DEPS when pw_assert_BACKEND is set")
+  }
+}
+
 # Note: While this is technically a test, doesn't verify any of the output and
 # is more of a compile test. The results can be visually verified if desired.
 pw_test("assert_test") {