Add //visibility:override to allow control over inheritance
Visibility rules can be 'inherited' in one of two ways. Either from
defaults or from a module that called ctx.CreateModule(...).
Previously, in both cases the inheriting module could only append
additional visibility rules to the end of the inherited rules. That
made it impossible to restrict the visibility by removing or ignore
inherited rules.
The //visibility:override rectifies that by allowing the inheriting
module to ignore all the rules that they would have inherited. It can
only go at the beginning of a list of rules specified in a module but
after defaults are applied it can end up in the middle of a list of
rules. In that case it behaves as if all the rules up to and including
the //visibility:override rule were discarded.
It can be used with //visibility:private to override
//visibility:public and vice versa.
Bug: 155787200
Test: m nothing
Change-Id: I8a9c9c5a1bdceaee387c08864ae2b34629e0d46f
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 4cf41a6..ca09345 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -636,6 +636,177 @@
},
},
{
+ name: "//visibility:private override //visibility:public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:public"],
+ }
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:private"],
+ defaults: ["libexample_defaults"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
+ },
+ },
+ {
+ name: "//visibility:public override //visibility:private",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:private"],
+ }
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:public"],
+ defaults: ["libexample_defaults"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libexample": visibility: cannot mix "//visibility:private" with any other visibility rules`,
+ },
+ },
+ {
+ name: "//visibility:override must be first in the list",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_library {
+ name: "libexample",
+ visibility: ["//other", "//visibility:override", "//namespace"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libexample": visibility: "//visibility:override" may only be used at the start of the visibility rules`,
+ },
+ },
+ {
+ name: "//visibility:override discards //visibility:private",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:private"],
+ }
+ mock_library {
+ name: "libexample",
+ // Make this visibility to //other but not //visibility:private
+ visibility: ["//visibility:override", "//other"],
+ defaults: ["libexample_defaults"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ },
+ },
+ {
+ name: "//visibility:override discards //visibility:public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:public"],
+ }
+ mock_library {
+ name: "libexample",
+ // Make this visibility to //other but not //visibility:public
+ visibility: ["//visibility:override", "//other"],
+ defaults: ["libexample_defaults"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ "namespace/Blueprints": []byte(`
+ mock_library {
+ name: "libnamespace",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+ },
+ },
+ {
+ name: "//visibility:override discards defaults supplied rules",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//namespace"],
+ }
+ mock_library {
+ name: "libexample",
+ // Make this visibility to //other but not //namespace
+ visibility: ["//visibility:override", "//other"],
+ defaults: ["libexample_defaults"],
+ }`),
+ "other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ deps: ["libexample"],
+ }`),
+ "namespace/Blueprints": []byte(`
+ mock_library {
+ name: "libnamespace",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+ },
+ },
+ {
+ name: "//visibility:override can override //visibility:public with //visibility:private",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:public"],
+ }
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:override", "//visibility:private"],
+ defaults: ["libexample_defaults"],
+ }`),
+ "namespace/Blueprints": []byte(`
+ mock_library {
+ name: "libnamespace",
+ deps: ["libexample"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "libnamespace" variant "android_common": depends on //top:libexample which is not visible to this module`,
+ },
+ },
+ {
+ name: "//visibility:override can override //visibility:private with //visibility:public",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ mock_defaults {
+ name: "libexample_defaults",
+ visibility: ["//visibility:private"],
+ }
+ mock_library {
+ name: "libexample",
+ visibility: ["//visibility:override", "//visibility:public"],
+ defaults: ["libexample_defaults"],
+ }`),
+ "namespace/Blueprints": []byte(`
+ mock_library {
+ name: "libnamespace",
+ deps: ["libexample"],
+ }`),
+ },
+ },
+ {
name: "//visibility:private mixed with itself",
fs: map[string][]byte{
"top/Blueprints": []byte(`