C++: Allow libraries to be exported by any target
Any library should be exportable by any cc_shared_library target regardless of whether the cc_shared_library target is in the same package or a parent package as long as the library author gives permission.
The library author can now do this by writing tags=["exported_by=//foo,//baz"].
PiperOrigin-RevId: 295137965
Change-Id: I4acffd26981fedd6cb0c505e2691da0c70a7b6b0
diff --git a/examples/experimental_cc_shared_library.bzl b/examples/experimental_cc_shared_library.bzl
index 49b9b8e..0ab7ee6 100644
--- a/examples/experimental_cc_shared_library.bzl
+++ b/examples/experimental_cc_shared_library.bzl
@@ -12,6 +12,7 @@
GraphNodeInfo = provider(
fields = {
"children": "Other GraphNodeInfo from dependencies of this target",
+ "exported_by": "Labels of targets that can export the library of this node",
"label": "Label of the target visited",
},
)
@@ -259,10 +260,19 @@
fail("Trying to export a library already exported by a different shared library: " +
str(export.label))
- if not _same_package_or_above(ctx.label, export[GraphNodeInfo].label):
+ can_be_exported = _same_package_or_above(ctx.label, export.label)
+
+ if not can_be_exported:
+ for exported_by in export[GraphNodeInfo].exported_by:
+ target_specified = _is_target_specified(exported_by)
+ exported_by_label = Label(exported_by)
+ if _check_if_target_under_path(ctx.label, exported_by_label, target_specified):
+ can_be_exported = True
+ break
+ if not can_be_exported:
fail(str(export.label) + " cannot be exported from " + str(ctx.label) +
- " because " + str(export.label) + " is not in the same package " +
- " or a sub-package")
+ " because it's not in the same package/subpackage or the library " +
+ "to be exported doesn't have this cc_shared_library in the exported_by tag.")
preloaded_deps_direct_labels = {}
preloaded_dep_merged_cc_info = None
@@ -348,9 +358,24 @@
if GraphNodeInfo in dep:
children.append(dep[GraphNodeInfo])
+ exported_by = []
+ if hasattr(ctx.rule.attr, "tags"):
+ for tag in ctx.rule.attr.tags:
+ if tag.startswith("exported_by=") and len(tag) > 12:
+ for target in tag[12:].split(","):
+ # Only absolute labels allowed. Targets in same package
+ # or subpackage can be exported anyway.
+ if not target.startswith("//") and not target.startswith("@"):
+ fail("Labels in exported_by of " + str(target) +
+ " must be absolute.")
+
+ Label(target) # Checking synthax is ok.
+ exported_by.append(target)
+
return [GraphNodeInfo(
label = ctx.label,
children = children,
+ exported_by = exported_by,
)]
graph_structure_aspect = aspect(
diff --git a/examples/test_cc_shared_library/BUILD b/examples/test_cc_shared_library/BUILD
index 93090c4..a28799c 100644
--- a/examples/test_cc_shared_library/BUILD
+++ b/examples/test_cc_shared_library/BUILD
@@ -85,6 +85,7 @@
exports = [
"bar",
"bar2",
+ "@test_repo//:bar",
],
)
diff --git a/examples/test_cc_shared_library2/BUILD b/examples/test_cc_shared_library2/BUILD
index 802d60f..1789a5f 100644
--- a/examples/test_cc_shared_library2/BUILD
+++ b/examples/test_cc_shared_library2/BUILD
@@ -4,5 +4,6 @@
name = "bar",
srcs = ["bar.cc"],
hdrs = ["bar.h"],
+ tags = ["exported_by=@rules_cc//examples/test_cc_shared_library:bar_so"],
visibility = ["//visibility:public"],
)