diff options
Diffstat (limited to 'sdk/sdk.go')
-rw-r--r-- | sdk/sdk.go | 182 |
1 files changed, 13 insertions, 169 deletions
diff --git a/sdk/sdk.go b/sdk/sdk.go index 84c9a96e4..aeeedb428 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -39,7 +39,6 @@ func registerSdkBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("sdk", SdkModuleFactory) ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory) ctx.PreDepsMutators(RegisterPreDepsMutators) - ctx.PostDepsMutators(RegisterPostDepsMutators) } type sdk struct { @@ -76,6 +75,8 @@ type sdk struct { snapshotFile android.OptionalPath + infoFile android.OptionalPath + // The builder, preserved for testing. builderForTests *snapshotBuilder } @@ -145,7 +146,7 @@ func newSdkModule(moduleExports bool) *sdk { return s } -// sdk_snapshot is a versioned snapshot of an SDK. This is an auto-generated module. +// sdk_snapshot is a snapshot of an SDK. This is an auto-generated module. func SnapshotModuleFactory() android.Module { s := newSdkModule(false) s.properties.Snapshot = true @@ -192,27 +193,32 @@ func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // Generate the snapshot from the member info. - p := s.buildSnapshot(ctx, sdkVariants) - zip := ctx.InstallFile(android.PathForMainlineSdksInstall(ctx), p.Base(), p) - s.snapshotFile = android.OptionalPathForPath(zip) + s.buildSnapshot(ctx, sdkVariants) } } func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries { - if !s.snapshotFile.Valid() { + if !s.snapshotFile.Valid() != !s.infoFile.Valid() { + panic("Snapshot (%q) and info file (%q) should both be set or neither should be set.") + } else if !s.snapshotFile.Valid() { return []android.AndroidMkEntries{} } return []android.AndroidMkEntries{android.AndroidMkEntries{ Class: "FAKE", OutputFile: s.snapshotFile, - DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path()), + DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path(), s.infoFile.Path()), Include: "$(BUILD_PHONY_PACKAGE)", ExtraFooters: []android.AndroidMkExtraFootersFunc{ func(w io.Writer, name, prefix, moduleDir string) { // Allow the sdk to be built by simply passing its name on the command line. fmt.Fprintln(w, ".PHONY:", s.Name()) fmt.Fprintln(w, s.Name()+":", s.snapshotFile.String()) + + // Allow the sdk info to be built by simply passing its name on the command line. + infoTarget := s.Name() + ".info" + fmt.Fprintln(w, ".PHONY:", infoTarget) + fmt.Fprintln(w, infoTarget+":", s.infoFile.String()) }, }, }} @@ -275,21 +281,6 @@ var _ android.SdkDependencyContext = (*dependencyContext)(nil) func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { ctx.BottomUp("SdkMember", memberMutator).Parallel() ctx.TopDown("SdkMember_deps", memberDepsMutator).Parallel() - ctx.BottomUp("SdkMemberInterVersion", memberInterVersionMutator).Parallel() -} - -// RegisterPostDepsMutators registers post-deps mutators to support modules implementing SdkAware -// interface and the sdk module type. This function has been made public to be called by tests -// outside of the sdk package -func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { - // These must run AFTER apexMutator. Note that the apex package is imported even though there is - // no direct dependency to the package here. sdkDepsMutator sets the SDK requirements from an - // APEX to its dependents. Since different versions of the same SDK can be used by different - // APEXes, the apex and its dependents (which includes the dependencies to the sdk members) - // should have been mutated for the apex before the SDK requirements are set. - ctx.TopDown("SdkDepsMutator", sdkDepsMutator).Parallel() - ctx.BottomUp("SdkDepsReplaceMutator", sdkDepsReplaceMutator).Parallel() - ctx.TopDown("SdkRequirementCheck", sdkRequirementsMutator).Parallel() } type dependencyTag struct { @@ -301,38 +292,6 @@ func (t dependencyTag) ExcludeFromApexContents() {} var _ android.ExcludeFromApexContentsTag = dependencyTag{} -// For dependencies from an in-development version of an SDK member to frozen versions of the same member -// e.g. libfoo -> libfoo.mysdk.11 and libfoo.mysdk.12 -// -// The dependency represented by this tag requires that for every APEX variant created for the -// `from` module that an equivalent APEX variant is created for the 'to' module. This is because an -// APEX that requires a specific version of an sdk (via the `uses_sdks` property will replace -// dependencies on the unversioned sdk member with a dependency on the appropriate versioned sdk -// member. In order for that to work the versioned sdk member needs to have a variant for that APEX. -// As it is not known at the time that the APEX variants are created which specific APEX variants of -// a versioned sdk members will be required it is necessary for the versioned sdk members to have -// variants for any APEX that it could be used within. -// -// If the APEX selects a versioned sdk member then it will not have a dependency on the `from` -// module at all so any dependencies of that module will not affect the APEX. However, if the APEX -// selects the unversioned sdk member then it must exclude all the versioned sdk members. In no -// situation would this dependency cause the `to` module to be added to the APEX hence why this tag -// also excludes the `to` module from being added to the APEX contents. -type sdkMemberVersionedDepTag struct { - dependencyTag - member string - version string -} - -func (t sdkMemberVersionedDepTag) AlwaysRequireApexVariant() bool { - return true -} - -// Mark this tag so dependencies that use it are excluded from visibility enforcement. -func (t sdkMemberVersionedDepTag) ExcludeFromVisibilityEnforcement() {} - -var _ android.AlwaysRequireApexVariantTag = sdkMemberVersionedDepTag{} - // Step 1: create dependencies from an SDK module to its members. func memberMutator(mctx android.BottomUpMutatorContext) { if s, ok := mctx.Module().(*sdk); ok { @@ -391,125 +350,10 @@ func memberDepsMutator(mctx android.TopDownMutatorContext) { } } -// Step 3: create dependencies from the unversioned SDK member to snapshot versions -// of the same member. By having these dependencies, they are mutated for multiple Mainline modules -// (apex and apk), each of which might want different sdks to be built with. For example, if both -// apex A and B are referencing libfoo which is a member of sdk 'mysdk', the two APEXes can be -// built with libfoo.mysdk.11 and libfoo.mysdk.12, respectively depending on which sdk they are -// using. -func memberInterVersionMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() && m.IsVersioned() { - if !m.ContainingSdk().Unversioned() { - memberName := m.MemberName() - tag := sdkMemberVersionedDepTag{member: memberName, version: m.ContainingSdk().Version} - mctx.AddReverseDependency(mctx.Module(), tag, memberName) - } - } -} - // An interface that encapsulates all the functionality needed to manage the sdk dependencies. // // It is a mixture of apex and sdk module functionality. type sdkAndApexModule interface { android.Module android.DepIsInSameApex - android.RequiredSdks -} - -// Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its -// descendants -func sdkDepsMutator(mctx android.TopDownMutatorContext) { - if parent, ok := mctx.Module().(sdkAndApexModule); ok { - // Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks() - // by reading its own properties like `uses_sdks`. - requiredSdks := parent.RequiredSdks() - if len(requiredSdks) > 0 { - mctx.VisitDirectDeps(func(m android.Module) { - // Only propagate required sdks from the apex onto its contents. - if dep, ok := m.(android.SdkAware); ok && android.IsDepInSameApex(mctx, parent, dep) { - dep.BuildWithSdks(requiredSdks) - } - }) - } - } -} - -// Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the -// versioned module is used instead of the un-versioned (in-development) module libfoo -func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) { - if versionedSdkMember, ok := mctx.Module().(android.SdkAware); ok && versionedSdkMember.IsInAnySdk() && versionedSdkMember.IsVersioned() { - if sdk := versionedSdkMember.ContainingSdk(); !sdk.Unversioned() { - // Only replace dependencies to <sdkmember> with <sdkmember@required-version> - // if the depending module requires it. e.g. - // foo -> sdkmember - // will be transformed to: - // foo -> sdkmember@1 - // if and only if foo is a member of an APEX that requires version 1 of the - // sdk containing sdkmember. - memberName := versionedSdkMember.MemberName() - - // Convert a panic into a normal error to allow it to be more easily tested for. This is a - // temporary workaround, once http://b/183204176 has been fixed this can be removed. - // TODO(b/183204176): Remove this after fixing. - defer func() { - if r := recover(); r != nil { - mctx.ModuleErrorf("sdkDepsReplaceMutator %s", r) - } - }() - - // Replace dependencies on sdkmember with a dependency on the current module which - // is a versioned prebuilt of the sdkmember if required. - mctx.ReplaceDependenciesIf(memberName, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool { - // from - foo - // to - sdkmember - replace := false - if parent, ok := from.(android.RequiredSdks); ok { - replace = parent.RequiredSdks().Contains(sdk) - } - return replace - }) - } - } -} - -// Step 6: ensure that the dependencies outside of the APEX are all from the required SDKs -func sdkRequirementsMutator(mctx android.TopDownMutatorContext) { - if m, ok := mctx.Module().(sdkAndApexModule); ok { - requiredSdks := m.RequiredSdks() - if len(requiredSdks) == 0 { - return - } - mctx.VisitDirectDeps(func(dep android.Module) { - tag := mctx.OtherModuleDependencyTag(dep) - if tag == android.DefaultsDepTag { - // dependency to defaults is always okay - return - } - - // Ignore the dependency from the unversioned member to any versioned members as an - // apex that depends on the unversioned member will not also be depending on a versioned - // member. - if _, ok := tag.(sdkMemberVersionedDepTag); ok { - return - } - - // If the dep is 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 { - // It is not an error if a dependency that is excluded from the apex due to the tag is not - // in one of the required SDKs. That is because all of the existing tags that implement it - // do not depend on modules which can or should belong to an sdk_snapshot. - if _, ok := tag.(android.ExcludeFromApexContentsTag); ok { - // The tag defines a dependency that never requires the child module to be part of the - // same apex. - return - } - - 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) - } - } - }) - } } |