Inherit default_visibility from parent package
Enhances the visibility mechanism to use the default_visibility
property of the closest ancestor package that has the property
specified.
Bug: 133290645
Test: m droid
Change-Id: I7248e9034a73894ac8d514f913316438c4d7c079
diff --git a/android/module.go b/android/module.go
index b912726..43b8763 100644
--- a/android/module.go
+++ b/android/module.go
@@ -226,11 +226,24 @@
return "//" + q.pkg + ":" + q.name
}
+func (q qualifiedModuleName) isRootPackage() bool {
+ return q.pkg == "" && q.name == ""
+}
+
// Get the id for the package containing this module.
func (q qualifiedModuleName) getContainingPackageId() qualifiedModuleName {
pkg := q.pkg
if q.name == "" {
- panic(fmt.Errorf("Cannot get containing package id of package module %s", pkg))
+ if pkg == "" {
+ panic(fmt.Errorf("Cannot get containing package id of root package"))
+ }
+
+ index := strings.LastIndex(pkg, "/")
+ if index == -1 {
+ pkg = ""
+ } else {
+ pkg = pkg[:index]
+ }
}
return newPackageId(pkg)
}
@@ -276,8 +289,15 @@
// If a module does not specify the `visibility` property then it uses the
// `default_visibility` property of the `package` module in the module's package.
//
+ // If a module does not specify the `visibility` property then it uses the
+ // `default_visibility` property of the `package` module in the module's package.
+ //
// If the `default_visibility` property is not set for the module's package then
- // the module uses `//visibility:legacy_public`.
+ // it will use the `default_visibility` of its closest ancestor package for which
+ // a `default_visibility` property is specified.
+ //
+ // If no `default_visibility` property can be found then the module uses the
+ // global default of `//visibility:legacy_public`.
//
// See https://android.googlesource.com/platform/build/soong/+/master/README.md#visibility for
// more details.
diff --git a/android/visibility.go b/android/visibility.go
index 2e01ff6..94af343 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -413,11 +413,7 @@
if ok {
rule = value.(compositeRule)
} else {
- packageQualifiedId := depQualified.getContainingPackageId()
- value, ok = moduleToVisibilityRule.Load(packageQualifiedId)
- if ok {
- rule = value.(compositeRule)
- }
+ rule = packageDefaultVisibility(ctx, depQualified)
}
if rule != nil && !rule.matches(qualified) {
ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
@@ -431,3 +427,20 @@
qualified := qualifiedModuleName{dir, moduleName}
return qualified
}
+
+func packageDefaultVisibility(ctx BaseModuleContext, moduleId qualifiedModuleName) compositeRule {
+ moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
+ packageQualifiedId := moduleId.getContainingPackageId()
+ for {
+ value, ok := moduleToVisibilityRule.Load(packageQualifiedId)
+ if ok {
+ return value.(compositeRule)
+ }
+
+ if packageQualifiedId.isRootPackage() {
+ return nil
+ }
+
+ packageQualifiedId = packageQualifiedId.getContainingPackageId()
+ }
+}
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 9a3e6aa..af6acf4 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -761,6 +761,64 @@
` visible to this module`,
},
},
+ {
+ name: "package default_visibility inherited to subpackages",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_visibility: ["//outsider"],
+ }
+
+ mock_library {
+ name: "libexample",
+ visibility: [":__subpackages__"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ mock_library {
+ name: "libnested",
+ deps: ["libexample"],
+ }`),
+ "outsider/Blueprints": []byte(`
+ mock_library {
+ name: "liboutsider",
+ deps: ["libexample", "libnested"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "liboutsider" variant "android_common": depends on //top:libexample which is not` +
+ ` visible to this module`,
+ },
+ },
+ {
+ name: "package default_visibility inherited to subpackages",
+ fs: map[string][]byte{
+ "top/Blueprints": []byte(`
+ package {
+ default_visibility: ["//visibility:private"],
+ }`),
+ "top/nested/Blueprints": []byte(`
+ package {
+ default_visibility: ["//outsider"],
+ }
+
+ mock_library {
+ name: "libnested",
+ }`),
+ "top/other/Blueprints": []byte(`
+ mock_library {
+ name: "libother",
+ }`),
+ "outsider/Blueprints": []byte(`
+ mock_library {
+ name: "liboutsider",
+ deps: ["libother", "libnested"],
+ }`),
+ },
+ expectedErrors: []string{
+ `module "liboutsider" variant "android_common": depends on //top/other:libother which is` +
+ ` not visible to this module`,
+ },
+ },
}
func TestVisibility(t *testing.T) {