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
This commit is contained in:
Googler 2020-02-14 06:58:52 -08:00 committed by Copybara-Service
parent a2060ec7c9
commit 810a11e772
3 changed files with 30 additions and 3 deletions

View File

@ -12,6 +12,7 @@ load("//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
GraphNodeInfo = provider( GraphNodeInfo = provider(
fields = { fields = {
"children": "Other GraphNodeInfo from dependencies of this target", "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", "label": "Label of the target visited",
}, },
) )
@ -259,10 +260,19 @@ def _cc_shared_library_impl(ctx):
fail("Trying to export a library already exported by a different shared library: " + fail("Trying to export a library already exported by a different shared library: " +
str(export.label)) 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) + fail(str(export.label) + " cannot be exported from " + str(ctx.label) +
" because " + str(export.label) + " is not in the same package " + " because it's not in the same package/subpackage or the library " +
" or a sub-package") "to be exported doesn't have this cc_shared_library in the exported_by tag.")
preloaded_deps_direct_labels = {} preloaded_deps_direct_labels = {}
preloaded_dep_merged_cc_info = None preloaded_dep_merged_cc_info = None
@ -348,9 +358,24 @@ def _graph_structure_aspect_impl(target, ctx):
if GraphNodeInfo in dep: if GraphNodeInfo in dep:
children.append(dep[GraphNodeInfo]) 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( return [GraphNodeInfo(
label = ctx.label, label = ctx.label,
children = children, children = children,
exported_by = exported_by,
)] )]
graph_structure_aspect = aspect( graph_structure_aspect = aspect(

View File

@ -85,6 +85,7 @@ cc_shared_library(
exports = [ exports = [
"bar", "bar",
"bar2", "bar2",
"@test_repo//:bar",
], ],
) )

View File

@ -4,5 +4,6 @@ cc_library(
name = "bar", name = "bar",
srcs = ["bar.cc"], srcs = ["bar.cc"],
hdrs = ["bar.h"], hdrs = ["bar.h"],
tags = ["exported_by=@rules_cc//examples/test_cc_shared_library:bar_so"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )