Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cbda5933 authored by Paul Duffin's avatar Paul Duffin Committed by Gerrit Code Review
Browse files

Merge "Add prebuilt_visibility property"

parents 0400ede3 157f40f0
Loading
Loading
Loading
Loading
+53 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android
import (
	"fmt"
	"regexp"
	"sort"
	"strings"
	"sync"

@@ -496,13 +497,63 @@ func packageDefaultVisibility(config Config, moduleId qualifiedModuleName) compo
	}
}

type VisibilityRuleSet interface {
	// Widen the visibility with some extra rules.
	Widen(extra []string) error

	Strings() []string
}

type visibilityRuleSet struct {
	rules []string
}

var _ VisibilityRuleSet = (*visibilityRuleSet)(nil)

func (v *visibilityRuleSet) Widen(extra []string) error {
	// Check the extra rules first just in case they are invalid. Otherwise, if
	// the current visibility is public then the extra rules will just be ignored.
	if len(extra) == 1 {
		singularRule := extra[0]
		switch singularRule {
		case "//visibility:public":
			// Public overrides everything so just discard any existing rules.
			v.rules = extra
			return nil
		case "//visibility:private":
			// Extending rule with private is an error.
			return fmt.Errorf("%q does not widen the visibility", singularRule)
		}
	}

	if len(v.rules) == 1 {
		switch v.rules[0] {
		case "//visibility:public":
			// No point in adding rules to something which is already public.
			return nil
		case "//visibility:private":
			// Adding any rules to private means it is no longer private so the
			// private can be discarded.
			v.rules = nil
		}
	}

	v.rules = FirstUniqueStrings(append(v.rules, extra...))
	sort.Strings(v.rules)
	return nil
}

func (v *visibilityRuleSet) Strings() []string {
	return v.rules
}

// Get the effective visibility rules, i.e. the actual rules that affect the visibility of the
// property irrespective of where they are defined.
//
// Includes visibility rules specified by package default_visibility and/or on defaults.
// Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g.
// //package/containing/rule:__subpackages__.
func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string {
func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) VisibilityRuleSet {
	moduleName := ctx.OtherModuleName(module)
	dir := ctx.OtherModuleDir(module)
	qualified := qualifiedModuleName{dir, moduleName}
@@ -527,7 +578,7 @@ func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string {
		rule = append(rule, packageRule{dir})
	}

	return rule.Strings()
	return &visibilityRuleSet{rule.Strings()}
}

// Clear the default visibility properties so they can be replaced.
+46 −0
Original line number Diff line number Diff line
@@ -1270,3 +1270,49 @@ func newMockParentFactory() Module {
	})
	return m
}

func testVisibilityRuleSet(t *testing.T, rules, extra, expected []string) {
	t.Helper()
	set := &visibilityRuleSet{rules}
	err := set.Widen(extra)
	if err != nil {
		t.Error(err)
		return
	}
	actual := set.Strings()
	if !reflect.DeepEqual(actual, expected) {
		t.Errorf("mismatching rules after extend: expected %#v, actual %#v", expected, actual)
	}
}

func TestVisibilityRuleSet(t *testing.T) {
	t.Run("extend empty", func(t *testing.T) {
		testVisibilityRuleSet(t, nil, []string{"//foo"}, []string{"//foo"})
	})
	t.Run("extend", func(t *testing.T) {
		testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar"}, []string{"//bar", "//foo"})
	})
	t.Run("extend duplicate", func(t *testing.T) {
		testVisibilityRuleSet(t, []string{"//foo"}, []string{"//bar", "//foo"}, []string{"//bar", "//foo"})
	})
	t.Run("extend public", func(t *testing.T) {
		testVisibilityRuleSet(t, []string{"//visibility:public"}, []string{"//foo"}, []string{"//visibility:public"})
	})
	t.Run("extend private", func(t *testing.T) {
		testVisibilityRuleSet(t, []string{"//visibility:private"}, []string{"//foo"}, []string{"//foo"})
	})
	t.Run("extend with public", func(t *testing.T) {
		testVisibilityRuleSet(t, []string{"//foo"}, []string{"//visibility:public"}, []string{"//visibility:public"})
	})
	t.Run("extend with private", func(t *testing.T) {
		t.Helper()
		set := &visibilityRuleSet{[]string{"//foo"}}
		err := set.Widen([]string{"//visibility:private"})
		expectedError := `"//visibility:private" does not widen the visibility`
		if err == nil {
			t.Errorf("missing error")
		} else if err.Error() != expectedError {
			t.Errorf("expected error %q found error %q", expectedError, err)
		}
	})
}
+17 −0
Original line number Diff line number Diff line
@@ -75,6 +75,20 @@ type sdkProperties struct {

	// True if this is a module_exports (or module_exports_snapshot) module type.
	Module_exports bool `blueprint:"mutated"`

	// The additional visibility to add to the prebuilt modules to allow them to
	// reference each other.
	//
	// This can only be used to widen the visibility of the members:
	//
	// * Specifying //visibility:public here will make all members visible and
	//   essentially ignore their own visibility.
	// * Specifying //visibility:private here is an error.
	// * Specifying any other rule here will add it to the members visibility and
	//   be output to the member prebuilt in the snapshot. Duplicates will be
	//   dropped. Adding a rule to members that have //visibility:private will
	//   cause the //visibility:private to be discarded.
	Prebuilt_visibility []string
}

