Add flags to cc_shared_library for easier debugging

--//examples:incompatible_link_once=False[default = False]
When True, it will be an error to link the same library more than once
unless it has the tag LINKABLE_MORE_THAN_ONCE

--//examples:experimental_debug=True[default = False]
When True, it will generate files listing the exports of each cc_shared_library
and which libraries are linked to it statically.

RELNOTES:none
PiperOrigin-RevId: 311323625
Change-Id: I340cc71965650f7c9dd7ef7fb9656da362021527
diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml
index fdee8b7..f227fc0 100644
--- a/.bazelci/presubmit.yml
+++ b/.bazelci/presubmit.yml
@@ -53,8 +53,10 @@
     - "//examples/test_cc_shared_library/..."
     build_flags:
     - "--experimental_cc_shared_library"
+    - "--//examples:incompatible_link_once=True"
     test_flags:
     - "--test_timeout=120"
     - "--experimental_cc_shared_library"
+    - "--//examples:incompatible_link_once=True"
     test_targets:
     - "//examples/test_cc_shared_library/..."
diff --git a/examples/BUILD b/examples/BUILD
index d9178c1..0bfcd24 100644
--- a/examples/BUILD
+++ b/examples/BUILD
@@ -12,5 +12,19 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
+
 # A collection of examples showing the usage of rules_cc
 licenses(["notice"])
+
+bool_flag(
+    name = "incompatible_link_once",
+    build_setting_default = False,
+    visibility = ["//visibility:public"],
+)
+
+bool_flag(
+    name = "experimental_debug",
+    build_setting_default = False,
+    visibility = ["//visibility:public"],
+)
diff --git a/examples/experimental_cc_shared_library.bzl b/examples/experimental_cc_shared_library.bzl
index ed3124c..f4a738f 100644
--- a/examples/experimental_cc_shared_library.bzl
+++ b/examples/experimental_cc_shared_library.bzl
@@ -5,6 +5,7 @@
 --experimental_cc_shared_library
 """
 
+load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
 load("//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
 
 # TODO(#5200): Add export_define to library_to_link and cc_library
@@ -363,9 +364,23 @@
     for export in ctx.attr.roots:
         exports[str(export.label)] = True
 
+    debug_files = []
+    if ctx.attr._experimental_debug[BuildSettingInfo].value:
+        exports_debug_file = ctx.actions.declare_file(ctx.label.name + "_exports.txt")
+        ctx.actions.write(content = "\n".join(exports.keys()), output = exports_debug_file)
+
+        link_once_static_libs_debug_file = ctx.actions.declare_file(ctx.label.name + "_link_once_static_libs.txt")
+        ctx.actions.write(content = "\n".join(link_once_static_libs), output = link_once_static_libs_debug_file)
+
+        debug_files.append(exports_debug_file)
+        debug_files.append(link_once_static_libs_debug_file)
+
+    if not ctx.attr._incompatible_link_once[BuildSettingInfo].value:
+        link_once_static_libs = []
+
     return [
         DefaultInfo(
-            files = depset([linking_outputs.library_to_link.resolved_symlink_dynamic_library]),
+            files = depset([linking_outputs.library_to_link.resolved_symlink_dynamic_library] + debug_files),
             runfiles = runfiles,
         ),
         CcSharedLibraryInfo(
@@ -439,6 +454,8 @@
         "static_deps": attr.string_list(),
         "user_link_flags": attr.string_list(),
         "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"),
+        "_experimental_debug": attr.label(default = "//examples:experimental_debug"),
+        "_incompatible_link_once": attr.label(default = "//examples:incompatible_link_once"),
     },
     toolchains = ["@rules_cc//cc:toolchain_type"],  # copybara-use-repo-external-label
     fragments = ["cpp"],