Prohibit dependencies outside of uses_sdks
When an APEX is built with uses_sdks, any depedndency from the APEX to the outside of the APEX should be from the SDKs that the APEX is built against. Bug: 138182343 Test: m Change-Id: I1c2ffe8d28ccf648d928ea59652c2d0070bf10eb
This commit is contained in:
parent
d7d5e5a1ac
commit
a7bc8ad0b9
|
@ -77,6 +77,10 @@ type ApexModule interface {
|
||||||
|
|
||||||
// Tests if this module is available for the specified APEX or ":platform"
|
// Tests if this module is available for the specified APEX or ":platform"
|
||||||
AvailableFor(what string) bool
|
AvailableFor(what string) bool
|
||||||
|
|
||||||
|
// DepIsInSameApex tests if the other module 'dep' is installed to the same
|
||||||
|
// APEX as this module
|
||||||
|
DepIsInSameApex(ctx BaseModuleContext, dep Module) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApexProperties struct {
|
type ApexProperties struct {
|
||||||
|
@ -154,6 +158,13 @@ func (m *ApexModuleBase) AvailableFor(what string) bool {
|
||||||
return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
|
return CheckAvailableForApex(what, m.ApexProperties.Apex_available)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool {
|
||||||
|
// By default, if there is a dependency from A to B, we try to include both in the same APEX,
|
||||||
|
// unless B is explicitly from outside of the APEX (i.e. a stubs lib). Thus, returning true.
|
||||||
|
// This is overridden by some module types like apex.ApexBundle, cc.Module, java.Module, etc.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
|
func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) {
|
||||||
for _, n := range m.ApexProperties.Apex_available {
|
for _, n := range m.ApexProperties.Apex_available {
|
||||||
if n == availableToPlatform || n == availableToAnyApex {
|
if n == availableToPlatform || n == availableToAnyApex {
|
||||||
|
|
|
@ -44,6 +44,17 @@ func (s SdkRef) Unversioned() bool {
|
||||||
return s.Version == ""
|
return s.Version == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns string representation of this SdkRef for debugging purpose
|
||||||
|
func (s SdkRef) String() string {
|
||||||
|
if s.Name == "" {
|
||||||
|
return "(No Sdk)"
|
||||||
|
}
|
||||||
|
if s.Unversioned() {
|
||||||
|
return s.Name
|
||||||
|
}
|
||||||
|
return s.Name + string(SdkVersionSeparator) + s.Version
|
||||||
|
}
|
||||||
|
|
||||||
// SdkVersionSeparator is a character used to separate an sdk name and its version
|
// SdkVersionSeparator is a character used to separate an sdk name and its version
|
||||||
const SdkVersionSeparator = '@'
|
const SdkVersionSeparator = '@'
|
||||||
|
|
||||||
|
|
|
@ -791,6 +791,11 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *apexBundle) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
|
||||||
|
// direct deps of an APEX bundle are all part of the APEX bundle
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
|
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
|
||||||
certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
|
certificate, overridden := ctx.DeviceConfig().OverrideCertificateFor(ctx.ModuleName())
|
||||||
if overridden {
|
if overridden {
|
||||||
|
|
10
cc/cc.go
10
cc/cc.go
|
@ -2182,6 +2182,16 @@ func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Write
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
|
||||||
|
if depTag, ok := ctx.OtherModuleDependencyTag(dep).(dependencyTag); ok {
|
||||||
|
if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.shared {
|
||||||
|
// dynamic dep to a stubs lib crosses APEX boundary
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Defaults
|
// Defaults
|
||||||
//
|
//
|
||||||
|
|
|
@ -190,6 +190,7 @@ func GatherRequiredDepsForTest(os android.OsType) string {
|
||||||
name: "crtbegin_so",
|
name: "crtbegin_so",
|
||||||
recovery_available: true,
|
recovery_available: true,
|
||||||
vendor_available: true,
|
vendor_available: true,
|
||||||
|
stl: "none",
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_object {
|
cc_object {
|
||||||
|
@ -208,6 +209,7 @@ func GatherRequiredDepsForTest(os android.OsType) string {
|
||||||
name: "crtend_so",
|
name: "crtend_so",
|
||||||
recovery_available: true,
|
recovery_available: true,
|
||||||
vendor_available: true,
|
vendor_available: true,
|
||||||
|
stl: "none",
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_object {
|
cc_object {
|
||||||
|
|
|
@ -1567,6 +1567,12 @@ func (j *Module) hasCode(ctx android.ModuleContext) bool {
|
||||||
return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
|
return len(srcFiles) > 0 || len(ctx.GetDirectDepsWithTag(staticLibTag)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
|
||||||
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||||
|
// dependencies other than the static linkage are all considered crossing APEX boundary
|
||||||
|
return depTag == staticLibTag
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Java libraries (.jar file)
|
// Java libraries (.jar file)
|
||||||
//
|
//
|
||||||
|
|
29
sdk/sdk.go
29
sdk/sdk.go
|
@ -122,6 +122,7 @@ func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
|
||||||
// should have been mutated for the apex before the SDK requirements are set.
|
// should have been mutated for the apex before the SDK requirements are set.
|
||||||
ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
|
ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel()
|
||||||
ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
|
ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel()
|
||||||
|
ctx.TopDown("SdkRequirementCheck", sdkRequirementsMutator).Parallel()
|
||||||
}
|
}
|
||||||
|
|
||||||
type dependencyTag struct {
|
type dependencyTag struct {
|
||||||
|
@ -229,3 +230,31 @@ func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 6: ensure that the dependencies from outside of the APEX are all from the required SDKs
|
||||||
|
func sdkRequirementsMutator(mctx android.TopDownMutatorContext) {
|
||||||
|
if m, ok := mctx.Module().(interface {
|
||||||
|
DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool
|
||||||
|
RequiredSdks() android.SdkRefs
|
||||||
|
}); ok {
|
||||||
|
requiredSdks := m.RequiredSdks()
|
||||||
|
if len(requiredSdks) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mctx.VisitDirectDeps(func(dep android.Module) {
|
||||||
|
if mctx.OtherModuleDependencyTag(dep) == android.DefaultsDepTag {
|
||||||
|
// dependency to defaults is always okay
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the dep is from outside of the APEX, but is not in any of the
|
||||||
|
// required SDKs, we know that the dep is a violation.
|
||||||
|
if sa, ok := dep.(android.SdkAware); ok {
|
||||||
|
if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) {
|
||||||
|
mctx.ModuleErrorf("depends on %q (in SDK %q) that isn't part of the required SDKs: %v",
|
||||||
|
sa.Name(), sa.ContainingSdk(), requiredSdks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -115,6 +115,23 @@ func testSdk(t *testing.T, bp string) (*android.TestContext, android.Config) {
|
||||||
return ctx, config
|
return ctx, config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testSdkError(t *testing.T, pattern, bp string) {
|
||||||
|
t.Helper()
|
||||||
|
ctx, config := testSdkContext(t, bp)
|
||||||
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
if len(errs) > 0 {
|
||||||
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
|
||||||
|
}
|
||||||
|
|
||||||
// ensure that 'result' contains 'expected'
|
// ensure that 'result' contains 'expected'
|
||||||
func ensureContains(t *testing.T, result string, expected string) {
|
func ensureContains(t *testing.T, result string, expected string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
@ -303,6 +320,63 @@ func TestBasicSdkWithCc(t *testing.T) {
|
||||||
ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
|
ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDepNotInRequiredSdks(t *testing.T) {
|
||||||
|
testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
|
||||||
|
sdk {
|
||||||
|
name: "mysdk",
|
||||||
|
java_libs: ["sdkmember"],
|
||||||
|
}
|
||||||
|
|
||||||
|
sdk_snapshot {
|
||||||
|
name: "mysdk@1",
|
||||||
|
java_libs: ["sdkmember_mysdk_1"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_import {
|
||||||
|
name: "sdkmember",
|
||||||
|
prefer: false,
|
||||||
|
host_supported: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
java_import {
|
||||||
|
name: "sdkmember_mysdk_1",
|
||||||
|
sdk_member_name: "sdkmember",
|
||||||
|
host_supported: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "myjavalib",
|
||||||
|
srcs: ["Test.java"],
|
||||||
|
libs: [
|
||||||
|
"sdkmember",
|
||||||
|
"otherlib",
|
||||||
|
],
|
||||||
|
system_modules: "none",
|
||||||
|
sdk_version: "none",
|
||||||
|
compile_dex: true,
|
||||||
|
host_supported: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// this lib is no in mysdk
|
||||||
|
java_library {
|
||||||
|
name: "otherlib",
|
||||||
|
srcs: ["Test.java"],
|
||||||
|
system_modules: "none",
|
||||||
|
sdk_version: "none",
|
||||||
|
compile_dex: true,
|
||||||
|
host_supported: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
java_libs: ["myjavalib"],
|
||||||
|
uses_sdks: ["mysdk@1"],
|
||||||
|
key: "myapex.key",
|
||||||
|
certificate: ":myapex.cert",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
var buildDir string
|
var buildDir string
|
||||||
|
|
||||||
func setUp() {
|
func setUp() {
|
||||||
|
|
Loading…
Reference in New Issue