// Contains information about the sdk properties that list sdk members, e.g.
@@ -211,6 +225,9 @@ func newSdkModule(moduleExports bool) *sdk {
	// properties for the member type specific list properties.
	s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
	s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)

	// Make sure that the prebuilt visibility property is verified for errors.
	android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)
	android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
	android.InitDefaultableModule(s)
	android.AddLoadHook(s, func(ctx android.LoadHookContext) {
+49 −2
Original line number Diff line number Diff line
@@ -108,6 +108,9 @@ func TestSnapshotVisibility(t *testing.T) {
				// generated sdk_snapshot.
				":__subpackages__",
			],
			prebuilt_visibility: [
				"//prebuilts/mysdk",
			],
			java_header_libs: [
				"myjavalib",
				"mypublicjavalib",
@@ -176,6 +179,7 @@ java_import {
    visibility: [
        "//other/foo",
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/myjavalib.jar"],
}
@@ -186,6 +190,7 @@ java_import {
    visibility: [
        "//other/foo",
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/myjavalib.jar"],
}
@@ -210,6 +215,7 @@ java_import {
    visibility: [
        "//other/bar",
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/mydefaultedjavalib.jar"],
}
@@ -220,6 +226,7 @@ java_import {
    visibility: [
        "//other/bar",
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/mydefaultedjavalib.jar"],
}
@@ -227,14 +234,20 @@ java_import {
java_import {
    name: "mysdk_myprivatejavalib@current",
    sdk_member_name: "myprivatejavalib",
    visibility: ["//package"],
    visibility: [
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/myprivatejavalib.jar"],
}

java_import {
    name: "myprivatejavalib",
    prefer: false,
    visibility: ["//package"],
    visibility: [
        "//package",
        "//prebuilts/mysdk",
    ],
    jars: ["java/myprivatejavalib.jar"],
}

@@ -254,6 +267,40 @@ sdk_snapshot {
`))
}

func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) {
	testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, `
		sdk {
			name: "mysdk",
			prebuilt_visibility: [
				"//foo",
				"//visibility:private",
			],
		}
`)
}

func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) {
	testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, `
		sdk {
			name: "mysdk",
			prebuilt_visibility: [
				"//visibility:private",
			],
			java_header_libs: [
				"myjavalib",
			],
		}

		java_library {
			name: "myjavalib",
			// Uses package default visibility
			srcs: ["Test.java"],
			system_modules: "none",
			sdk_version: "none",
		}
`)
}

func TestSDkInstall(t *testing.T) {
	sdk := `
		sdk {
+10 −2
Original line number Diff line number Diff line
@@ -300,7 +300,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro
	snapshotModule.AddProperty("name", snapshotName)

	// Make sure that the snapshot has the same visibility as the sdk.
	visibility := android.EffectiveVisibilityRules(ctx, s)
	visibility := android.EffectiveVisibilityRules(ctx, s).Strings()
	if len(visibility) != 0 {
		snapshotModule.AddProperty("visibility", visibility)
	}
@@ -719,7 +719,15 @@ func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType
	} else {
		// Extract visibility information from a member variant. All variants have the same
		// visibility so it doesn't matter which one is used.
		visibility := android.EffectiveVisibilityRules(s.ctx, variant)
		visibilityRules := android.EffectiveVisibilityRules(s.ctx, variant)

		// Add any additional visibility rules needed for the prebuilts to reference each other.
		err := visibilityRules.Widen(s.sdk.properties.Prebuilt_visibility)
		if err != nil {
			s.ctx.PropertyErrorf("prebuilt_visibility", "%s", err)
		}

		visibility := visibilityRules.Strings()
		if len(visibility) != 0 {
			m.AddProperty("visibility", visibility)
		}