diff --git a/android/sdk.go b/android/sdk.go index 01e18ed4b..b9220ca69 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -17,6 +17,7 @@ package android import ( "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) @@ -31,9 +32,6 @@ type SdkAware interface { MemberName() string BuildWithSdks(sdks SdkRefs) RequiredSdks() SdkRefs - - // Build a snapshot of the module. - BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder) } // SdkRef refers to a version of an SDK @@ -203,3 +201,56 @@ type BpPropertySet interface { type BpModule interface { BpPropertySet } + +// An individual member of the SDK, includes all of the variants that the SDK +// requires. +type SdkMember interface { + // The name of the member. + Name() string + + // All the variants required by the SDK. + Variants() []SdkAware +} + +// Interface that must be implemented for every type that can be a member of an +// sdk. +// +// The basic implementation should look something like this, where ModuleType is +// the name of the module type being supported. +// +// var ModuleTypeSdkMemberType = newModuleTypeSdkMemberType() +// +// func newModuleTypeSdkMemberType() android.SdkMemberType { +// return &moduleTypeSdkMemberType{} +// } +// +// type moduleTypeSdkMemberType struct { +// } +// +// ...methods... +// +type SdkMemberType interface { + // Add dependencies from the SDK module to all the variants the member + // contributes to the SDK. The exact set of variants required is determined + // by the SDK and its properties. The dependencies must be added with the + // supplied tag. + // + // The BottomUpMutatorContext provided is for the SDK module. + AddDependencies(mctx BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) + + // Return true if the supplied module is an instance of this member type. + // + // This is used to check the type of each variant before added to the + // SdkMember. Returning false will cause an error to be logged expaining that + // the module is not allowed in whichever sdk property it was added. + IsInstance(module Module) bool + + // Build the snapshot for the SDK member + // + // The ModuleContext provided is for the SDK module, so information for + // variants in the supplied member can be accessed using the Other... methods. + // + // The SdkMember is guaranteed to contain variants for which the + // IsInstance(Module) method returned true. + BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) +} diff --git a/cc/library.go b/cc/library.go index 98cae3d49..60b00b193 100644 --- a/cc/library.go +++ b/cc/library.go @@ -24,6 +24,7 @@ import ( "strings" "sync" + "github.com/google/blueprint" "github.com/google/blueprint/pathtools" "android/soong/android" @@ -1403,3 +1404,230 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu return outputFile } + +var LibrarySdkMemberType = &librarySdkMemberType{} + +type librarySdkMemberType struct { +} + +func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { + targets := mctx.MultiTargets() + for _, lib := range names { + for _, target := range targets { + name, version := StubsLibNameAndVersion(lib) + if version == "" { + version = LatestStubsVersionFor(mctx.Config(), name) + } + mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ + {Mutator: "image", Variation: android.CoreVariation}, + {Mutator: "link", Variation: "shared"}, + {Mutator: "version", Variation: version}, + }...), dependencyTag, name) + } + } +} + +func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { + _, ok := module.(*Module) + return ok +} + +// copy exported header files and stub *.so files +func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { + info := organizeVariants(member) + buildSharedNativeLibSnapshot(sdkModuleContext, info, builder) +} + +func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) { + // a function for emitting include dirs + printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) { + includeDirs := lib.exportedIncludeDirs + includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...) + if len(includeDirs) == 0 { + return + } + for _, dir := range includeDirs { + if _, gen := dir.(android.WritablePath); gen { + // generated headers are copied via exportedDeps. See below. + continue + } + targetDir := nativeIncludeDir + if info.hasArchSpecificFlags { + targetDir = filepath.Join(lib.archType, targetDir) + } + + // TODO(jiyong) copy headers having other suffixes + headers, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.h", nil) + for _, file := range headers { + src := android.PathForSource(sdkModuleContext, file) + dest := filepath.Join(targetDir, file) + builder.CopyToSnapshot(src, dest) + } + } + + genHeaders := lib.exportedDeps + for _, file := range genHeaders { + targetDir := nativeGeneratedIncludeDir + if info.hasArchSpecificFlags { + targetDir = filepath.Join(lib.archType, targetDir) + } + dest := filepath.Join(targetDir, lib.name, file.Rel()) + builder.CopyToSnapshot(file, dest) + } + } + + if !info.hasArchSpecificFlags { + printExportedDirCopyCommandsForNativeLibs(info.archVariants[0]) + } + + // for each architecture + for _, av := range info.archVariants { + builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av)) + + if info.hasArchSpecificFlags { + printExportedDirCopyCommandsForNativeLibs(av) + } + } + + info.generatePrebuiltLibrary(sdkModuleContext, builder) +} + +func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) { + + // a function for emitting include dirs + addExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, properties android.BpPropertySet, systemInclude bool) { + includeDirs := nativeIncludeDirPathsFor(lib, systemInclude, info.hasArchSpecificFlags) + if len(includeDirs) == 0 { + return + } + var propertyName string + if !systemInclude { + propertyName = "export_include_dirs" + } else { + propertyName = "export_system_include_dirs" + } + properties.AddProperty(propertyName, includeDirs) + } + + pbm := builder.AddPrebuiltModule(info.name, "cc_prebuilt_library_shared") + + if !info.hasArchSpecificFlags { + addExportedDirsForNativeLibs(info.archVariants[0], pbm, false /*systemInclude*/) + addExportedDirsForNativeLibs(info.archVariants[0], pbm, true /*systemInclude*/) + } + + archProperties := pbm.AddPropertySet("arch") + for _, av := range info.archVariants { + archTypeProperties := archProperties.AddPropertySet(av.archType) + archTypeProperties.AddProperty("srcs", []string{nativeStubFilePathFor(av)}) + if info.hasArchSpecificFlags { + // export_* properties are added inside the arch: {: {...}} block + addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/) + addExportedDirsForNativeLibs(av, archTypeProperties, true /*systemInclude*/) + } + } + pbm.AddProperty("stl", "none") + pbm.AddProperty("system_shared_libs", []string{}) +} + +const ( + nativeIncludeDir = "include" + nativeGeneratedIncludeDir = "include_gen" + nativeStubDir = "lib" + nativeStubFileSuffix = ".so" +) + +// path to the stub file of a native shared library. Relative to / +func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string { + return filepath.Join(lib.archType, + nativeStubDir, lib.name+nativeStubFileSuffix) +} + +// paths to the include dirs of a native shared library. Relative to / +func nativeIncludeDirPathsFor(lib archSpecificNativeLibInfo, systemInclude bool, archSpecific bool) []string { + var result []string + var includeDirs []android.Path + if !systemInclude { + includeDirs = lib.exportedIncludeDirs + } else { + includeDirs = lib.exportedSystemIncludeDirs + } + for _, dir := range includeDirs { + var path string + if _, gen := dir.(android.WritablePath); gen { + path = filepath.Join(nativeGeneratedIncludeDir, lib.name) + } else { + path = filepath.Join(nativeIncludeDir, dir.String()) + } + if archSpecific { + path = filepath.Join(lib.archType, path) + } + result = append(result, path) + } + return result +} + +// archSpecificNativeLibInfo represents an arch-specific variant of a native lib +type archSpecificNativeLibInfo struct { + name string + archType string + exportedIncludeDirs android.Paths + exportedSystemIncludeDirs android.Paths + exportedFlags []string + exportedDeps android.Paths + outputFile android.Path +} + +func (lib *archSpecificNativeLibInfo) signature() string { + return fmt.Sprintf("%v %v %v %v", + lib.name, + lib.exportedIncludeDirs.Strings(), + lib.exportedSystemIncludeDirs.Strings(), + lib.exportedFlags) +} + +// nativeLibInfo represents a collection of arch-specific modules having the same name +type nativeLibInfo struct { + name string + archVariants []archSpecificNativeLibInfo + // hasArchSpecificFlags is set to true if modules for each architecture all have the same + // include dirs, flags, etc, in which case only those of the first arch is selected. + hasArchSpecificFlags bool +} + +// Organize the variants by architecture. +func organizeVariants(member android.SdkMember) *nativeLibInfo { + info := &nativeLibInfo{name: member.Name()} + + for _, variant := range member.Variants() { + ccModule := variant.(*Module) + + info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{ + name: ccModule.BaseModuleName(), + archType: ccModule.Target().Arch.ArchType.String(), + exportedIncludeDirs: ccModule.ExportedIncludeDirs(), + exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(), + exportedFlags: ccModule.ExportedFlags(), + exportedDeps: ccModule.ExportedDeps(), + outputFile: ccModule.OutputFile().Path(), + }) + } + + // Determine if include dirs and flags for each variant are different across arch-specific + // variants or not. And set hasArchSpecificFlags accordingly + // by default, include paths and flags are assumed to be the same across arches + info.hasArchSpecificFlags = false + oldSignature := "" + for _, av := range info.archVariants { + newSignature := av.signature() + if oldSignature == "" { + oldSignature = newSignature + } + if oldSignature != newSignature { + info.hasArchSpecificFlags = true + break + } + } + + return info +} diff --git a/java/droiddoc.go b/java/droiddoc.go index 16e6921e1..45a72e14d 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -19,6 +19,7 @@ import ( "path/filepath" "strings" + "github.com/google/blueprint" "github.com/google/blueprint/proptools" "android/soong/android" @@ -1973,7 +1974,27 @@ func PrebuiltStubsSourcesFactory() android.Module { return module } -func (d *Droidstubs) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) { +var DroidStubsSdkMemberType = &droidStubsSdkMemberType{} + +type droidStubsSdkMemberType struct { +} + +func (mt *droidStubsSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { + mctx.AddVariationDependencies(nil, dependencyTag, names...) +} + +func (mt *droidStubsSdkMemberType) IsInstance(module android.Module) bool { + _, ok := module.(*Droidstubs) + return ok +} + +func (mt *droidStubsSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { + variants := member.Variants() + if len(variants) != 1 { + sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name()) + } + variant := variants[0] + d, _ := variant.(*Droidstubs) stubsSrcJar := d.stubsSrcJar snapshotRelativeDir := filepath.Join("java", d.Name()+"_stubs_sources") diff --git a/java/java.go b/java/java.go index 9c0fcbaa0..0334ca49a 100644 --- a/java/java.go +++ b/java/java.go @@ -1721,7 +1721,31 @@ func (j *Library) javaStubFilePathFor() string { return filepath.Join(javaStubDir, j.Name()+javaStubFileSuffix) } -func (j *Library) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) { +var LibrarySdkMemberType = &librarySdkMemberType{} + +type librarySdkMemberType struct { +} + +func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { + mctx.AddVariationDependencies(nil, dependencyTag, names...) +} + +func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { + _, ok := module.(*Library) + return ok +} + +func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { + variants := member.Variants() + if len(variants) != 1 { + sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name()) + for _, variant := range variants { + sdkModuleContext.ModuleErrorf(" %q", variant) + } + } + variant := variants[0] + j := variant.(*Library) + headerJars := j.HeaderJars() if len(headerJars) != 1 { panic(fmt.Errorf("there must be only one header jar from %q", j.Name())) diff --git a/sdk/sdk.go b/sdk/sdk.go index 18b0040b9..80dd088c8 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -27,6 +27,7 @@ import ( // registered before mutators in this package. See RegisterPostDepsMutators for more details. _ "android/soong/apex" "android/soong/cc" + "android/soong/java" ) func init() { @@ -37,6 +38,14 @@ func init() { android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory) android.PreDepsMutators(RegisterPreDepsMutators) android.PostDepsMutators(RegisterPostDepsMutators) + + // Populate the dependency tags for each member list property. This needs to + // be done here to break an initialization cycle. + for _, memberListProperty := range sdkMemberListProperties { + memberListProperty.dependencyTag = &sdkMemberDependencyTag{ + memberListProperty: memberListProperty, + } + } } type sdk struct { @@ -62,6 +71,45 @@ type sdkProperties struct { Snapshot bool `blueprint:"mutated"` } +type sdkMemberDependencyTag struct { + blueprint.BaseDependencyTag + memberListProperty *sdkMemberListProperty +} + +// Contains information about the sdk properties that list sdk members, e.g. +// Java_libs. +type sdkMemberListProperty struct { + // the name of the property as used in a .bp file + name string + + // getter for the list of member names + getter func(properties *sdkProperties) []string + + // the type of member referenced in the list + memberType android.SdkMemberType + + // the dependency tag used for items in this list. + dependencyTag *sdkMemberDependencyTag +} + +var sdkMemberListProperties = []*sdkMemberListProperty{ + { + name: "java_libs", + getter: func(properties *sdkProperties) []string { return properties.Java_libs }, + memberType: java.LibrarySdkMemberType, + }, + { + name: "stubs_sources", + getter: func(properties *sdkProperties) []string { return properties.Stubs_sources }, + memberType: java.DroidStubsSdkMemberType, + }, + { + name: "native_shared_libs", + getter: func(properties *sdkProperties) []string { return properties.Native_shared_libs }, + memberType: cc.LibrarySdkMemberType, + }, +} + // sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.) // which Mainline modules like APEX can choose to build with. func ModuleFactory() android.Module { @@ -145,10 +193,6 @@ type dependencyTag struct { blueprint.BaseDependencyTag } -// For dependencies from an SDK module to its members -// e.g. mysdk -> libfoo and libbar -var sdkMemberDepTag 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 type sdkMemberVesionedDepTag struct { @@ -160,22 +204,10 @@ type sdkMemberVesionedDepTag struct { // Step 1: create dependencies from an SDK module to its members. func memberMutator(mctx android.BottomUpMutatorContext) { if m, ok := mctx.Module().(*sdk); ok { - mctx.AddVariationDependencies(nil, sdkMemberDepTag, m.properties.Java_libs...) - mctx.AddVariationDependencies(nil, sdkMemberDepTag, m.properties.Stubs_sources...) - - targets := mctx.MultiTargets() - for _, target := range targets { - for _, lib := range m.properties.Native_shared_libs { - name, version := cc.StubsLibNameAndVersion(lib) - if version == "" { - version = cc.LatestStubsVersionFor(mctx.Config(), name) - } - mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{ - {Mutator: "image", Variation: android.CoreVariation}, - {Mutator: "link", Variation: "shared"}, - {Mutator: "version", Variation: version}, - }...), sdkMemberDepTag, name) - } + for _, memberListProperty := range sdkMemberListProperties { + names := memberListProperty.getter(&m.properties) + tag := memberListProperty.dependencyTag + memberListProperty.memberType.AddDependencies(mctx, tag, names) } } } diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 6c2065998..2f0e59858 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -158,7 +158,7 @@ func TestBasicSdkWithJava(t *testing.T) { ctx, _ := testSdk(t, ` sdk { name: "mysdk", - java_libs: ["sdkmember"], + java_libs: ["myjavalib"], } sdk_snapshot { diff --git a/sdk/update.go b/sdk/update.go index 63bb1b73b..602e0a498 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -16,7 +16,6 @@ package sdk import ( "fmt" - "path/filepath" "reflect" "strings" @@ -24,8 +23,6 @@ import ( "github.com/google/blueprint/proptools" "android/soong/android" - "android/soong/cc" - "android/soong/java" ) var pctx = android.NewPackageContext("android/soong/sdk") @@ -105,105 +102,46 @@ func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderC rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base()) } -func (s *sdk) javaLibs(ctx android.ModuleContext) []android.SdkAware { - result := []android.SdkAware{} +// Collect all the members. +// +// The members are first grouped by type and then grouped by name. The order of +// the types is the order they are referenced in sdkMemberListProperties. The +// names are in order in which the dependencies were added. +func collectMembers(ctx android.ModuleContext) []*sdkMember { + byType := make(map[android.SdkMemberType][]*sdkMember) + byName := make(map[string]*sdkMember) + ctx.VisitDirectDeps(func(m android.Module) { - if j, ok := m.(*java.Library); ok { - result = append(result, j) - } - }) - return result -} + tag := ctx.OtherModuleDependencyTag(m) + if memberTag, ok := tag.(*sdkMemberDependencyTag); ok { + memberListProperty := memberTag.memberListProperty + memberType := memberListProperty.memberType -func (s *sdk) stubsSources(ctx android.ModuleContext) []android.SdkAware { - result := []android.SdkAware{} - ctx.VisitDirectDeps(func(m android.Module) { - if j, ok := m.(*java.Droidstubs); ok { - result = append(result, j) - } - }) - return result -} - -// archSpecificNativeLibInfo represents an arch-specific variant of a native lib -type archSpecificNativeLibInfo struct { - name string - archType string - exportedIncludeDirs android.Paths - exportedSystemIncludeDirs android.Paths - exportedFlags []string - exportedDeps android.Paths - outputFile android.Path -} - -func (lib *archSpecificNativeLibInfo) signature() string { - return fmt.Sprintf("%v %v %v %v", - lib.name, - lib.exportedIncludeDirs.Strings(), - lib.exportedSystemIncludeDirs.Strings(), - lib.exportedFlags) -} - -// nativeLibInfo represents a collection of arch-specific modules having the same name -type nativeLibInfo struct { - name string - archVariants []archSpecificNativeLibInfo - // hasArchSpecificFlags is set to true if modules for each architecture all have the same - // include dirs, flags, etc, in which case only those of the first arch is selected. - hasArchSpecificFlags bool -} - -// nativeMemberInfos collects all cc.Modules that are member of an SDK. -func (s *sdk) nativeMemberInfos(ctx android.ModuleContext) []*nativeLibInfo { - infoMap := make(map[string]*nativeLibInfo) - - // Collect cc.Modules - ctx.VisitDirectDeps(func(m android.Module) { - ccModule, ok := m.(*cc.Module) - if !ok { - return - } - depName := ctx.OtherModuleName(m) - - if _, ok := infoMap[depName]; !ok { - infoMap[depName] = &nativeLibInfo{name: depName} - } - - info := infoMap[depName] - info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{ - name: ccModule.BaseModuleName(), - archType: ccModule.Target().Arch.ArchType.String(), - exportedIncludeDirs: ccModule.ExportedIncludeDirs(), - exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(), - exportedFlags: ccModule.ExportedFlags(), - exportedDeps: ccModule.ExportedDeps(), - outputFile: ccModule.OutputFile().Path(), - }) - }) - - // Determine if include dirs and flags for each module are different across arch-specific - // modules or not. And set hasArchSpecificFlags accordingly - for _, info := range infoMap { - // by default, include paths and flags are assumed to be the same across arches - info.hasArchSpecificFlags = false - oldSignature := "" - for _, av := range info.archVariants { - newSignature := av.signature() - if oldSignature == "" { - oldSignature = newSignature + // Make sure that the resolved module is allowed in the member list property. + if !memberType.IsInstance(m) { + ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(m), memberListProperty.name) } - if oldSignature != newSignature { - info.hasArchSpecificFlags = true - break + + name := ctx.OtherModuleName(m) + + member := byName[name] + if member == nil { + member = &sdkMember{memberType: memberType, name: name} + byName[name] = member + byType[memberType] = append(byType[memberType], member) } + + member.variants = append(member.variants, m.(android.SdkAware)) } + }) + + var members []*sdkMember + for _, memberListProperty := range sdkMemberListProperties { + membersOfType := byType[memberListProperty.memberType] + members = append(members, membersOfType...) } - var list []*nativeLibInfo - for _, v := range infoMap { - list = append(list, v) - } - return list + return members } // SDK directory structure @@ -224,44 +162,6 @@ func (s *sdk) nativeMemberInfos(ctx android.ModuleContext) []*nativeLibInfo { // /lib/ // libFoo.so : a stub library -const ( - nativeIncludeDir = "include" - nativeGeneratedIncludeDir = "include_gen" - nativeStubDir = "lib" - nativeStubFileSuffix = ".so" -) - -// path to the stub file of a native shared library. Relative to / -func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string { - return filepath.Join(lib.archType, - nativeStubDir, lib.name+nativeStubFileSuffix) -} - -// paths to the include dirs of a native shared library. Relative to / -func nativeIncludeDirPathsFor(ctx android.ModuleContext, lib archSpecificNativeLibInfo, - systemInclude bool, archSpecific bool) []string { - var result []string - var includeDirs []android.Path - if !systemInclude { - includeDirs = lib.exportedIncludeDirs - } else { - includeDirs = lib.exportedSystemIncludeDirs - } - for _, dir := range includeDirs { - var path string - if _, gen := dir.(android.WritablePath); gen { - path = filepath.Join(nativeGeneratedIncludeDir, lib.name) - } else { - path = filepath.Join(nativeIncludeDir, dir.String()) - } - if archSpecific { - path = filepath.Join(lib.archType, path) - } - result = append(result, path) - } - return result -} - // A name that uniquely identifies a prebuilt SDK member for a version of SDK snapshot // This isn't visible to users, so could be changed in future. func versionedSdkMemberName(ctx android.ModuleContext, memberName string, version string) string { @@ -290,22 +190,8 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath { } s.builderForTests = builder - // copy exported AIDL files and stub jar files - javaLibs := s.javaLibs(ctx) - for _, m := range javaLibs { - m.BuildSnapshot(ctx, builder) - } - - // copy stubs sources - stubsSources := s.stubsSources(ctx) - for _, m := range stubsSources { - m.BuildSnapshot(ctx, builder) - } - - // copy exported header files and stub *.so files - nativeLibInfos := s.nativeMemberInfos(ctx) - for _, info := range nativeLibInfos { - buildSharedNativeLibSnapshot(ctx, info, builder) + for _, member := range collectMembers(ctx) { + member.memberType.BuildSnapshot(ctx, builder, member) } for _, unversioned := range builder.prebuiltOrder { @@ -326,14 +212,11 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath { snapshotModule := bpFile.newModule("sdk_snapshot") snapshotModule.AddProperty("name", snapshotName) addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule) - if len(s.properties.Java_libs) > 0 { - snapshotModule.AddProperty("java_libs", builder.versionedSdkMemberNames(s.properties.Java_libs)) - } - if len(s.properties.Stubs_sources) > 0 { - snapshotModule.AddProperty("stubs_sources", builder.versionedSdkMemberNames(s.properties.Stubs_sources)) - } - if len(s.properties.Native_shared_libs) > 0 { - snapshotModule.AddProperty("native_shared_libs", builder.versionedSdkMemberNames(s.properties.Native_shared_libs)) + for _, memberListProperty := range sdkMemberListProperties { + names := memberListProperty.getter(&s.properties) + if len(names) > 0 { + snapshotModule.AddProperty(memberListProperty.name, builder.versionedSdkMemberNames(names)) + } } bpFile.AddModule(snapshotModule) @@ -442,98 +325,6 @@ func (s *sdk) GetAndroidBpContentsForTests() string { return contents.content.String() } -func buildSharedNativeLibSnapshot(ctx android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) { - // a function for emitting include dirs - printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) { - includeDirs := lib.exportedIncludeDirs - includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...) - if len(includeDirs) == 0 { - return - } - for _, dir := range includeDirs { - if _, gen := dir.(android.WritablePath); gen { - // generated headers are copied via exportedDeps. See below. - continue - } - targetDir := nativeIncludeDir - if info.hasArchSpecificFlags { - targetDir = filepath.Join(lib.archType, targetDir) - } - - // TODO(jiyong) copy headers having other suffixes - headers, _ := ctx.GlobWithDeps(dir.String()+"/**/*.h", nil) - for _, file := range headers { - src := android.PathForSource(ctx, file) - dest := filepath.Join(targetDir, file) - builder.CopyToSnapshot(src, dest) - } - } - - genHeaders := lib.exportedDeps - for _, file := range genHeaders { - targetDir := nativeGeneratedIncludeDir - if info.hasArchSpecificFlags { - targetDir = filepath.Join(lib.archType, targetDir) - } - dest := filepath.Join(targetDir, lib.name, file.Rel()) - builder.CopyToSnapshot(file, dest) - } - } - - if !info.hasArchSpecificFlags { - printExportedDirCopyCommandsForNativeLibs(info.archVariants[0]) - } - - // for each architecture - for _, av := range info.archVariants { - builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av)) - - if info.hasArchSpecificFlags { - printExportedDirCopyCommandsForNativeLibs(av) - } - } - - info.generatePrebuiltLibrary(ctx, builder) -} - -func (info *nativeLibInfo) generatePrebuiltLibrary(ctx android.ModuleContext, builder android.SnapshotBuilder) { - - // a function for emitting include dirs - addExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, properties android.BpPropertySet, systemInclude bool) { - includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags) - if len(includeDirs) == 0 { - return - } - var propertyName string - if !systemInclude { - propertyName = "export_include_dirs" - } else { - propertyName = "export_system_include_dirs" - } - properties.AddProperty(propertyName, includeDirs) - } - - pbm := builder.AddPrebuiltModule(info.name, "cc_prebuilt_library_shared") - - if !info.hasArchSpecificFlags { - addExportedDirsForNativeLibs(info.archVariants[0], pbm, false /*systemInclude*/) - addExportedDirsForNativeLibs(info.archVariants[0], pbm, true /*systemInclude*/) - } - - archProperties := pbm.AddPropertySet("arch") - for _, av := range info.archVariants { - archTypeProperties := archProperties.AddPropertySet(av.archType) - archTypeProperties.AddProperty("srcs", []string{nativeStubFilePathFor(av)}) - if info.hasArchSpecificFlags { - // export_* properties are added inside the arch: {: {...}} block - addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/) - addExportedDirsForNativeLibs(av, archTypeProperties, true /*systemInclude*/) - } - } - pbm.AddProperty("stl", "none") - pbm.AddProperty("system_shared_libs", []string{}) -} - type snapshotBuilder struct { ctx android.ModuleContext sdk *sdk @@ -613,3 +404,19 @@ func (s *snapshotBuilder) versionedSdkMemberNames(members []string) []string { } return references } + +var _ android.SdkMember = (*sdkMember)(nil) + +type sdkMember struct { + memberType android.SdkMemberType + name string + variants []android.SdkAware +} + +func (m *sdkMember) Name() string { + return m.name +} + +func (m *sdkMember) Variants() []android.SdkAware { + return m.variants +}