Merge "Generate empty classpaths.proto for bootclasspath_fragment.go."
diff --git a/android/sdk.go b/android/sdk.go
index 0adfd89..36c576d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -284,11 +284,20 @@
// Add a property set with the specified name and return so that additional
// properties can be added.
AddPropertySet(name string) BpPropertySet
+
+ // Add comment for property (or property set).
+ AddCommentForProperty(name, text string)
}
// A .bp module definition.
type BpModule interface {
BpPropertySet
+
+ // ModuleType returns the module type of the module
+ ModuleType() string
+
+ // Name returns the name of the module or "" if no name has been specified.
+ Name() string
}
// An individual member of the SDK, includes all of the variants that the SDK
@@ -380,6 +389,10 @@
// The name of the member type property on an sdk module.
SdkPropertyName() string
+ // RequiresBpProperty returns true if this member type requires its property to be usable within
+ // an Android.bp file.
+ RequiresBpProperty() bool
+
// True if the member type supports the sdk/sdk_snapshot, false otherwise.
UsableWithSdkAndSdkSnapshot() bool
@@ -405,6 +418,10 @@
// the module is not allowed in whichever sdk property it was added.
IsInstance(module Module) bool
+ // UsesSourceModuleTypeInSnapshot returns true when the AddPrebuiltModule() method returns a
+ // source module type.
+ UsesSourceModuleTypeInSnapshot() bool
+
// Add a prebuilt module that the sdk will populate.
//
// The sdk module code generates the snapshot as follows:
@@ -448,15 +465,29 @@
// Base type for SdkMemberType implementations.
type SdkMemberTypeBase struct {
- PropertyName string
+ PropertyName string
+
+ // When set to true BpPropertyNotRequired indicates that the member type does not require the
+ // property to be specifiable in an Android.bp file.
+ BpPropertyNotRequired bool
+
SupportsSdk bool
HostOsDependent bool
+
+ // When set to true UseSourceModuleTypeInSnapshot indicates that the member type creates a source
+ // module type in its SdkMemberType.AddPrebuiltModule() method. That prevents the sdk snapshot
+ // code from automatically adding a prefer: true flag.
+ UseSourceModuleTypeInSnapshot bool
}
func (b *SdkMemberTypeBase) SdkPropertyName() string {
return b.PropertyName
}
+func (b *SdkMemberTypeBase) RequiresBpProperty() bool {
+ return !b.BpPropertyNotRequired
+}
+
func (b *SdkMemberTypeBase) UsableWithSdkAndSdkSnapshot() bool {
return b.SupportsSdk
}
@@ -465,6 +496,10 @@
return b.HostOsDependent
}
+func (b *SdkMemberTypeBase) UsesSourceModuleTypeInSnapshot() bool {
+ return b.UseSourceModuleTypeInSnapshot
+}
+
// Encapsulates the information about registered SdkMemberTypes.
type SdkMemberTypesRegistry struct {
// The list of types sorted by property name.
diff --git a/apex/apex.go b/apex/apex.go
index 7ceb00b..2c0df27 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -50,10 +50,15 @@
ctx.RegisterModuleType("override_apex", overrideApexFactory)
ctx.RegisterModuleType("apex_set", apexSetFactory)
+ ctx.PreArchMutators(registerPreArchMutators)
ctx.PreDepsMutators(RegisterPreDepsMutators)
ctx.PostDepsMutators(RegisterPostDepsMutators)
}
+func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
+ ctx.TopDown("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel()
+}
+
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 9bc5720..c7cdbfa 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -40,17 +40,29 @@
// This is intentionally not registered by name as it is not intended to be used from within an
// `Android.bp` file.
-// Properties that are specific to `deapexer` but which need to be provided on the `prebuilt_apex`
-// module.`
-type DeapexerProperties struct {
- // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
- // APEX bundle will create an APEX variant and provide dex implementation jars for use by
- // dexpreopt and boot jars package check.
- Exported_java_libs []string
+// DeapexerExportedFile defines the properties needed to expose a file from the deapexer module.
+type DeapexerExportedFile struct {
+ // The tag parameter which must be passed to android.OutputFileProducer OutputFiles(tag) method
+ // to retrieve the path to the unpacked file.
+ Tag string
- // List of bootclasspath fragments inside this prebuiltd APEX bundle and for which this APEX
- // bundle will create an APEX variant.
- Exported_bootclasspath_fragments []string
+ // The path within the APEX that needs to be exported.
+ Path string `android:"path"`
+}
+
+// DeapexerProperties specifies the properties supported by the deapexer module.
+//
+// As these are never intended to be supplied in a .bp file they use a different naming convention
+// to make it clear that they are different.
+type DeapexerProperties struct {
+ // List of common modules that may need access to files exported by this module.
+ //
+ // A common module in this sense is one that is not arch specific but uses a common variant for
+ // all architectures, e.g. java.
+ CommonModules []string
+
+ // List of files exported from the .apex file by this module
+ ExportedFiles []DeapexerExportedFile
}
type SelectedApexProperties struct {
@@ -81,7 +93,7 @@
func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies from the java modules to which this exports files from the `.apex` file onto
// this module so that they can access the `DeapexerInfo` object that this provides.
- for _, lib := range p.properties.Exported_java_libs {
+ for _, lib := range p.properties.CommonModules {
dep := prebuiltApexExportedModuleName(ctx, lib)
ctx.AddReverseDependency(ctx.Module(), android.DeapexerTag, dep)
}
@@ -96,10 +108,12 @@
exports := make(map[string]android.Path)
// Create mappings from name+tag to all the required exported paths.
- for _, l := range p.properties.Exported_java_libs {
- // Populate the exports that this makes available. The path here must match the path of the
- // file in the APEX created by apexFileForJavaModule(...).
- exports[l+"{.dexjar}"] = deapexerOutput.Join(ctx, "javalib", l+".jar")
+ for _, e := range p.properties.ExportedFiles {
+ tag := e.Tag
+ path := e.Path
+
+ // Populate the exports that this makes available.
+ exports[tag] = deapexerOutput.Join(ctx, path)
}
// If the prebuilt_apex exports any files then create a build rule that unpacks the apex using
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 8996352..9d632a9 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "path/filepath"
"strconv"
"strings"
@@ -46,11 +47,10 @@
}
type prebuiltCommon struct {
- prebuilt android.Prebuilt
- properties prebuiltCommonProperties
+ prebuilt android.Prebuilt
- deapexerProperties DeapexerProperties
- selectedApexProperties SelectedApexProperties
+ // Properties common to both prebuilt_apex and apex_set.
+ prebuiltCommonProperties prebuiltCommonProperties
}
type sanitizedPrebuilt interface {
@@ -58,7 +58,18 @@
}
type prebuiltCommonProperties struct {
+ SelectedApexProperties
+
ForceDisable bool `blueprint:"mutated"`
+
+ // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
+ // APEX bundle will create an APEX variant and provide dex implementation jars for use by
+ // dexpreopt and boot jars package check.
+ Exported_java_libs []string
+
+ // List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX
+ // bundle will create an APEX variant.
+ Exported_bootclasspath_fragments []string
}
func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
@@ -66,7 +77,7 @@
}
func (p *prebuiltCommon) isForceDisabled() bool {
- return p.properties.ForceDisable
+ return p.prebuiltCommonProperties.ForceDisable
}
func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool {
@@ -88,25 +99,47 @@
forceDisable = forceDisable || (android.InList("hwaddress", ctx.Config().SanitizeDevice()) && !sanitized.hasSanitizedSource("hwaddress"))
if forceDisable && p.prebuilt.SourceExists() {
- p.properties.ForceDisable = true
+ p.prebuiltCommonProperties.ForceDisable = true
return true
}
return false
}
-func (p *prebuiltCommon) deapexerDeps(ctx android.BottomUpMutatorContext) {
+// prebuiltApexModuleCreator defines the methods that need to be implemented by prebuilt_apex and
+// apex_set in order to create the modules needed to provide access to the prebuilt .apex file.
+type prebuiltApexModuleCreator interface {
+ createPrebuiltApexModules(ctx android.TopDownMutatorContext)
+}
+
+// prebuiltApexModuleCreatorMutator is the mutator responsible for invoking the
+// prebuiltApexModuleCreator's createPrebuiltApexModules method.
+//
+// It is registered as a pre-arch mutator as it must run after the ComponentDepsMutator because it
+// will need to access dependencies added by that (exported modules) but must run before the
+// DepsMutator so that the deapexer module it creates can add dependencies onto itself from the
+// exported modules.
+func prebuiltApexModuleCreatorMutator(ctx android.TopDownMutatorContext) {
+ module := ctx.Module()
+ if creator, ok := module.(prebuiltApexModuleCreator); ok {
+ creator.createPrebuiltApexModules(ctx)
+ }
+}
+
+// prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents.
+func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
+ module := ctx.Module()
// Add dependencies onto the java modules that represent the java libraries that are provided by
// and exported from this prebuilt apex.
- for _, exported := range p.deapexerProperties.Exported_java_libs {
- dep := prebuiltApexExportedModuleName(ctx, exported)
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
+ for _, exported := range p.prebuiltCommonProperties.Exported_java_libs {
+ dep := android.PrebuiltNameFromSource(exported)
+ ctx.AddDependency(module, exportedJavaLibTag, dep)
}
// Add dependencies onto the bootclasspath fragment modules that are exported from this prebuilt
// apex.
- for _, exported := range p.deapexerProperties.Exported_bootclasspath_fragments {
- dep := prebuiltApexExportedModuleName(ctx, exported)
- ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedBootclasspathFragmentTag, dep)
+ for _, exported := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments {
+ dep := android.PrebuiltNameFromSource(exported)
+ ctx.AddDependency(module, exportedBootclasspathFragmentTag, dep)
}
}
@@ -240,8 +273,7 @@
android.ModuleBase
prebuiltCommon
- properties PrebuiltProperties
- selectedApexProperties SelectedApexProperties
+ properties PrebuiltProperties
inputApex android.Path
installDir android.InstallPath
@@ -354,58 +386,16 @@
}
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
-//
-// If this needs to make files from within a `.apex` file available for use by other Soong modules,
-// e.g. make dex implementation jars available for java_import modules isted in exported_java_libs,
-// it does so as follows:
-//
-// 1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and
-// makes them available for use by other modules, at both Soong and ninja levels.
-//
-// 2. It adds a dependency onto those modules and creates an apex specific variant similar to what
-// an `apex` module does. That ensures that code which looks for specific apex variant, e.g.
-// dexpreopt, will work the same way from source and prebuilt.
-//
-// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
-// itself so that they can retrieve the file paths to those files.
-//
-// It also creates a child module `selector` that is responsible for selecting the appropriate
-// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
-// 1. To dedup the selection logic so it only runs in one module.
-// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
-// `apex_set`.
-//
-// prebuilt_apex
-// / | \
-// / | \
-// V | V
-// selector <--- deapexer <--- exported java lib
-//
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
- module.AddProperties(&module.properties, &module.deapexerProperties, &module.selectedApexProperties)
- android.InitSingleSourcePrebuiltModule(module, &module.selectedApexProperties, "Selected_apex")
+ module.AddProperties(&module.properties, &module.prebuiltCommonProperties)
+ android.InitSingleSourcePrebuiltModule(module, &module.prebuiltCommonProperties, "Selected_apex")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- baseModuleName := module.BaseModuleName()
-
- apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
- createApexSelectorModule(ctx, apexSelectorModuleName, &module.properties.ApexFileProperties)
-
- apexFileSource := ":" + apexSelectorModuleName
- if len(module.deapexerProperties.Exported_java_libs) != 0 {
- createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.deapexerProperties)
- }
-
- // Add a source reference to retrieve the selected apex from the selector module.
- module.selectedApexProperties.Selected_apex = proptools.StringPtr(apexFileSource)
- })
-
return module
}
-func createApexSelectorModule(ctx android.LoadHookContext, name string, apexFileProperties *ApexFileProperties) {
+func createApexSelectorModule(ctx android.TopDownMutatorContext, name string, apexFileProperties *ApexFileProperties) {
props := struct {
Name *string
}{
@@ -418,7 +408,54 @@
)
}
-func createDeapexerModule(ctx android.LoadHookContext, deapexerName string, apexFileSource string, deapexerProperties *DeapexerProperties) {
+// createDeapexerModuleIfNeeded will create a deapexer module if it is needed.
+//
+// A deapexer module is only needed when the prebuilt apex specifies one or more modules in either
+// the `exported_java_libs` or `exported_bootclasspath_fragments` properties as that indicates that
+// the listed modules need access to files from within the prebuilt .apex file.
+func createDeapexerModuleIfNeeded(ctx android.TopDownMutatorContext, deapexerName string, apexFileSource string, properties *prebuiltCommonProperties) {
+ // Only create the deapexer module if it is needed.
+ if len(properties.Exported_java_libs)+len(properties.Exported_bootclasspath_fragments) == 0 {
+ return
+ }
+
+ // Compute the deapexer properties from the transitive dependencies of this module.
+ javaModules := []string{}
+ exportedFiles := map[string]string{}
+ ctx.WalkDeps(func(child, parent android.Module) bool {
+ tag := ctx.OtherModuleDependencyTag(child)
+
+ name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child))
+ if java.IsBootclasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag {
+ javaModules = append(javaModules, name)
+
+ // Add the dex implementation jar to the set of exported files. The path here must match the
+ // path of the file in the APEX created by apexFileForJavaModule(...).
+ exportedFiles[name+"{.dexjar}"] = filepath.Join("javalib", name+".jar")
+
+ } else if tag == exportedBootclasspathFragmentTag {
+ // Only visit the children of the bootclasspath_fragment for now.
+ return true
+ }
+
+ return false
+ })
+
+ // Create properties for deapexer module.
+ deapexerProperties := &DeapexerProperties{
+ // Remove any duplicates from the java modules lists as a module may be included via a direct
+ // dependency as well as transitive ones.
+ CommonModules: android.SortedUniqueStrings(javaModules),
+ }
+
+ // Populate the exported files property in a fixed order.
+ for _, tag := range android.SortedStringKeys(exportedFiles) {
+ deapexerProperties.ExportedFiles = append(deapexerProperties.ExportedFiles, DeapexerExportedFile{
+ Tag: tag,
+ Path: exportedFiles[tag],
+ })
+ }
+
props := struct {
Name *string
Selected_apex *string
@@ -479,8 +516,52 @@
exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
)
-func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
- p.deapexerDeps(ctx)
+var _ prebuiltApexModuleCreator = (*Prebuilt)(nil)
+
+// createPrebuiltApexModules creates modules necessary to export files from the prebuilt apex to the
+// build.
+//
+// If this needs to make files from within a `.apex` file available for use by other Soong modules,
+// e.g. make dex implementation jars available for java_import modules listed in exported_java_libs,
+// it does so as follows:
+//
+// 1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and
+// makes them available for use by other modules, at both Soong and ninja levels.
+//
+// 2. It adds a dependency onto those modules and creates an apex specific variant similar to what
+// an `apex` module does. That ensures that code which looks for specific apex variant, e.g.
+// dexpreopt, will work the same way from source and prebuilt.
+//
+// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto
+// itself so that they can retrieve the file paths to those files.
+//
+// It also creates a child module `selector` that is responsible for selecting the appropriate
+// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons:
+// 1. To dedup the selection logic so it only runs in one module.
+// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an
+// `apex_set`.
+//
+// prebuilt_apex
+// / | \
+// / | \
+// V V V
+// selector <--- deapexer <--- exported java lib
+//
+func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
+ baseModuleName := p.BaseModuleName()
+
+ apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
+ createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
+
+ apexFileSource := ":" + apexSelectorModuleName
+ createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource, &p.prebuiltCommonProperties)
+
+ // Add a source reference to retrieve the selected apex from the selector module.
+ p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
+}
+
+func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+ p.prebuiltApexContentsDeps(ctx)
}
var _ ApexInfoMutator = (*Prebuilt)(nil)
@@ -491,7 +572,7 @@
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// TODO(jungjw): Check the key validity.
- p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path()
+ p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
p.installDir = android.PathForModuleInstall(ctx, "apex")
p.installFilename = p.InstallFilename()
if !strings.HasSuffix(p.installFilename, imageApexSuffix) {
@@ -693,30 +774,15 @@
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
func apexSetFactory() android.Module {
module := &ApexSet{}
- module.AddProperties(&module.properties, &module.selectedApexProperties, &module.deapexerProperties)
+ module.AddProperties(&module.properties, &module.prebuiltCommonProperties)
- android.InitSingleSourcePrebuiltModule(module, &module.selectedApexProperties, "Selected_apex")
+ android.InitSingleSourcePrebuiltModule(module, &module.prebuiltCommonProperties, "Selected_apex")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- baseModuleName := module.BaseModuleName()
-
- apexExtractorModuleName := apexExtractorModuleName(baseModuleName)
- createApexExtractorModule(ctx, apexExtractorModuleName, &module.properties.ApexExtractorProperties)
-
- apexFileSource := ":" + apexExtractorModuleName
- if len(module.deapexerProperties.Exported_java_libs) != 0 {
- createDeapexerModule(ctx, deapexerModuleName(baseModuleName), apexFileSource, &module.deapexerProperties)
- }
-
- // After passing the arch specific src properties to the creating the apex selector module
- module.selectedApexProperties.Selected_apex = proptools.StringPtr(apexFileSource)
- })
-
return module
}
-func createApexExtractorModule(ctx android.LoadHookContext, name string, apexExtractorProperties *ApexExtractorProperties) {
+func createApexExtractorModule(ctx android.TopDownMutatorContext, name string, apexExtractorProperties *ApexExtractorProperties) {
props := struct {
Name *string
}{
@@ -733,8 +799,30 @@
return baseModuleName + ".apex.extractor"
}
-func (a *ApexSet) DepsMutator(ctx android.BottomUpMutatorContext) {
- a.deapexerDeps(ctx)
+var _ prebuiltApexModuleCreator = (*ApexSet)(nil)
+
+// createPrebuiltApexModules creates modules necessary to export files from the apex set to other
+// modules.
+//
+// This effectively does for apex_set what Prebuilt.createPrebuiltApexModules does for a
+// prebuilt_apex except that instead of creating a selector module which selects one .apex file
+// from those provided this creates an extractor module which extracts the appropriate .apex file
+// from the zip file containing them.
+func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
+ baseModuleName := a.BaseModuleName()
+
+ apexExtractorModuleName := apexExtractorModuleName(baseModuleName)
+ createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
+
+ apexFileSource := ":" + apexExtractorModuleName
+ createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource, &a.prebuiltCommonProperties)
+
+ // After passing the arch specific src properties to the creating the apex selector module
+ a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
+}
+
+func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
+ a.prebuiltApexContentsDeps(ctx)
}
var _ ApexInfoMutator = (*ApexSet)(nil)
@@ -749,7 +837,7 @@
ctx.ModuleErrorf("filename should end in %s for apex_set", imageApexSuffix)
}
- inputApex := android.OptionalPathForModuleSrc(ctx, a.selectedApexProperties.Selected_apex).Path()
+ inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path()
a.outputApex = android.PathForModuleOut(ctx, a.installFilename)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index c543ef8..407073a 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -257,24 +257,74 @@
depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
dir: "foo/bar",
filesystem: map[string]string{
- "foo/bar/a.cpp": "",
+ "foo/bar/both.cpp": "",
+ "foo/bar/sharedonly.cpp": "",
+ "foo/bar/staticonly.cpp": "",
"foo/bar/Android.bp": `
cc_library {
name: "a",
- shared: { whole_static_libs: ["b"] },
- static: { srcs: ["a.cpp"] },
+ srcs: ["both.cpp"],
+ cflags: ["bothflag"],
+ shared_libs: ["shared_dep_for_both"],
+ static_libs: ["static_dep_for_both"],
+ whole_static_libs: ["whole_static_lib_for_both"],
+ static: {
+ srcs: ["staticonly.cpp"],
+ cflags: ["staticflag"],
+ shared_libs: ["shared_dep_for_static"],
+ static_libs: ["static_dep_for_static"],
+ whole_static_libs: ["whole_static_lib_for_static"],
+ },
+ shared: {
+ srcs: ["sharedonly.cpp"],
+ cflags: ["sharedflag"],
+ shared_libs: ["shared_dep_for_shared"],
+ static_libs: ["static_dep_for_shared"],
+ whole_static_libs: ["whole_static_lib_for_shared"],
+ },
bazel_module: { bp2build_available: true },
}
-cc_library_static { name: "b" }
+cc_library_static { name: "static_dep_for_shared" }
+
+cc_library_static { name: "static_dep_for_static" }
+
+cc_library_static { name: "static_dep_for_both" }
+
+cc_library_static { name: "whole_static_lib_for_shared" }
+
+cc_library_static { name: "whole_static_lib_for_static" }
+
+cc_library_static { name: "whole_static_lib_for_both" }
+
+cc_library { name: "shared_dep_for_shared" }
+
+cc_library { name: "shared_dep_for_static" }
+
+cc_library { name: "shared_dep_for_both" }
`,
},
bp: soongCcLibraryPreamble,
expectedBazelTargets: []string{`cc_library(
name = "a",
- copts = ["-Ifoo/bar"],
- srcs = ["a.cpp"],
- static_deps_for_shared = [":b"],
+ copts = [
+ "bothflag",
+ "-Ifoo/bar",
+ ],
+ deps = [":static_dep_for_both"],
+ dynamic_deps = [":shared_dep_for_both"],
+ dynamic_deps_for_shared = [":shared_dep_for_shared"],
+ dynamic_deps_for_static = [":shared_dep_for_static"],
+ shared_copts = ["sharedflag"],
+ shared_srcs = ["sharedonly.cpp"],
+ srcs = ["both.cpp"],
+ static_copts = ["staticflag"],
+ static_deps_for_shared = [":static_dep_for_shared"],
+ static_deps_for_static = [":static_dep_for_static"],
+ static_srcs = ["staticonly.cpp"],
+ whole_archive_deps = [":whole_static_lib_for_both"],
+ whole_archive_deps_for_shared = [":whole_static_lib_for_shared"],
+ whole_archive_deps_for_static = [":whole_static_lib_for_static"],
)`},
},
{
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index bff9b07..d082db1 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -189,8 +189,6 @@
":header_lib_2",
":static_lib_1",
":static_lib_2",
- ":whole_static_lib_1",
- ":whole_static_lib_2",
],
includes = [
"export_include_dir_1",
@@ -201,6 +199,10 @@
"foo_static1.cc",
"foo_static2.cc",
],
+ whole_archive_deps = [
+ ":whole_static_lib_1",
+ ":whole_static_lib_2",
+ ],
)`, `cc_library_static(
name = "static_lib_1",
copts = ["-I."],
@@ -423,13 +425,14 @@
name = "foo_static",
copts = ["-I."],
deps = select({
- "//build/bazel/platforms/arch:arm64": [
- ":static_dep",
- ":static_dep2",
- ],
+ "//build/bazel/platforms/arch:arm64": [":static_dep"],
"//conditions:default": [],
}),
linkstatic = True,
+ whole_archive_deps = select({
+ "//build/bazel/platforms/arch:arm64": [":static_dep2"],
+ "//conditions:default": [],
+ }),
)`, `cc_library_static(
name = "static_dep",
copts = ["-I."],
@@ -458,13 +461,14 @@
name = "foo_static",
copts = ["-I."],
deps = select({
- "//build/bazel/platforms/os:android": [
- ":static_dep",
- ":static_dep2",
- ],
+ "//build/bazel/platforms/os:android": [":static_dep"],
"//conditions:default": [],
}),
linkstatic = True,
+ whole_archive_deps = select({
+ "//build/bazel/platforms/os:android": [":static_dep2"],
+ "//conditions:default": [],
+ }),
)`, `cc_library_static(
name = "static_dep",
copts = ["-I."],
@@ -497,10 +501,7 @@
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
copts = ["-I."],
- deps = [
- ":static_dep",
- ":static_dep2",
- ] + select({
+ deps = [":static_dep"] + select({
"//build/bazel/platforms/arch:arm64": [":static_dep4"],
"//conditions:default": [],
}) + select({
@@ -508,6 +509,7 @@
"//conditions:default": [],
}),
linkstatic = True,
+ whole_archive_deps = [":static_dep2"],
)`, `cc_library_static(
name = "static_dep",
copts = ["-I."],
@@ -732,8 +734,7 @@
cc_library_static { name: "static_dep" }
cc_library_static {
name: "foo_static",
- static_libs: ["static_dep"],
- whole_static_libs: ["static_dep"],
+ static_libs: ["static_dep", "static_dep"],
}`,
expectedBazelTargets: []string{`cc_library_static(
name = "foo_static",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 67f88e2..7d01986 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -85,7 +85,11 @@
}
type sharedAttributes struct {
- staticDeps bazel.LabelListAttribute
+ copts bazel.StringListAttribute
+ srcs bazel.LabelListAttribute
+ staticDeps bazel.LabelListAttribute
+ dynamicDeps bazel.LabelListAttribute
+ wholeArchiveDeps bazel.LabelListAttribute
}
// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
@@ -95,17 +99,35 @@
return sharedAttributes{}
}
- var staticDeps bazel.LabelListAttribute
+ copts := bazel.StringListAttribute{Value: lib.SharedProperties.Shared.Cflags}
- staticDeps.Value = android.BazelLabelForModuleDeps(ctx, lib.SharedProperties.Shared.Whole_static_libs)
+ srcs := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleSrc(ctx, lib.SharedProperties.Shared.Srcs)}
+
+ staticDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.SharedProperties.Shared.Static_libs)}
+
+ dynamicDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.SharedProperties.Shared.Shared_libs)}
+
+ wholeArchiveDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.SharedProperties.Shared.Whole_static_libs)}
return sharedAttributes{
- staticDeps: staticDeps,
+ copts: copts,
+ srcs: srcs,
+ staticDeps: staticDeps,
+ dynamicDeps: dynamicDeps,
+ wholeArchiveDeps: wholeArchiveDeps,
}
}
type staticAttributes struct {
- srcs bazel.LabelListAttribute
+ copts bazel.StringListAttribute
+ srcs bazel.LabelListAttribute
+ staticDeps bazel.LabelListAttribute
+ dynamicDeps bazel.LabelListAttribute
+ wholeArchiveDeps bazel.LabelListAttribute
}
// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
@@ -115,11 +137,26 @@
return staticAttributes{}
}
- var srcs bazel.LabelListAttribute
- srcs.Value = android.BazelLabelForModuleSrc(ctx, lib.StaticProperties.Static.Srcs)
+ copts := bazel.StringListAttribute{Value: lib.StaticProperties.Static.Cflags}
+
+ srcs := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleSrc(ctx, lib.StaticProperties.Static.Srcs)}
+
+ staticDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.StaticProperties.Static.Static_libs)}
+
+ dynamicDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.StaticProperties.Static.Shared_libs)}
+
+ wholeArchiveDeps := bazel.LabelListAttribute{
+ Value: android.BazelLabelForModuleDeps(ctx, lib.StaticProperties.Static.Whole_static_libs)}
return staticAttributes{
- srcs: srcs,
+ copts: copts,
+ srcs: srcs,
+ staticDeps: staticDeps,
+ dynamicDeps: dynamicDeps,
+ wholeArchiveDeps: wholeArchiveDeps,
}
}
@@ -246,10 +283,11 @@
// Convenience struct to hold all attributes parsed from linker properties.
type linkerAttributes struct {
- deps bazel.LabelListAttribute
- dynamicDeps bazel.LabelListAttribute
- linkopts bazel.StringListAttribute
- versionScript bazel.LabelAttribute
+ deps bazel.LabelListAttribute
+ dynamicDeps bazel.LabelListAttribute
+ wholeArchiveDeps bazel.LabelListAttribute
+ linkopts bazel.StringListAttribute
+ versionScript bazel.LabelAttribute
}
// FIXME(b/187655838): Use the existing linkerFlags() function instead of duplicating logic here
@@ -266,6 +304,7 @@
func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) linkerAttributes {
var deps bazel.LabelListAttribute
var dynamicDeps bazel.LabelListAttribute
+ var wholeArchiveDeps bazel.LabelListAttribute
var linkopts bazel.StringListAttribute
var versionScript bazel.LabelAttribute
@@ -274,11 +313,11 @@
libs := baseLinkerProps.Header_libs
libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
libs = append(libs, baseLinkerProps.Static_libs...)
- libs = append(libs, baseLinkerProps.Whole_static_libs...)
+ wholeArchiveLibs := baseLinkerProps.Whole_static_libs
libs = android.SortedUniqueStrings(libs)
deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, libs))
-
linkopts.Value = getBp2BuildLinkerFlags(baseLinkerProps)
+ wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
if baseLinkerProps.Version_script != nil {
versionScript.Value = android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)
@@ -296,19 +335,19 @@
libs := baseLinkerProps.Header_libs
libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
libs = append(libs, baseLinkerProps.Static_libs...)
- libs = append(libs, baseLinkerProps.Whole_static_libs...)
+ wholeArchiveLibs := baseLinkerProps.Whole_static_libs
libs = android.SortedUniqueStrings(libs)
deps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, libs))
-
linkopts.SetValueForArch(arch.Name, getBp2BuildLinkerFlags(baseLinkerProps))
+ wholeArchiveDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
if baseLinkerProps.Version_script != nil {
versionScript.SetValueForArch(arch.Name,
android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
-
- sharedLibs := baseLinkerProps.Shared_libs
- dynamicDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
}
+
+ sharedLibs := baseLinkerProps.Shared_libs
+ dynamicDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
}
}
@@ -317,8 +356,9 @@
libs := baseLinkerProps.Header_libs
libs = append(libs, baseLinkerProps.Export_header_lib_headers...)
libs = append(libs, baseLinkerProps.Static_libs...)
- libs = append(libs, baseLinkerProps.Whole_static_libs...)
+ wholeArchiveLibs := baseLinkerProps.Whole_static_libs
libs = android.SortedUniqueStrings(libs)
+ wholeArchiveDeps.SetValueForOS(os.Name, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
deps.SetValueForOS(os.Name, android.BazelLabelForModuleDeps(ctx, libs))
linkopts.SetValueForOS(os.Name, getBp2BuildLinkerFlags(baseLinkerProps))
@@ -329,10 +369,11 @@
}
return linkerAttributes{
- deps: deps,
- dynamicDeps: dynamicDeps,
- linkopts: linkopts,
- versionScript: versionScript,
+ deps: deps,
+ dynamicDeps: dynamicDeps,
+ wholeArchiveDeps: wholeArchiveDeps,
+ linkopts: linkopts,
+ versionScript: versionScript,
}
}
diff --git a/cc/library.go b/cc/library.go
index 7e960a7..c5ff9b1 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -220,16 +220,29 @@
// For bp2build conversion.
type bazelCcLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Hdrs bazel.LabelListAttribute
- Copts bazel.StringListAttribute
- Linkopts bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- User_link_flags bazel.StringListAttribute
- Includes bazel.StringListAttribute
- Static_deps_for_shared bazel.LabelListAttribute
- Version_script bazel.LabelAttribute
+ // Attributes pertaining to both static and shared variants.
+ Srcs bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Dynamic_deps bazel.LabelListAttribute
+ Whole_archive_deps bazel.LabelListAttribute
+ Copts bazel.StringListAttribute
+ Includes bazel.StringListAttribute
+ Linkopts bazel.StringListAttribute
+ // Attributes pertaining to shared variant.
+ Shared_copts bazel.StringListAttribute
+ Shared_srcs bazel.LabelListAttribute
+ Static_deps_for_shared bazel.LabelListAttribute
+ Dynamic_deps_for_shared bazel.LabelListAttribute
+ Whole_archive_deps_for_shared bazel.LabelListAttribute
+ User_link_flags bazel.StringListAttribute
+ Version_script bazel.LabelAttribute
+ // Attributes pertaining to static variant.
+ Static_copts bazel.StringListAttribute
+ Static_srcs bazel.LabelListAttribute
+ Static_deps_for_static bazel.LabelListAttribute
+ Dynamic_deps_for_static bazel.LabelListAttribute
+ Whole_archive_deps_for_static bazel.LabelListAttribute
}
type bazelCcLibrary struct {
@@ -276,17 +289,26 @@
var srcs bazel.LabelListAttribute
srcs.Append(compilerAttrs.srcs)
- srcs.Append(staticAttrs.srcs)
attrs := &bazelCcLibraryAttributes{
- Srcs: srcs,
- Copts: compilerAttrs.copts,
- Linkopts: linkerAttrs.linkopts,
- Deps: linkerAttrs.deps,
- Dynamic_deps: linkerAttrs.dynamicDeps,
- Version_script: linkerAttrs.versionScript,
- Static_deps_for_shared: sharedAttrs.staticDeps,
- Includes: exportedIncludes,
+ Srcs: srcs,
+ Deps: linkerAttrs.deps,
+ Dynamic_deps: linkerAttrs.dynamicDeps,
+ Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+ Copts: compilerAttrs.copts,
+ Includes: exportedIncludes,
+ Linkopts: linkerAttrs.linkopts,
+ Shared_copts: sharedAttrs.copts,
+ Shared_srcs: sharedAttrs.srcs,
+ Static_deps_for_shared: sharedAttrs.staticDeps,
+ Whole_archive_deps_for_shared: sharedAttrs.wholeArchiveDeps,
+ Dynamic_deps_for_shared: sharedAttrs.dynamicDeps,
+ Version_script: linkerAttrs.versionScript,
+ Static_copts: staticAttrs.copts,
+ Static_srcs: staticAttrs.srcs,
+ Static_deps_for_static: staticAttrs.staticDeps,
+ Whole_archive_deps_for_static: staticAttrs.wholeArchiveDeps,
+ Dynamic_deps_for_static: staticAttrs.dynamicDeps,
}
props := bazel.BazelTargetModuleProperties{
@@ -2194,13 +2216,14 @@
}
type bazelCcLibraryStaticAttributes struct {
- Copts bazel.StringListAttribute
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Linkopts bazel.StringListAttribute
- Linkstatic bool
- Includes bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
+ Copts bazel.StringListAttribute
+ Srcs bazel.LabelListAttribute
+ Deps bazel.LabelListAttribute
+ Whole_archive_deps bazel.LabelListAttribute
+ Linkopts bazel.StringListAttribute
+ Linkstatic bool
+ Includes bazel.StringListAttribute
+ Hdrs bazel.LabelListAttribute
}
type bazelCcLibraryStatic struct {
@@ -2221,9 +2244,11 @@
exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
attrs := &bazelCcLibraryStaticAttributes{
- Copts: compilerAttrs.copts,
- Srcs: compilerAttrs.srcs,
- Deps: linkerAttrs.deps,
+ Copts: compilerAttrs.copts,
+ Srcs: compilerAttrs.srcs,
+ Deps: linkerAttrs.deps,
+ Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+
Linkopts: linkerAttrs.linkopts,
Linkstatic: true,
Includes: exportedIncludes,
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 0f2fd54..e91546e 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -95,9 +95,6 @@
prebuilt_apex {
name: "com.android.art",
src: "art.apex",
- exported_java_libs: [
- "mybootlib",
- ],
exported_bootclasspath_fragments: [
"mybootclasspathfragment",
],
diff --git a/sdk/bp.go b/sdk/bp.go
index 11ec8c6..e2dace8 100644
--- a/sdk/bp.go
+++ b/sdk/bp.go
@@ -25,6 +25,7 @@
type bpPropertySet struct {
properties map[string]interface{}
tags map[string]android.BpPropertyTag
+ comments map[string]string
order []string
}
@@ -133,10 +134,22 @@
return s.properties[name]
}
+func (s *bpPropertySet) getOptionalValue(name string) (interface{}, bool) {
+ value, ok := s.properties[name]
+ return value, ok
+}
+
func (s *bpPropertySet) getTag(name string) interface{} {
return s.tags[name]
}
+func (s *bpPropertySet) AddCommentForProperty(name, text string) {
+ if s.comments == nil {
+ s.comments = map[string]string{}
+ }
+ s.comments[name] = strings.TrimSpace(text)
+}
+
func (s *bpPropertySet) transformContents(transformer bpPropertyTransformer) {
var newOrder []string
for _, name := range s.order {
@@ -188,6 +201,12 @@
}
}
+func (s *bpPropertySet) removeProperty(name string) {
+ delete(s.properties, name)
+ delete(s.tags, name)
+ _, s.order = android.RemoveFromList(name, s.order)
+}
+
func (s *bpPropertySet) insertAfter(position string, name string, value interface{}) {
if s.properties[name] != nil {
panic("Property %q already exists in property set")
@@ -216,6 +235,19 @@
moduleType string
}
+func (m *bpModule) ModuleType() string {
+ return m.moduleType
+}
+
+func (m *bpModule) Name() string {
+ name, hasName := m.getOptionalValue("name")
+ if hasName {
+ return name.(string)
+ } else {
+ return ""
+ }
+}
+
var _ android.BpModule = (*bpModule)(nil)
type bpPropertyTransformer interface {
@@ -346,16 +378,26 @@
// is unique within this file.
func (f *bpFile) AddModule(module android.BpModule) {
m := module.(*bpModule)
- if name, ok := m.getValue("name").(string); ok {
- if f.modules[name] != nil {
- panic(fmt.Sprintf("Module %q already exists in bp file", name))
- }
-
- f.modules[name] = m
- f.order = append(f.order, m)
- } else {
- panic("Module does not have a name property, or it is not a string")
+ moduleType := module.ModuleType()
+ name := m.Name()
+ hasName := true
+ if name == "" {
+ // Use a prefixed module type as the name instead just in case this is something like a package
+ // of namespace module which does not require a name.
+ name = "#" + moduleType
+ hasName = false
}
+
+ if f.modules[name] != nil {
+ if hasName {
+ panic(fmt.Sprintf("Module %q already exists in bp file", name))
+ } else {
+ panic(fmt.Sprintf("Unnamed module type %q already exists in bp file", moduleType))
+ }
+ }
+
+ f.modules[name] = m
+ f.order = append(f.order, m)
}
func (f *bpFile) newModule(moduleType string) *bpModule {
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 624c0fa..b1c8aeb 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -169,23 +169,27 @@
var fields []reflect.StructField
// Iterate over the member types creating StructField and sdkMemberListProperty objects.
- for f, memberType := range sdkMemberTypes {
+ nextFieldIndex := 0
+ for _, memberType := range sdkMemberTypes {
+
p := memberType.SdkPropertyName()
- // Create a dynamic exported field for the member type's property.
- fields = append(fields, reflect.StructField{
- Name: proptools.FieldNameForProperty(p),
- Type: reflect.TypeOf([]string{}),
- Tag: `android:"arch_variant"`,
- })
+ var getter func(properties interface{}) []string
+ var setter func(properties interface{}, list []string)
+ if memberType.RequiresBpProperty() {
+ // Create a dynamic exported field for the member type's property.
+ fields = append(fields, reflect.StructField{
+ Name: proptools.FieldNameForProperty(p),
+ Type: reflect.TypeOf([]string{}),
+ Tag: `android:"arch_variant"`,
+ })
- // Copy the field index for use in the getter func as using the loop variable directly will
- // cause all funcs to use the last value.
- fieldIndex := f
+ // Copy the field index for use in the getter func as using the loop variable directly will
+ // cause all funcs to use the last value.
+ fieldIndex := nextFieldIndex
+ nextFieldIndex += 1
- // Create an sdkMemberListProperty for the member type.
- memberListProperty := &sdkMemberListProperty{
- getter: func(properties interface{}) []string {
+ getter = func(properties interface{}) []string {
// The properties is expected to be of the following form (where
// <Module_types> is the name of an SdkMemberType.SdkPropertyName().
// properties *struct {<Module_types> []string, ....}
@@ -195,9 +199,9 @@
//
list := reflect.ValueOf(properties).Elem().Field(fieldIndex).Interface().([]string)
return list
- },
+ }
- setter: func(properties interface{}, list []string) {
+ setter = func(properties interface{}, list []string) {
// The properties is expected to be of the following form (where
// <Module_types> is the name of an SdkMemberType.SdkPropertyName().
// properties *struct {<Module_types> []string, ....}
@@ -206,8 +210,13 @@
// *properties.<Module_types> = list
//
reflect.ValueOf(properties).Elem().Field(fieldIndex).Set(reflect.ValueOf(list))
- },
+ }
+ }
+ // Create an sdkMemberListProperty for the member type.
+ memberListProperty := &sdkMemberListProperty{
+ getter: getter,
+ setter: setter,
memberType: memberType,
// Dependencies added directly from member properties are always exported.
@@ -402,6 +411,9 @@
// Add dependencies from enabled and non CommonOS variants to the sdk member variants.
if s.Enabled() && !s.IsCommonOSVariant() {
for _, memberListProperty := range s.memberListProperties() {
+ if memberListProperty.getter == nil {
+ continue
+ }
names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
if len(names) > 0 {
tag := memberListProperty.dependencyTag
diff --git a/sdk/update.go b/sdk/update.go
index 853f6b0..a265676 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -266,8 +266,11 @@
}
s.builderForTests = builder
- // Create the prebuilt modules for each of the member modules.
+ // Group the variants for each member module together and then group the members of each member
+ // type together.
members := s.groupMemberVariantsByMemberThenType(ctx, memberVariantDeps)
+
+ // Create the prebuilt modules for each of the member modules.
for _, member := range members {
memberType := member.memberType
@@ -284,11 +287,6 @@
// to internal members with a unique module name and setting prefer: false.
unversionedTransformer := unversionedTransformation{
builder: builder,
- // Set the prefer based on the environment variable. This is a temporary work around to allow a
- // snapshot to be created that sets prefer: true.
- // TODO(b/174997203): Remove once the ability to select the modules to prefer can be done
- // dynamically at build time not at snapshot generation time.
- prefer: ctx.Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER"),
}
for _, unversioned := range builder.prebuiltOrder {
@@ -518,15 +516,19 @@
}
combined := sdkVariantToCombinedProperties[memberVariantDep.sdkVariant]
- memberTypeProperty := s.memberListProperty(memberVariantDep.memberType)
+ memberListProperty := s.memberListProperty(memberVariantDep.memberType)
memberName := ctx.OtherModuleName(memberVariantDep.variant)
+ if memberListProperty.getter == nil {
+ continue
+ }
+
// Append the member to the appropriate list, if it is not already present in the list.
- memberList := memberTypeProperty.getter(combined.dynamicProperties)
+ memberList := memberListProperty.getter(combined.dynamicProperties)
if !android.InList(memberName, memberList) {
memberList = append(memberList, memberName)
}
- memberTypeProperty.setter(combined.dynamicProperties, memberList)
+ memberListProperty.setter(combined.dynamicProperties, memberList)
}
return list
@@ -578,6 +580,9 @@
dynamicMemberTypeListProperties := combined.dynamicProperties
for _, memberListProperty := range s.memberListProperties() {
+ if memberListProperty.getter == nil {
+ continue
+ }
names := memberListProperty.getter(dynamicMemberTypeListProperties)
if len(names) > 0 {
propertySet.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names, false))
@@ -611,9 +616,11 @@
func (t unversionedToVersionedTransformation) transformModule(module *bpModule) *bpModule {
// Use a versioned name for the module but remember the original name for the
// snapshot.
- name := module.getValue("name").(string)
+ name := module.Name()
module.setProperty("name", t.builder.versionedSdkMemberName(name, true))
module.insertAfter("name", "sdk_member_name", name)
+ // Remove the prefer property if present as versioned modules never need marking with prefer.
+ module.removeProperty("prefer")
return module
}
@@ -629,20 +636,12 @@
type unversionedTransformation struct {
identityTransformation
builder *snapshotBuilder
- prefer bool
}
func (t unversionedTransformation) transformModule(module *bpModule) *bpModule {
// If the module is an internal member then use a unique name for it.
- name := module.getValue("name").(string)
+ name := module.Name()
module.setProperty("name", t.builder.unversionedSdkMemberName(name, true))
-
- // Set prefer. Setting this to false is not strictly required as that is the default but it does
- // provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to check
- // the behavior when a prebuilt is preferred. It also makes it explicit what the default behavior
- // is for the module.
- module.insertAfter("name", "prefer", t.prefer)
-
return module
}
@@ -693,12 +692,26 @@
func outputPropertySet(contents *generatedContents, set *bpPropertySet) {
contents.Indent()
+ addComment := func(name string) {
+ if text, ok := set.comments[name]; ok {
+ for _, line := range strings.Split(text, "\n") {
+ contents.Printfln("// %s", line)
+ }
+ }
+ }
+
// Output the properties first, followed by the nested sets. This ensures a
// consistent output irrespective of whether property sets are created before
// or after the properties. This simplifies the creation of the module.
for _, name := range set.order {
value := set.getValue(name)
+ // Do not write property sets in the properties phase.
+ if _, ok := value.(*bpPropertySet); ok {
+ continue
+ }
+
+ addComment(name)
switch v := value.(type) {
case []string:
length := len(v)
@@ -719,9 +732,6 @@
case bool:
contents.Printfln("%s: %t,", name, v)
- case *bpPropertySet:
- // Do not write property sets in the properties phase.
-
default:
contents.Printfln("%s: %q,", name, value)
}
@@ -733,6 +743,7 @@
// Only write property sets in the sets phase.
switch v := value.(type) {
case *bpPropertySet:
+ addComment(name)
contents.Printfln("%s: {", name)
outputPropertySet(contents, v)
contents.Printfln("},")
@@ -751,7 +762,9 @@
func (s *sdk) GetUnversionedAndroidBpContentsForTests() string {
contents := &generatedContents{}
generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
- return !strings.Contains(module.properties["name"].(string), "@")
+ name := module.Name()
+ // Include modules that are either unversioned or have no name.
+ return !strings.Contains(name, "@")
})
return contents.content.String()
}
@@ -759,7 +772,9 @@
func (s *sdk) GetVersionedAndroidBpContentsForTests() string {
contents := &generatedContents{}
generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
- return strings.Contains(module.properties["name"].(string), "@")
+ name := module.Name()
+ // Include modules that are either versioned or have no name.
+ return name == "" || strings.Contains(name, "@")
})
return contents.content.String()
}
@@ -1381,6 +1396,21 @@
memberType := member.memberType
+ // Do not add the prefer property if the member snapshot module is a source module type.
+ if !memberType.UsesSourceModuleTypeInSnapshot() {
+ // Set the prefer based on the environment variable. This is a temporary work around to allow a
+ // snapshot to be created that sets prefer: true.
+ // TODO(b/174997203): Remove once the ability to select the modules to prefer can be done
+ // dynamically at build time not at snapshot generation time.
+ prefer := ctx.sdkMemberContext.Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_PREFER")
+
+ // Set prefer. Setting this to false is not strictly required as that is the default but it does
+ // provide a convenient hook to post-process the generated Android.bp file, e.g. in tests to
+ // check the behavior when a prebuilt is preferred. It also makes it explicit what the default
+ // behavior is for the module.
+ bpModule.insertAfter("name", "prefer", prefer)
+ }
+
// Group the variants by os type.
variantsByOsType := make(map[android.OsType][]android.Module)
variants := member.Variants()
diff --git a/third_party/zip/android_test.go b/third_party/zip/android_test.go
index 9932c1b..46588d4 100644
--- a/third_party/zip/android_test.go
+++ b/third_party/zip/android_test.go
@@ -140,3 +140,83 @@
t.Errorf("Expected UnompressedSize64 %d, got %d", w, g)
}
}
+
+// Test for b/187485108: zip64 output can't be read by p7zip 16.02.
+func TestZip64P7ZipRecords(t *testing.T) {
+ if testing.Short() {
+ t.Skip("slow test; skipping")
+ }
+
+ const size = uint32max + 1
+ zipBytes := &bytes.Buffer{}
+ zip := NewWriter(zipBytes)
+ f, err := zip.CreateHeaderAndroid(&FileHeader{
+ Name: "large",
+ Method: Store,
+ UncompressedSize64: size,
+ CompressedSize64: size,
+ })
+ if err != nil {
+ t.Fatalf("Create: %v", err)
+ }
+ _, err = f.Write(make([]byte, size))
+ if err != nil {
+ t.Fatalf("Write: %v", err)
+ }
+ err = zip.Close()
+ if err != nil {
+ t.Fatalf("Close: %v", err)
+ }
+
+ buf := zipBytes.Bytes()
+ p := findSignatureInBlock(buf)
+ if p < 0 {
+ t.Fatalf("Missing signature")
+ }
+
+ b := readBuf(buf[p+4:]) // skip signature
+ d := &directoryEnd{
+ diskNbr: uint32(b.uint16()),
+ dirDiskNbr: uint32(b.uint16()),
+ dirRecordsThisDisk: uint64(b.uint16()),
+ directoryRecords: uint64(b.uint16()),
+ directorySize: uint64(b.uint32()),
+ directoryOffset: uint64(b.uint32()),
+ commentLen: b.uint16(),
+ }
+
+ // p7zip 16.02 wants regular end record directoryRecords to be accurate.
+ if g, w := d.directoryRecords, uint64(1); g != w {
+ t.Errorf("wanted directoryRecords %d, got %d", w, g)
+ }
+
+ if g, w := d.directorySize, uint64(uint32max); g != w {
+ t.Errorf("wanted directorySize %d, got %d", w, g)
+ }
+
+ if g, w := d.directoryOffset, uint64(uint32max); g != w {
+ t.Errorf("wanted directoryOffset %d, got %d", w, g)
+ }
+
+ r := bytes.NewReader(buf)
+
+ p64, err := findDirectory64End(r, int64(p))
+ if err != nil {
+ t.Fatalf("findDirectory64End: %v", err)
+ }
+ if p < 0 {
+ t.Fatalf("findDirectory64End: not found")
+ }
+ err = readDirectory64End(r, p64, d)
+ if err != nil {
+ t.Fatalf("readDirectory64End: %v", err)
+ }
+
+ if g, w := d.directoryRecords, uint64(1); g != w {
+ t.Errorf("wanted directoryRecords %d, got %d", w, g)
+ }
+
+ if g, w := d.directoryOffset, uint64(uint32max); g <= w {
+ t.Errorf("wanted directoryOffset > %d, got %d", w, g)
+ }
+}
diff --git a/third_party/zip/writer.go b/third_party/zip/writer.go
index 8dd986e..f526838 100644
--- a/third_party/zip/writer.go
+++ b/third_party/zip/writer.go
@@ -155,7 +155,14 @@
// store max values in the regular end record to signal that
// that the zip64 values should be used instead
- records = uint16max
+ // BEGIN ANDROID CHANGE: only store uintmax for the number of entries in the regular
+ // end record if it doesn't fit. p7zip 16.02 rejects zip files where the number of
+ // entries in the regular end record is larger than the number of entries counted
+ // in the central directory.
+ if records > uint16max {
+ records = uint16max
+ }
+ // END ANDROID CHANGE
size = uint32max
offset = uint32max
}