diff options
34 files changed, 713 insertions, 173 deletions
diff --git a/android/Android.bp b/android/Android.bp index aef18fec0..1cc7ffe1d 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -112,6 +112,7 @@ bootstrap_go_package { "soong_config_modules.go", "team.go", "test_asserts.go", + "test_mapping_zip.go", "test_suites.go", "testing.go", "transition.go", diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go index b698d24a5..205b85590 100644 --- a/android/aconfig_providers.go +++ b/android/aconfig_providers.go @@ -136,7 +136,7 @@ func aconfigUpdateAndroidBuildActions(ctx ModuleContext) { AconfigFiles: mergedAconfigFiles, ModeInfos: mergedModeInfos, }) - ctx.setAconfigPaths(getAconfigFilePaths(ctx.Module().base(), mergedAconfigFiles)) + ctx.setAconfigPaths(getAconfigFilePaths(getContainer(ctx.Module()), mergedAconfigFiles)) } } @@ -147,7 +147,8 @@ func aconfigUpdateAndroidMkData(ctx fillInEntriesContext, mod Module, data *Andr return } data.Extra = append(data.Extra, func(w io.Writer, outputFile Path) { - AndroidMkEmitAssignList(w, "LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles).Strings()) + AndroidMkEmitAssignList(w, "LOCAL_ACONFIG_FILES", getAconfigFilePaths( + getContainerUsingProviders(ctx, mod), info.AconfigFiles).Strings()) }) // If there is a Custom writer, it needs to support this provider. if data.Custom != nil { @@ -179,24 +180,29 @@ func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries // All of the files in the module potentially depend on the aconfig flag values. for idx, _ := range *entries { (*entries)[idx].ExtraEntries = append((*entries)[idx].ExtraEntries, - func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { - entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) + func(_ AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { + entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths( + getContainerUsingProviders(ctx, mod), info.AconfigFiles)) }, ) } } +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func aconfigUpdateAndroidMkInfos(ctx fillInEntriesContext, mod Module, infos *AndroidMkProviderInfo) { info, ok := OtherModuleProvider(ctx, mod, AconfigPropagatingProviderKey) if !ok || len(info.AconfigFiles) == 0 { return } // All of the files in the module potentially depend on the aconfig flag values. - infos.PrimaryInfo.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) + infos.PrimaryInfo.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths( + getContainerUsingProviders(ctx, mod), info.AconfigFiles)) if len(infos.ExtraInfo) > 0 { for _, ei := range (*infos).ExtraInfo { - ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles)) + ei.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths( + getContainerUsingProviders(ctx, mod), info.AconfigFiles)) } } } @@ -224,19 +230,39 @@ func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, genera return Paths{output} } -func getAconfigFilePaths(m *ModuleBase, aconfigFiles map[string]Paths) (paths Paths) { - // TODO(b/311155208): The default container here should be system. +func getContainer(m Module) string { container := "system" + base := m.base() + if base.SocSpecific() { + container = "vendor" + } else if base.ProductSpecific() { + container = "product" + } else if base.SystemExtSpecific() { + // system_ext and system partitions should be treated as one container + container = "system" + } - if m.SocSpecific() { + return container +} + +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func getContainerUsingProviders(ctx OtherModuleProviderContext, m Module) string { + container := "system" + commonInfo, _ := OtherModuleProvider(ctx, m, CommonModuleInfoKey) + if commonInfo.Vendor || commonInfo.Proprietary || commonInfo.SocSpecific { container = "vendor" - } else if m.ProductSpecific() { + } else if commonInfo.ProductSpecific { container = "product" - } else if m.SystemExtSpecific() { + } else if commonInfo.SystemExtSpecific { // system_ext and system partitions should be treated as one container container = "system" } + return container +} + +func getAconfigFilePaths(container string, aconfigFiles map[string]Paths) (paths Paths) { paths = append(paths, aconfigFiles[container]...) if container == "system" { // TODO(b/311155208): Once the default container is system, we can drop this. diff --git a/android/androidmk.go b/android/androidmk.go index c081ba372..d9d78f349 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -775,6 +775,8 @@ func (so *soongOnlyAndroidMkSingleton) GenerateBuildActions(ctx SingletonContext // In soong-only mode, we don't do most of the androidmk stuff. But disted files are still largely // defined through the androidmk mechanisms, so this function is an alternate implementation of // the androidmk singleton that just focuses on getting the dist contributions +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []Module) { allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods) @@ -895,28 +897,29 @@ func getSoongOnlyDataFromMods(ctx fillInEntriesContext, mods []Module) ([]distCo } } - if shouldSkipAndroidMkProcessing(ctx, mod.base()) { + commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + if commonInfo.SkipAndroidMkProcessing { continue } if info, ok := OtherModuleProvider(ctx, mod, AndroidMkInfoProvider); ok { // Deep copy the provider info since we need to modify the info later info := deepCopyAndroidMkProviderInfo(info) - info.PrimaryInfo.fillInEntries(ctx, mod) + info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) if info.PrimaryInfo.disabled() { continue } if moduleInfoJSON, ok := OtherModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok { moduleInfoJSONs = append(moduleInfoJSONs, moduleInfoJSON...) } - if contribution := info.PrimaryInfo.getDistContributions(ctx, mod); contribution != nil { + if contribution := info.PrimaryInfo.getDistContributions(ctx, mod, &commonInfo); contribution != nil { allDistContributions = append(allDistContributions, *contribution) } for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod) + ei.fillInEntries(ctx, mod, &commonInfo) if ei.disabled() { continue } - if contribution := ei.getDistContributions(ctx, mod); contribution != nil { + if contribution := ei.getDistContributions(ctx, mod, &commonInfo); contribution != nil { allDistContributions = append(allDistContributions, *contribution) } } @@ -1333,9 +1336,12 @@ type AndroidMkProviderInfoProducer interface { // TODO: rename it to AndroidMkEntriesProvider after AndroidMkEntriesProvider interface is gone. var AndroidMkInfoProvider = blueprint.NewProvider[*AndroidMkProviderInfo]() +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod Module, providerInfo *AndroidMkProviderInfo) error { - if shouldSkipAndroidMkProcessing(ctx, mod.base()) { + commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + if commonInfo.SkipAndroidMkProcessing { return nil } @@ -1345,11 +1351,11 @@ func translateAndroidMkEntriesInfoModule(ctx SingletonContext, w io.Writer, modu aconfigUpdateAndroidMkInfos(ctx, mod, &info) // Any new or special cases here need review to verify correct propagation of license information. - info.PrimaryInfo.fillInEntries(ctx, mod) + info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) info.PrimaryInfo.write(w) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod) + ei.fillInEntries(ctx, mod, &commonInfo) ei.write(w) } } @@ -1478,13 +1484,14 @@ func (a *AndroidMkInfo) AddCompatibilityTestSuites(suites ...string) { a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...) } -func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module) { +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) { helperInfo := AndroidMkInfo{ EntryMap: make(map[string][]string), } - base := mod.base() - name := base.BaseModuleName() + name := commonInfo.BaseModuleName if a.OverrideName != "" { name = a.OverrideName } @@ -1492,16 +1499,16 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module) { if a.Include == "" { a.Include = "$(BUILD_PREBUILT)" } - a.Required = append(a.Required, mod.RequiredModuleNames(ctx)...) - a.Required = append(a.Required, mod.VintfFragmentModuleNames(ctx)...) - a.Host_required = append(a.Host_required, mod.HostRequiredModuleNames()...) - a.Target_required = append(a.Target_required, mod.TargetRequiredModuleNames()...) + a.Required = append(a.Required, commonInfo.RequiredModuleNames...) + a.Required = append(a.Required, commonInfo.VintfFragmentModuleNames...) + a.Host_required = append(a.Host_required, commonInfo.HostRequiredModuleNames...) + a.Target_required = append(a.Target_required, commonInfo.TargetRequiredModuleNames...) - for _, distString := range a.GetDistForGoals(ctx, mod) { + for _, distString := range a.GetDistForGoals(ctx, mod, commonInfo) { a.HeaderStrings = append(a.HeaderStrings, distString) } - a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), base.BaseModuleName(), ctx.ModuleSubDir(mod))) + a.HeaderStrings = append(a.HeaderStrings, fmt.Sprintf("\ninclude $(CLEAR_VARS) # type: %s, name: %s, variant: %s", ctx.ModuleType(mod), commonInfo.BaseModuleName, ctx.ModuleSubDir(mod))) // Collect make variable assignment entries. helperInfo.SetString("LOCAL_PATH", ctx.ModuleDir(mod)) @@ -1526,7 +1533,7 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module) { // Soong may not have generated the install rule also when `no_full_install: true`. // Mark this module as uninstallable in order to prevent Make from creating an // install rule there. - helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", proptools.Bool(base.commonProperties.No_full_install)) + helperInfo.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", commonInfo.NoFullInstall) } if info.UncheckedModule { @@ -1541,31 +1548,31 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module) { helperInfo.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(info.TestData)...) } - if am, ok := mod.(ApexModule); ok { - helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform()) + if commonInfo.IsApexModule { + helperInfo.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", commonInfo.NotAvailableForPlatform) } - archStr := base.Arch().ArchType.String() + archStr := commonInfo.Target.Arch.ArchType.String() host := false - switch base.Os().Class { + switch commonInfo.Target.Os.Class { case Host: - if base.Target().HostCross { + if commonInfo.Target.HostCross { // Make cannot identify LOCAL_MODULE_HOST_CROSS_ARCH:= common. - if base.Arch().ArchType != Common { + if commonInfo.Target.Arch.ArchType != Common { helperInfo.SetString("LOCAL_MODULE_HOST_CROSS_ARCH", archStr) } } else { // Make cannot identify LOCAL_MODULE_HOST_ARCH:= common. - if base.Arch().ArchType != Common { + if commonInfo.Target.Arch.ArchType != Common { helperInfo.SetString("LOCAL_MODULE_HOST_ARCH", archStr) } } host = true case Device: // Make cannot identify LOCAL_MODULE_TARGET_ARCH:= common. - if base.Arch().ArchType != Common { - if base.Target().NativeBridge { - hostArchStr := base.Target().NativeBridgeHostArchName + if commonInfo.Target.Arch.ArchType != Common { + if commonInfo.Target.NativeBridge { + hostArchStr := commonInfo.Target.NativeBridgeHostArchName if hostArchStr != "" { helperInfo.SetString("LOCAL_MODULE_TARGET_ARCH", hostArchStr) } @@ -1574,27 +1581,28 @@ func (a *AndroidMkInfo) fillInEntries(ctx fillInEntriesContext, mod Module) { } } - if !base.InVendorRamdisk() { + if !commonInfo.InVendorRamdisk { helperInfo.AddPaths("LOCAL_FULL_INIT_RC", info.InitRcPaths) } if len(info.VintfFragmentsPaths) > 0 { helperInfo.AddPaths("LOCAL_FULL_VINTF_FRAGMENTS", info.VintfFragmentsPaths) } - helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", Bool(base.commonProperties.Proprietary)) - if Bool(base.commonProperties.Vendor) || Bool(base.commonProperties.Soc_specific) { + helperInfo.SetBoolIfTrue("LOCAL_PROPRIETARY_MODULE", commonInfo.Proprietary) + if commonInfo.Vendor || commonInfo.SocSpecific { helperInfo.SetString("LOCAL_VENDOR_MODULE", "true") } - helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", Bool(base.commonProperties.Device_specific)) - helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", Bool(base.commonProperties.Product_specific)) - helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", Bool(base.commonProperties.System_ext_specific)) - if base.commonProperties.Owner != nil { - helperInfo.SetString("LOCAL_MODULE_OWNER", *base.commonProperties.Owner) + helperInfo.SetBoolIfTrue("LOCAL_ODM_MODULE", commonInfo.DeviceSpecific) + helperInfo.SetBoolIfTrue("LOCAL_PRODUCT_MODULE", commonInfo.ProductSpecific) + helperInfo.SetBoolIfTrue("LOCAL_SYSTEM_EXT_MODULE", commonInfo.SystemExtSpecific) + if commonInfo.Owner != "" { + helperInfo.SetString("LOCAL_MODULE_OWNER", commonInfo.Owner) } } if host { - makeOs := base.Os().String() - if base.Os() == Linux || base.Os() == LinuxBionic || base.Os() == LinuxMusl { + os := commonInfo.Target.Os + makeOs := os.String() + if os == Linux || os == LinuxBionic || os == LinuxMusl { makeOs = "linux" } helperInfo.SetString("LOCAL_MODULE_HOST_OS", makeOs) @@ -1652,8 +1660,10 @@ func (a *AndroidMkInfo) write(w io.Writer) { // Compute the list of Make strings to declare phony goals and dist-for-goals // calls from the module's dist and dists properties. -func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module) []string { - distContributions := a.getDistContributions(ctx, mod) +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module, commonInfo *CommonModuleInfo) []string { + distContributions := a.getDistContributions(ctx, mod, commonInfo) if distContributions == nil { return nil } @@ -1662,9 +1672,11 @@ func (a *AndroidMkInfo) GetDistForGoals(ctx fillInEntriesContext, mod Module) [] } // Compute the contributions that the module makes to the dist. -func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod Module) *distContributions { - amod := mod.base() - name := amod.BaseModuleName() +// TODO(b/397766191): Change the signature to take ModuleProxy +// Please only access the module's internal data through providers. +func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod Module, + commonInfo *CommonModuleInfo) *distContributions { + name := commonInfo.BaseModuleName // Collate the set of associated tag/paths available for copying to the dist. // Start with an empty (nil) set. @@ -1700,12 +1712,12 @@ func (a *AndroidMkInfo) getDistContributions(ctx fillInEntriesContext, mod Modul // Collate the contributions this module makes to the dist. distContributions := &distContributions{} - if !exemptFromRequiredApplicableLicensesProperty(mod) { + if !commonInfo.ExemptFromRequiredApplicableLicensesProperty { distContributions.licenseMetadataFile = info.LicenseMetadataFile } // Iterate over this module's dist structs, merged from the dist and dists properties. - for _, dist := range amod.Dists() { + for _, dist := range commonInfo.Dists { // Get the list of goals this dist should be enabled for. e.g. sdk, droidcore goals := strings.Join(dist.Targets, " ") diff --git a/android/config.go b/android/config.go index 4b0aebb43..f6d08b841 100644 --- a/android/config.go +++ b/android/config.go @@ -2188,6 +2188,10 @@ func (c *config) UseR8StoreStoreFenceConstructorInlining() bool { return c.productVariables.GetBuildFlagBool("RELEASE_R8_STORE_STORE_FENCE_CONSTRUCTOR_INLINING") } +func (c *config) UseR8GlobalCheckNotNullFlags() bool { + return c.productVariables.GetBuildFlagBool("RELEASE_R8_GLOBAL_CHECK_NOT_NULL_FLAGS") +} + func (c *config) UseDexV41() bool { return c.productVariables.GetBuildFlagBool("RELEASE_USE_DEX_V41") } diff --git a/android/module.go b/android/module.go index f359e9f4d..996c64e52 100644 --- a/android/module.go +++ b/android/module.go @@ -1922,6 +1922,23 @@ type CommonModuleInfo struct { // The primary licenses property, may be nil, records license metadata for the module. PrimaryLicensesProperty applicableLicensesProperty Owner string + Vendor bool + Proprietary bool + SocSpecific bool + ProductSpecific bool + SystemExtSpecific bool + DeviceSpecific bool + // When set to true, this module is not installed to the full install path (ex: under + // out/target/product/<name>/<partition>). It can be installed only to the packaging + // modules like android_filesystem. + NoFullInstall bool + InVendorRamdisk bool + ExemptFromRequiredApplicableLicensesProperty bool + RequiredModuleNames []string + HostRequiredModuleNames []string + TargetRequiredModuleNames []string + VintfFragmentModuleNames []string + Dists []Dist } type ApiLevelOrPlatform struct { @@ -2266,7 +2283,21 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) SkipInstall: m.commonProperties.SkipInstall, Host: m.Host(), PrimaryLicensesProperty: m.primaryLicensesProperty, - Owner: m.Owner(), + Owner: m.module.Owner(), + SocSpecific: Bool(m.commonProperties.Soc_specific), + Vendor: Bool(m.commonProperties.Vendor), + Proprietary: Bool(m.commonProperties.Proprietary), + ProductSpecific: Bool(m.commonProperties.Product_specific), + SystemExtSpecific: Bool(m.commonProperties.System_ext_specific), + DeviceSpecific: Bool(m.commonProperties.Device_specific), + NoFullInstall: proptools.Bool(m.commonProperties.No_full_install), + InVendorRamdisk: m.InVendorRamdisk(), + ExemptFromRequiredApplicableLicensesProperty: exemptFromRequiredApplicableLicensesProperty(m.module), + RequiredModuleNames: m.module.RequiredModuleNames(ctx), + HostRequiredModuleNames: m.module.HostRequiredModuleNames(), + TargetRequiredModuleNames: m.module.TargetRequiredModuleNames(), + VintfFragmentModuleNames: m.module.VintfFragmentModuleNames(ctx), + Dists: m.Dists(), } if mm, ok := m.module.(interface { MinSdkVersion(ctx EarlyModuleContext) ApiLevel diff --git a/android/path_properties.go b/android/path_properties.go index 55a4dc066..d769d58c4 100644 --- a/android/path_properties.go +++ b/android/path_properties.go @@ -54,12 +54,14 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { var pathDeviceFirstPrefer32Properties []string var pathDeviceCommonProperties []string var pathCommonOsProperties []string + var pathHostCommonProperties []string for _, ps := range props { pathProperties = append(pathProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path")...) pathDeviceFirstProperties = append(pathDeviceFirstProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first")...) pathDeviceFirstPrefer32Properties = append(pathDeviceFirstPrefer32Properties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_first_prefer32")...) pathDeviceCommonProperties = append(pathDeviceCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_device_common")...) pathCommonOsProperties = append(pathCommonOsProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_common_os")...) + pathHostCommonProperties = append(pathHostCommonProperties, taggedPropertiesForPropertyStruct(ctx, ps, "path_host_common")...) } // Remove duplicates to avoid multiple dependencies. @@ -68,6 +70,7 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { pathDeviceFirstPrefer32Properties = FirstUniqueStrings(pathDeviceFirstPrefer32Properties) pathDeviceCommonProperties = FirstUniqueStrings(pathDeviceCommonProperties) pathCommonOsProperties = FirstUniqueStrings(pathCommonOsProperties) + pathHostCommonProperties = FirstUniqueStrings(pathHostCommonProperties) // Add dependencies to anything that is a module reference. for _, s := range pathProperties { @@ -108,6 +111,12 @@ func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) { ctx.AddVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m) } } + // properties tagged "path_host_common" get the host common variant + for _, s := range pathHostCommonProperties { + if m, t := SrcIsModuleWithTag(s); m != "" { + ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), sourceOrOutputDepTag(m, t), m) + } + } // properties tagged "path_common_os" get the CommonOs variant for _, s := range pathCommonOsProperties { if m, t := SrcIsModuleWithTag(s); m != "" { diff --git a/android/test_mapping_zip.go b/android/test_mapping_zip.go new file mode 100644 index 000000000..8dc70d7fe --- /dev/null +++ b/android/test_mapping_zip.go @@ -0,0 +1,49 @@ +// Copyright 2025 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +func init() { + InitRegistrationContext.RegisterSingletonType("test_mapping_zip_singleton", testMappingZipSingletonFactory) +} + +func testMappingZipSingletonFactory() Singleton { + return &testMappingZipSingleton{} +} + +type testMappingZipSingleton struct{} + +func (s *testMappingZipSingleton) GenerateBuildActions(ctx SingletonContext) { + fileListFile := PathForArbitraryOutput(ctx, ".module_paths", "TEST_MAPPING.list") + out := PathForOutput(ctx, "test_mappings.zip") + dep := PathForOutput(ctx, "test_mappings.zip.d") + + // disabled-presubmit-tests used to be filled out based on modules that set + // LOCAL_PRESUBMIT_DISABLED. But that's no longer used and there was never a soong equivalent + // anyways, so just always create an empty file. + disabledPresubmitTestsFile := PathForOutput(ctx, "disabled-presubmit-tests") + WriteFileRule(ctx, disabledPresubmitTestsFile, "") + + builder := NewRuleBuilder(pctx, ctx) + builder.Command().BuiltTool("soong_zip"). + FlagWithOutput("-o ", out). + FlagWithInput("-l ", fileListFile). + FlagWithArg("-e ", "disabled-presubmit-tests"). + FlagWithInput("-f ", disabledPresubmitTestsFile) + builder.Command().Textf("echo '%s : ' $(cat %s) > ", out, fileListFile).DepFile(dep) + builder.Build("test_mappings_zip", "build TEST_MAPPING zip") + + ctx.Phony("test_mapping", out) + ctx.DistForGoals([]string{"dist_files", "test_mapping"}, out) +} diff --git a/android/testing.go b/android/testing.go index 0cab0abdf..1962fdea5 100644 --- a/android/testing.go +++ b/android/testing.go @@ -1197,10 +1197,11 @@ func AndroidMkInfoForTest(t *testing.T, ctx *TestContext, mod Module) *AndroidMk info := OtherModuleProviderOrDefault(ctx, mod, AndroidMkInfoProvider) aconfigUpdateAndroidMkInfos(ctx, mod, info) - info.PrimaryInfo.fillInEntries(ctx, mod) + commonInfo, _ := OtherModuleProvider(ctx, mod, CommonModuleInfoKey) + info.PrimaryInfo.fillInEntries(ctx, mod, &commonInfo) if len(info.ExtraInfo) > 0 { for _, ei := range info.ExtraInfo { - ei.fillInEntries(ctx, mod) + ei.fillInEntries(ctx, mod, &commonInfo) } } diff --git a/apex/apex.go b/apex/apex.go index 4b510f8f1..6e4685b1f 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -82,10 +82,6 @@ type apexBundleProperties struct { // /system/sepolicy/apex/<module_name>_file_contexts. File_contexts *string `android:"path"` - // By default, file_contexts is amended by force-labelling / and /apex_manifest.pb as system_file - // to avoid mistakes. When set as true, no force-labelling. - Use_file_contexts_as_is *bool - // Path to the canned fs config file for customizing file's // uid/gid/mod/capabilities. The content of this file is appended to the // default config, so that the custom entries are preferred. The format is diff --git a/apex/builder.go b/apex/builder.go index 842771920..15737f8c7 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -428,8 +428,6 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Path { ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", fileContexts.String()) } - useFileContextsAsIs := proptools.Bool(a.properties.Use_file_contexts_as_is) - output := android.PathForModuleOut(ctx, "file_contexts") rule := android.NewRuleBuilder(pctx, ctx) @@ -446,11 +444,9 @@ func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.Path { rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output) // new line rule.Command().Text("echo").Text(">>").Output(output) - if !useFileContextsAsIs { - // force-label /apex_manifest.pb and / - rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output) - rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output) - } + // force-label /apex_manifest.pb and / + rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output) + rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output) rule.Build("file_contexts."+a.Name(), "Generate file_contexts") return output diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index cf7ea8af9..61f79d695 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -471,3 +471,120 @@ func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexNam t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual) } } + +func TestCheckSystemServerOrderWithArtApex(t *testing.T) { + preparers := android.GroupFixturePreparers( + java.PrepareForTestWithDexpreopt, + java.PrepareForTestWithJavaSdkLibraryFiles, + PrepareForTestWithApexBuildComponents, + prepareForTestWithArtApex, + java.FixtureConfigureBootJars("com.android.art:framework-art"), + dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-apex1", "com.android.art:service-art"), + java.FixtureWithLastReleaseApis("baz"), + ) + + // Creates a com.android.art apex with a bootclasspath fragment and a systemserverclasspath fragment, and a + // com.android.apex1 prebuilt whose bootclasspath fragment depends on the com.android.art bootclasspath fragment. + // Verifies that the checkSystemServerOrder doesn't get confused by the bootclasspath dependencies and report + // that service-apex1 depends on service-art. + result := preparers.RunTestWithBp(t, ` + apex { + name: "com.android.art", + key: "com.android.art.key", + bootclasspath_fragments: ["art-bootclasspath-fragment"], + systemserverclasspath_fragments: ["art-systemserverclasspath-fragment"], + updatable: false, + } + + apex_key { + name: "com.android.art.key", + public_key: "com.android.art.avbpubkey", + private_key: "com.android.art.pem", + } + + bootclasspath_fragment { + name: "art-bootclasspath-fragment", + image_name: "art", + contents: ["framework-art"], + apex_available: [ + "com.android.art", + ], + hidden_api: { + split_packages: ["*"], + }, + } + + java_library { + name: "framework-art", + apex_available: ["com.android.art"], + srcs: ["a.java"], + compile_dex: true, + } + + systemserverclasspath_fragment { + name: "art-systemserverclasspath-fragment", + apex_available: ["com.android.art"], + contents: ["service-art"], + } + + java_library { + name: "service-art", + srcs: ["a.java"], + apex_available: ["com.android.art"], + compile_dex: true, + } + + prebuilt_apex { + name: "com.android.apex1", + arch: { + arm64: { + src: "myapex-arm64.apex", + }, + arm: { + src: "myapex-arm.apex", + }, + }, + exported_bootclasspath_fragments: ["com.android.apex1-bootclasspath-fragment"], + exported_systemserverclasspath_fragments: ["com.android.apex1-systemserverclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "com.android.apex1-bootclasspath-fragment", + visibility: ["//visibility:public"], + apex_available: ["com.android.apex1"], + contents: ["framework-apex1"], + fragments: [ + { + apex: "com.android.art", + module: "art-bootclasspath-fragment", + }, + ], + hidden_api: { + annotation_flags: "hiddenapi/annotation-flags.csv", + metadata: "hiddenapi/metadata.csv", + index: "hiddenapi/index.csv", + stub_flags: "hiddenapi/stub-flags.csv", + all_flags: "hiddenapi/all-flags.csv", + }, + } + + java_import { + name: "framework-apex1", + apex_available: ["com.android.apex1"], + } + + prebuilt_systemserverclasspath_fragment { + name: "com.android.apex1-systemserverclasspath-fragment", + apex_available: ["com.android.apex1"], + contents: ["service-apex1"], + } + + java_import { + name: "service-apex1", + installable: true, + apex_available: ["com.android.apex1"], + sdk_version: "current", + }`) + + _ = result +} diff --git a/cc/Android.bp b/cc/Android.bp index 3b29ae8cf..1ac5a4a8f 100644 --- a/cc/Android.bp +++ b/cc/Android.bp @@ -36,6 +36,7 @@ bootstrap_go_package { "linkable.go", "lto.go", "makevars.go", + "misc_disted_files.go", "orderfile.go", "prebuilt.go", "proto.go", diff --git a/cc/fuzz.go b/cc/fuzz.go index a8e4cb70a..bd3d8e431 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -353,6 +353,7 @@ func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPa fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data) fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_common_data)...) fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Device_first_data)...) + fuzzPackagedModule.Data = append(fuzzPackagedModule.Data, android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Host_common_data)...) if fuzzPackagedModule.FuzzProperties.Dictionary != nil { fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary) diff --git a/cc/makevars.go b/cc/makevars.go index c94510280..9358755cc 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -100,15 +100,7 @@ func makeVarsProvider(ctx android.MakeVarsContext) { // Filter vendor_public_library that are exported to make var exportedVendorPublicLibraries []string - var warningsAllowed []string - var usingWnoErrors []string - var missingProfiles []string ctx.VisitAllModules(func(module android.Module) { - if v, ok := android.OtherModuleProvider(ctx, module, CcMakeVarsInfoProvider); ok { - warningsAllowed = android.AppendIfNotZero(warningsAllowed, v.WarningsAllowed) - usingWnoErrors = android.AppendIfNotZero(usingWnoErrors, v.UsingWnoError) - missingProfiles = android.AppendIfNotZero(missingProfiles, v.MissingProfile) - } if ccModule, ok := module.(*Module); ok { baseName := ccModule.BaseModuleName() if ccModule.IsVendorPublicLibrary() && module.ExportedToMake() { @@ -123,9 +115,6 @@ func makeVarsProvider(ctx android.MakeVarsContext) { ctx.Strict("LSDUMP_PATHS", strings.Join(lsdumpPaths, " ")) ctx.Strict("ANDROID_WARNING_ALLOWED_PROJECTS", makeStringOfWarningAllowedProjects()) - ctx.Strict("SOONG_MODULES_WARNINGS_ALLOWED", makeVarsString(warningsAllowed)) - ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeVarsString(usingWnoErrors)) - ctx.Strict("SOONG_MODULES_MISSING_PGO_PROFILE_FILE", makeVarsString(missingProfiles)) ctx.Strict("CLANG_COVERAGE_CONFIG_CFLAGS", strings.Join(clangCoverageCFlags, " ")) ctx.Strict("CLANG_COVERAGE_CONFIG_COMMFLAGS", strings.Join(clangCoverageCommonFlags, " ")) diff --git a/cc/misc_disted_files.go b/cc/misc_disted_files.go new file mode 100644 index 000000000..4bdffaa03 --- /dev/null +++ b/cc/misc_disted_files.go @@ -0,0 +1,89 @@ +// Copyright 2025 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cc + +import ( + "android/soong/android" + "strings" +) + +func init() { + android.InitRegistrationContext.RegisterSingletonType("cc_misc_disted_files", ccMiscDistedFilesSingletonFactory) +} + +func ccMiscDistedFilesSingletonFactory() android.Singleton { + return &ccMiscDistedFilesSingleton{} +} + +type ccMiscDistedFilesSingleton struct { + warningsAllowed []string + usingWnoErrors []string +} + +func (s *ccMiscDistedFilesSingleton) GenerateBuildActions(ctx android.SingletonContext) { + var warningsAllowed []string + var usingWnoErrors []string + var missingProfiles []string + ctx.VisitAllModules(func(module android.Module) { + if v, ok := android.OtherModuleProvider(ctx, module, CcMakeVarsInfoProvider); ok { + warningsAllowed = android.AppendIfNotZero(warningsAllowed, v.WarningsAllowed) + usingWnoErrors = android.AppendIfNotZero(usingWnoErrors, v.UsingWnoError) + missingProfiles = android.AppendIfNotZero(missingProfiles, v.MissingProfile) + } + }) + + warningsAllowed = android.SortedUniqueStrings(warningsAllowed) + usingWnoErrors = android.SortedUniqueStrings(usingWnoErrors) + missingProfiles = android.SortedUniqueStrings(missingProfiles) + + s.warningsAllowed = warningsAllowed + s.usingWnoErrors = usingWnoErrors + + var sb strings.Builder + sb.WriteString("# Modules using -Wno-error\n") + for _, nwe := range usingWnoErrors { + sb.WriteString(nwe) + sb.WriteString("\n") + } + sb.WriteString("# Modules that allow warnings\n") + for _, wa := range warningsAllowed { + sb.WriteString(wa) + sb.WriteString("\n") + } + wallWerrFile := android.PathForOutput(ctx, "wall_werror.txt") + android.WriteFileRuleVerbatim(ctx, wallWerrFile, sb.String()) + + // Only dist this file in soong-only builds. In soong+make builds, it contains information + // from make modules, so we'll still rely on make to build and dist it. + if !ctx.Config().KatiEnabled() { + ctx.DistForGoal("droidcore-unbundled", wallWerrFile) + } + + var sb2 strings.Builder + sb2.WriteString("# Modules missing PGO profile files\n") + for _, mp := range missingProfiles { + sb2.WriteString(mp) + sb2.WriteString("\n") + } + profileMissingFile := android.PathForOutput(ctx, "pgo_profile_file_missing.txt") + android.WriteFileRuleVerbatim(ctx, profileMissingFile, sb2.String()) + + ctx.DistForGoal("droidcore-unbundled", profileMissingFile) +} + +func (s *ccMiscDistedFilesSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.Strict("SOONG_MODULES_WARNINGS_ALLOWED", strings.Join(s.warningsAllowed, " ")) + ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", strings.Join(s.usingWnoErrors, " ")) +} diff --git a/cc/test.go b/cc/test.go index 2c5c36eac..d2c4b28e8 100644 --- a/cc/test.go +++ b/cc/test.go @@ -94,6 +94,11 @@ type TestBinaryProperties struct { // of a host test. Device_first_data []string `android:"path_device_first"` + // Same as data, but will add dependencies on modules using the host's os variation and + // the common arch variation. Useful for a device test that wants to depend on a host + // module, for example to include a custom Tradefed test runner. + Host_common_data []string `android:"path_host_common"` + // list of shared library modules that should be installed alongside the test Data_libs []string `android:"arch_variant"` @@ -345,6 +350,7 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...) dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_first_data)...) + dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...) for _, dataSrcPath := range dataSrcPaths { test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go index d9573a3e3..acfa8e073 100644 --- a/ci_tests/ci_test_package_zip.go +++ b/ci_tests/ci_test_package_zip.go @@ -190,6 +190,10 @@ func createOutput(ctx android.ModuleContext, pctx android.PackageContext) androi } for _, installedFile := range installedFilesInfo.InstallFiles { + // there are additional installed files for some app-class modules, we only need the .apk files in the test package + if class == "app" && installedFile.Ext() != ".apk" { + continue + } name := removeFileExtension(installedFile.Base()) f := strings.TrimPrefix(installedFile.String(), productOut+"/") if strings.HasPrefix(f, "out") { diff --git a/cmd/symbols_map/symbols_map.go b/cmd/symbols_map/symbols_map.go index c56cf93e8..3955c8ad1 100644 --- a/cmd/symbols_map/symbols_map.go +++ b/cmd/symbols_map/symbols_map.go @@ -72,6 +72,7 @@ func main() { elfFile := flags.String("elf", "", "extract identifier from an elf file") r8File := flags.String("r8", "", "extract identifier from an r8 dictionary") + locationFlag := flags.String("location", "", "an override for the value of the location field in the proto. If not specified, the filename will be used") merge := flags.String("merge", "", "merge multiple identifier protos") writeIfChanged := flags.Bool("write_if_changed", false, "only write output file if it is modified") @@ -134,6 +135,10 @@ func main() { panic("shouldn't get here") } + if *locationFlag != "" { + location = *locationFlag + } + mapping := symbols_map_proto.Mapping{ Identifier: proto.String(identifier), Location: proto.String(location), diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 1452b412e..699a6757d 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -283,10 +283,7 @@ func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]" clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]" - if systemServerClasspathJars.ContainsJar(module.Name) { - // TODO(b/397461231): renable this check - //checkSystemServerOrder(ctx, jarIndex) - } else { + if !systemServerClasspathJars.ContainsJar(module.Name) { // Standalone jars are loaded by separate class loaders with SYSTEMSERVERCLASSPATH as the // parent. clcHostString = "PCL[];" + clcHostString @@ -578,29 +575,6 @@ func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.Out } } -// Check the order of jars on the system server classpath and give a warning/error if a jar precedes -// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't -// have the dependency jar in the class loader context, and it won't be able to resolve any -// references to its classes and methods. -func checkSystemServerOrder(ctx android.PathContext, jarIndex int) { - mctx, isModule := ctx.(android.ModuleContext) - if isModule { - config := GetGlobalConfig(ctx) - jars := config.AllSystemServerClasspathJars(ctx) - mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { - depIndex := jars.IndexOfJar(dep.Name()) - if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { - jar := jars.Jar(jarIndex) - dep := jars.Jar(depIndex) - mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+ - " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+ - " references from '%s' to '%s'.\n", jar, dep, jar, dep) - } - return true - }) - } -} - // Returns path to a file containing the reult of verify_uses_libraries check (empty if the check // has succeeded, or an error message if it failed). func UsesLibrariesStatusFile(ctx android.ModuleContext) android.WritablePath { diff --git a/filesystem/android_device.go b/filesystem/android_device.go index 4ee5681dc..fef4aeb43 100644 --- a/filesystem/android_device.go +++ b/filesystem/android_device.go @@ -17,16 +17,24 @@ package filesystem import ( "cmp" "fmt" + "path/filepath" "slices" "strings" "sync/atomic" "android/soong/android" + "android/soong/java" "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) +var proguardDictToProto = pctx.AndroidStaticRule("proguard_dict_to_proto", blueprint.RuleParams{ + Command: `${symbols_map} -r8 $in -location $location -write_if_changed $out`, + Restat: true, + CommandDeps: []string{"${symbols_map}"}, +}, "location") + type PartitionNameProperties struct { // Name of the super partition filesystem module Super_partition_name *string @@ -89,6 +97,10 @@ type androidDevice struct { deviceProps DeviceProperties allImagesZip android.Path + + proguardDictZip android.Path + proguardDictMapping android.Path + proguardUsageZip android.Path } func AndroidDeviceFactory() android.Module { @@ -161,7 +173,11 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } + allInstalledModules := a.allInstalledModules(ctx) + a.buildTargetFilesZip(ctx) + a.buildProguardZips(ctx, allInstalledModules) + var deps []android.Path if proptools.String(a.partitionProps.Super_partition_name) != "" { superImage := ctx.GetDirectDepProxyWithTag(*a.partitionProps.Super_partition_name, superPartitionDepTag) @@ -214,7 +230,7 @@ func (a *androidDevice) GenerateAndroidBuildActions(ctx android.ModuleContext) { allImagesZip := android.PathForModuleOut(ctx, "all_images.zip") allImagesZipBuilder := android.NewRuleBuilder(pctx, ctx) - cmd := allImagesZipBuilder.Command().BuiltTool("soong_zip").Flag("--sort_entries") + cmd := allImagesZipBuilder.Command().BuiltTool("soong_zip") for _, dep := range deps { cmd.FlagWithArg("-e ", dep.Base()) cmd.FlagWithInput("-f ", dep) @@ -281,22 +297,32 @@ func (a *androidDevice) allInstalledModules(ctx android.ModuleContext) []android return ret } +func insertBeforeExtension(file, insertion string) string { + ext := filepath.Ext(file) + return strings.TrimSuffix(file, ext) + insertion + ext +} + func (a *androidDevice) distFiles(ctx android.ModuleContext) { - if !ctx.Config().KatiEnabled() { - if proptools.Bool(a.deviceProps.Main_device) { - fsInfoMap := a.getFsInfos(ctx) - for _, partition := range android.SortedKeys(fsInfoMap) { - fsInfo := fsInfoMap[partition] - if fsInfo.InstalledFiles.Json != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json) - } - if fsInfo.InstalledFiles.Txt != nil { - ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt) - } + if !ctx.Config().KatiEnabled() && proptools.Bool(a.deviceProps.Main_device) { + fsInfoMap := a.getFsInfos(ctx) + for _, partition := range android.SortedKeys(fsInfoMap) { + fsInfo := fsInfoMap[partition] + if fsInfo.InstalledFiles.Json != nil { + ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Json) + } + if fsInfo.InstalledFiles.Txt != nil { + ctx.DistForGoal("droidcore-unbundled", fsInfo.InstalledFiles.Txt) } } - } + namePrefix := "" + if ctx.Config().HasDeviceProduct() { + namePrefix = ctx.Config().DeviceProduct() + "-" + } + ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER")) + } } func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) { @@ -305,6 +331,56 @@ func (a *androidDevice) MakeVars(ctx android.MakeVarsModuleContext) { } } +func (a *androidDevice) buildProguardZips(ctx android.ModuleContext, allInstalledModules []android.Module) { + dictZip := android.PathForModuleOut(ctx, "proguard-dict.zip") + dictZipBuilder := android.NewRuleBuilder(pctx, ctx) + dictZipCmd := dictZipBuilder.Command().BuiltTool("soong_zip").Flag("-d").FlagWithOutput("-o ", dictZip) + + dictMapping := android.PathForModuleOut(ctx, "proguard-dict-mapping.textproto") + dictMappingBuilder := android.NewRuleBuilder(pctx, ctx) + dictMappingCmd := dictMappingBuilder.Command().BuiltTool("symbols_map").Flag("-merge").Output(dictMapping) + + protosDir := android.PathForModuleOut(ctx, "proguard_mapping_protos") + + usageZip := android.PathForModuleOut(ctx, "proguard-usage.zip") + usageZipBuilder := android.NewRuleBuilder(pctx, ctx) + usageZipCmd := usageZipBuilder.Command().BuiltTool("merge_zips").Output(usageZip) + + for _, mod := range allInstalledModules { + if proguardInfo, ok := android.OtherModuleProvider(ctx, mod, java.ProguardProvider); ok { + // Maintain these out/target/common paths for backwards compatibility. They may be able + // to be changed if tools look up file locations from the protobuf, but I'm not + // exactly sure how that works. + dictionaryFakePath := fmt.Sprintf("out/target/common/obj/%s/%s_intermediates/proguard_dictionary", proguardInfo.Class, proguardInfo.ModuleName) + dictZipCmd.FlagWithArg("-e ", dictionaryFakePath) + dictZipCmd.FlagWithInput("-f ", proguardInfo.ProguardDictionary) + dictZipCmd.Textf("-e out/target/common/obj/%s/%s_intermediates/classes.jar", proguardInfo.Class, proguardInfo.ModuleName) + dictZipCmd.FlagWithInput("-f ", proguardInfo.ClassesJar) + + protoFile := protosDir.Join(ctx, filepath.Dir(dictionaryFakePath), "proguard_dictionary.textproto") + ctx.Build(pctx, android.BuildParams{ + Rule: proguardDictToProto, + Input: proguardInfo.ProguardDictionary, + Output: protoFile, + Args: map[string]string{ + "location": dictionaryFakePath, + }, + }) + dictMappingCmd.Input(protoFile) + + usageZipCmd.Input(proguardInfo.ProguardUsageZip) + } + } + + dictZipBuilder.Build("proguard_dict_zip", "Building proguard dictionary zip") + dictMappingBuilder.Build("proguard_dict_mapping_proto", "Building proguard mapping proto") + usageZipBuilder.Build("proguard_usage_zip", "Building proguard usage zip") + + a.proguardDictZip = dictZip + a.proguardDictMapping = dictMapping + a.proguardUsageZip = usageZip +} + // Helper structs for target_files.zip creation type targetFilesZipCopy struct { srcModule *string diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index 1ce6131aa..28eb36d1e 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -33,11 +33,14 @@ import ( "github.com/google/blueprint/proptools" ) +var pctx = android.NewPackageContext("android/soong/filesystem") + func init() { registerBuildComponents(android.InitRegistrationContext) registerMutators(android.InitRegistrationContext) pctx.HostBinToolVariable("fileslist", "fileslist") pctx.HostBinToolVariable("fs_config", "fs_config") + pctx.HostBinToolVariable("symbols_map", "symbols_map") } func registerBuildComponents(ctx android.RegistrationContext) { @@ -576,8 +579,6 @@ func buildInstalledFiles(ctx android.ModuleContext, partition string, rootDir an return txt, json } -var pctx = android.NewPackageContext("android/soong/filesystem") - func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { validatePartitionType(ctx, f) if f.filesystemBuilder.ShouldUseVintfFragmentModuleOnly() { diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go index 3fd79a719..83ccd89ae 100644 --- a/fuzz/fuzz_common.go +++ b/fuzz/fuzz_common.go @@ -427,6 +427,12 @@ type FuzzProperties struct { // device's first architecture's variant. Can be useful to add device-built apps to the data // of a host test. Device_first_data []string `android:"path_device_first"` + + // Same as data, but will add dependencies on modules using the host's os variation and + // the common arch variation. Useful for a device test that wants to depend on a host + // module, for example to include a custom Tradefed test runner. + Host_common_data []string `android:"path_host_common"` + // Optional dictionary to be installed to the fuzz target's output directory. Dictionary *string `android:"path"` // Define the fuzzing frameworks this fuzz target can be built for. If diff --git a/java/app.go b/java/app.go index 9b10bf3cd..17548e74a 100644 --- a/java/app.go +++ b/java/app.go @@ -452,6 +452,16 @@ func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { android.SetProvider(ctx, AppInfoProvider, appInfo) a.requiredModuleNames = a.getRequiredModuleNames(ctx) + + if a.dexer.proguardDictionary.Valid() { + android.SetProvider(ctx, ProguardProvider, ProguardInfo{ + ModuleName: ctx.ModuleName(), + Class: "APPS", + ProguardDictionary: a.dexer.proguardDictionary.Path(), + ProguardUsageZip: a.dexer.proguardUsageZip.Path(), + ClassesJar: a.implementationAndResourcesJar, + }) + } } func (a *AndroidApp) getRequiredModuleNames(ctx android.ModuleContext) []string { @@ -1636,6 +1646,7 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_common_data)...) a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_data)...) a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Device_first_prefer32_data)...) + a.data = append(a.data, android.PathsForModuleSrc(ctx, a.testProperties.Host_common_data)...) // Install test deps if !ctx.Config().KatiEnabled() { diff --git a/java/dex.go b/java/dex.go index c9d3f376d..ed2df2103 100644 --- a/java/dex.go +++ b/java/dex.go @@ -435,6 +435,11 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, dexParams *compileDexParams, android.PathForSource(ctx, "build/make/core/proguard.flags"), } + if ctx.Config().UseR8GlobalCheckNotNullFlags() { + flagFiles = append(flagFiles, android.PathForSource(ctx, + "build/make/core/proguard/checknotnull.flags")) + } + flagFiles = append(flagFiles, d.extraProguardFlagsFiles...) // TODO(ccross): static android library proguard files @@ -583,7 +588,6 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam var description string var artProfileOutputPath *android.OutputPath var implicitOutputs android.WritablePaths - var flags []string var deps android.Paths args := map[string]string{ "zipFlags": zipFlags, @@ -610,18 +614,13 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam description = "r8" debugMode := android.InList("--debug", commonFlags) r8Flags, r8Deps, r8ArtProfileOutputPath := d.r8Flags(ctx, dexParams, debugMode) - flags = append(flags, r8Flags...) deps = append(deps, r8Deps...) args["r8Flags"] = strings.Join(append(commonFlags, r8Flags...), " ") if r8ArtProfileOutputPath != nil { artProfileOutputPath = r8ArtProfileOutputPath - implicitOutputs = append( - implicitOutputs, - artProfileOutputPath, - ) // Add the implicit r8 Art profile output to args so that r8RE knows // about this implicit output - args["outR8ArtProfile"] = artProfileOutputPath.String() + args["outR8ArtProfile"] = r8ArtProfileOutputPath.String() } args["outDict"] = proguardDictionary.String() args["outConfig"] = proguardConfiguration.String() @@ -642,16 +641,11 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam if useD8 { description = "d8" d8Flags, d8Deps, d8ArtProfileOutputPath := d.d8Flags(ctx, dexParams) - flags = append(flags, d8Flags...) deps = append(deps, d8Deps...) deps = append(deps, commonDeps...) args["d8Flags"] = strings.Join(append(commonFlags, d8Flags...), " ") if d8ArtProfileOutputPath != nil { artProfileOutputPath = d8ArtProfileOutputPath - implicitOutputs = append( - implicitOutputs, - artProfileOutputPath, - ) } // If we are generating both d8 and r8, only use RBE when both are enabled. switch { @@ -667,6 +661,12 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam rule = d8 } } + if artProfileOutputPath != nil { + implicitOutputs = append( + implicitOutputs, + artProfileOutputPath, + ) + } ctx.Build(pctx, android.BuildParams{ Rule: rule, Description: description, @@ -697,3 +697,13 @@ func (d *dexer) compileDex(ctx android.ModuleContext, dexParams *compileDexParam return javalibJar, artProfileOutputPath } + +type ProguardInfo struct { + ModuleName string + Class string + ProguardDictionary android.Path + ProguardUsageZip android.Path + ClassesJar android.Path +} + +var ProguardProvider = blueprint.NewProvider[ProguardInfo]() diff --git a/java/dexpreopt.go b/java/dexpreopt.go index 5755dec23..b21cfc968 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -565,6 +565,10 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa if !isApexSystemServerJar { d.builtInstalled = dexpreoptRule.Installs().String() } + + if isSystemServerJar { + checkSystemServerOrder(ctx, libName) + } } func getModuleInstallPathInfo(ctx android.ModuleContext, fullInstallPath string) (android.InstallPath, string, string) { @@ -631,3 +635,30 @@ func (d *dexpreopter) GetRewrittenProfile() android.Path { func (d *dexpreopter) SetRewrittenProfile(p android.Path) { d.rewrittenProfile = p } + +// Check the order of jars on the system server classpath and give a warning/error if a jar precedes +// one of its dependencies. This is not an error, but a missed optimization, as dexpreopt won't +// have the dependency jar in the class loader context, and it won't be able to resolve any +// references to its classes and methods. +func checkSystemServerOrder(ctx android.ModuleContext, libName string) { + config := dexpreopt.GetGlobalConfig(ctx) + jars := config.AllSystemServerClasspathJars(ctx) + jarIndex := config.AllSystemServerJars(ctx).IndexOfJar(libName) + ctx.WalkDeps(func(dep android.Module, parent android.Module) bool { + tag := ctx.OtherModuleDependencyTag(dep) + // Ideally this should only be walking relevant dependencies, but to maintain existing behavior + // for now just exclude any known irrelevant dependencies that would lead to incorrect errors. + if _, ok := tag.(bootclasspathDependencyTag); ok { + return false + } + depIndex := jars.IndexOfJar(dep.Name()) + if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars { + jar := jars.Jar(jarIndex) + dep := jars.Jar(depIndex) + ctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+ + " '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+ + " references from '%s' to '%s'.\n", jar, dep, jar, dep) + } + return true + }) +} diff --git a/java/java.go b/java/java.go index b9109ee94..b18c56130 100644 --- a/java/java.go +++ b/java/java.go @@ -1172,6 +1172,16 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { buildComplianceMetadata(ctx) j.createApiXmlFile(ctx) + + if j.dexer.proguardDictionary.Valid() { + android.SetProvider(ctx, ProguardProvider, ProguardInfo{ + ModuleName: ctx.ModuleName(), + Class: "JAVA_LIBRARIES", + ProguardDictionary: j.dexer.proguardDictionary.Path(), + ProguardUsageZip: j.dexer.proguardUsageZip.Path(), + ClassesJar: j.implementationAndResourcesJar, + }) + } } func (j *Library) javaLibraryModuleInfoJSON(ctx android.ModuleContext) *android.ModuleInfoJSON { @@ -1539,6 +1549,11 @@ type testProperties struct { // host test. Device_first_prefer32_data []string `android:"path_device_first_prefer32"` + // Same as data, but will add dependencies on modules using the host's os variation and + // the common arch variation. Useful for a device test that wants to depend on a host + // module, for example to include a custom Tradefed test runner. + Host_common_data []string `android:"path_host_common"` + // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. @@ -1837,6 +1852,7 @@ func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_common_data)...) j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_data)...) j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Device_first_prefer32_data)...) + j.data = append(j.data, android.PathsForModuleSrc(ctx, j.testProperties.Host_common_data)...) j.extraTestConfigs = android.PathsForModuleSrc(ctx, j.testProperties.Test_options.Extra_test_configs) diff --git a/java/java_test.go b/java/java_test.go index 636a0c891..a6290a628 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -585,6 +585,29 @@ func TestTest(t *testing.T) { } } +func TestHostCommonData(t *testing.T) { + t.Parallel() + ctx, _ := testJava(t, ` + java_library_host { + name: "host", + srcs: ["a.java"], + } + + java_test { + name: "foo", + srcs: ["a.java"], + host_common_data: [":host"], + } + `) + + foo := ctx.ModuleForTests(t, "foo", "android_common").Module().(*Test) + host := ctx.ModuleForTests(t, "host", ctx.Config().BuildOSCommonTarget.String()).Module().(*Library) + + if g, w := foo.data.RelativeToTop().Strings(), []string{host.outputFile.RelativeToTop().String()}; !slices.Equal(g, w) { + t.Errorf("expected test data %q, got %q\n", w, g) + } +} + func TestHostBinaryNoJavaDebugInfoOverride(t *testing.T) { t.Parallel() bp := ` diff --git a/java/jdeps.go b/java/jdeps.go index 927c1694d..07f8c4378 100644 --- a/java/jdeps.go +++ b/java/jdeps.go @@ -99,7 +99,7 @@ func (j *jdepsGeneratorSingleton) GenerateBuildActions(ctx android.SingletonCont Rule: android.Touch, Output: jfpath, }) - ctx.DistForGoal("general-tests", j.outputPath) + ctx.DistForGoals([]string{"general-tests", "dist_files"}, j.outputPath) } func createJsonFile(moduleInfos map[string]android.IdeInfo, jfpath android.WritablePath) error { diff --git a/java/robolectric.go b/java/robolectric.go index 5dcc7dd81..be369f780 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -168,6 +168,7 @@ func (r *robolectricTest) GenerateAndroidBuildActions(ctx android.ModuleContext) r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_common_data)...) r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_data)...) r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Device_first_prefer32_data)...) + r.data = append(r.data, android.PathsForModuleSrc(ctx, r.testProperties.Host_common_data)...) var ok bool var instrumentedApp *JavaInfo diff --git a/rust/test.go b/rust/test.go index 5c183bc67..9833ffdb6 100644 --- a/rust/test.go +++ b/rust/test.go @@ -46,9 +46,16 @@ type TestProperties struct { // the test Data []string `android:"path,arch_variant"` - // Same as data, but will add dependencies on the device's + // Same as data, but adds dependencies on modules using the device's os variant, and common + // architecture's variant. Can be useful to add device-built apps to the data of a host + // test. Device_common_data []string `android:"path_device_common"` + // Same as data, but will add dependencies on modules using the host's os variation and + // the common arch variation. Useful for a device test that wants to depend on a host + // module, for example to include a custom Tradefed test runner. + Host_common_data []string `android:"path_host_common"` + // list of shared library modules that should be installed alongside the test Data_libs []string `android:"arch_variant"` @@ -147,6 +154,7 @@ func (test *testDecorator) install(ctx ModuleContext) { dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Device_common_data)...) + dataSrcPaths = append(dataSrcPaths, android.PathsForModuleSrc(ctx, test.Properties.Host_common_data)...) ctx.VisitDirectDepsProxyWithTag(dataLibDepTag, func(dep android.ModuleProxy) { depName := ctx.OtherModuleName(dep) diff --git a/sh/sh_binary.go b/sh/sh_binary.go index c0c6ff2ae..f8d1ce523 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -138,6 +138,11 @@ type TestProperties struct { // host test. Device_first_data []string `android:"path_device_first"` + // Same as data, but will add dependencies on modules using the host's os variation and + // the common arch variation. Useful for a device test that wants to depend on a host + // module, for example to include a custom Tradefed test runner. + Host_common_data []string `android:"path_host_common"` + // Add RootTargetPreparer to auto generated test config. This guarantees the test to run // with root permission. Require_root *bool @@ -436,6 +441,7 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data) expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_common_data)...) expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Device_first_data)...) + expandedData = append(expandedData, android.PathsForModuleSrc(ctx, s.testProperties.Host_common_data)...) // Emulate the data property for java_data dependencies. for _, javaData := range ctx.GetDirectDepsProxyWithTag(shTestJavaDataTag) { expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...) diff --git a/zip/cmd/main.go b/zip/cmd/main.go index 831f6d421..37537ab8b 100644 --- a/zip/cmd/main.go +++ b/zip/cmd/main.go @@ -164,7 +164,6 @@ func main() { directories := flags.Bool("d", false, "include directories in zip") compLevel := flags.Int("L", 5, "deflate compression level (0-9)") emulateJar := flags.Bool("jar", false, "modify the resultant .zip to emulate the output of 'jar'") - sortEntries := flags.Bool("sort_entries", false, "sort the zip entries") writeIfChanged := flags.Bool("write_if_changed", false, "only update resultant .zip if it has changed") ignoreMissingFiles := flags.Bool("ignore_missing_files", false, "continue if a requested file does not exist") symlinks := flags.Bool("symlinks", true, "store symbolic links in zip instead of following them") @@ -229,7 +228,6 @@ func main() { FileArgs: fileArgsBuilder.FileArgs(), OutputFilePath: *out, EmulateJar: *emulateJar, - SortEntries: *sortEntries, SrcJar: *srcJar, AddDirectoryEntriesToZip: *directories, CompressionLevel: *compLevel, diff --git a/zip/zip.go b/zip/zip.go index e4e9585d5..22b770474 100644 --- a/zip/zip.go +++ b/zip/zip.go @@ -272,7 +272,6 @@ type ZipArgs struct { FileArgs []FileArg OutputFilePath string EmulateJar bool - SortEntries bool SrcJar bool AddDirectoryEntriesToZip bool CompressionLevel int @@ -395,7 +394,7 @@ func zipTo(args ZipArgs, w io.Writer) error { } } - return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SortEntries, args.SrcJar, args.NumParallelJobs) + return z.write(w, pathMappings, args.ManifestSourcePath, args.EmulateJar, args.SrcJar, args.NumParallelJobs) } // Zip creates an output zip archive from given sources. @@ -476,6 +475,42 @@ func fillPathPairs(fa FileArg, src string, pathMappings *[]pathMapping, return nil } +func (z *ZipWriter) moveJavaFileBasedOnPackage(mapping *pathMapping) error { + src := mapping.src + var s os.FileInfo + var err error + if z.followSymlinks { + s, err = z.fs.Stat(src) + } else { + s, err = z.fs.Lstat(src) + } + if err != nil { + if os.IsNotExist(err) && z.ignoreMissingFiles { + return nil + } + return err + } + if !s.Mode().IsRegular() { + return nil + } + r, err := z.fs.Open(src) + if err != nil { + return err + } + // rewrite the destination using the package path if it can be determined + pkg, err := jar.JavaPackage(r, src) + err2 := r.Close() + if err2 != nil { + return err2 + } + if err != nil { + // ignore errors for now, leaving the file at in its original location in the zip + } else { + mapping.dest = filepath.Join(filepath.Join(strings.Split(pkg, ".")...), filepath.Base(src)) + } + return nil +} + func jarSort(mappings []pathMapping) { sort.SliceStable(mappings, func(i int, j int) bool { return jar.EntryNamesLess(mappings[i].dest, mappings[j].dest) @@ -483,7 +518,7 @@ func jarSort(mappings []pathMapping) { } func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest string, - emulateJar, sortEntries, srcJar bool, + emulateJar, srcJar bool, parallelJobs int) error { z.errors = make(chan error) @@ -513,16 +548,38 @@ func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest stri return errors.New("must specify --jar when specifying a manifest via -m") } - if emulateJar && sortEntries { - return errors.New("Cannot specify both --jar and --sort_entries (--jar implies sorting with a different algorithm)") + // move java source files to the correct folder based on the package statement inside of them. + // This is done before the entry sorting so that they're still in the right order. + if srcJar { + var javaMoveErrors []error + var javaMoveErrorsLock sync.Mutex + var wg sync.WaitGroup + for i := range pathMappings { + if filepath.Ext(pathMappings[i].src) == ".java" { + wg.Add(1) + go func() { + err := z.moveJavaFileBasedOnPackage(&pathMappings[i]) + if err != nil { + javaMoveErrorsLock.Lock() + javaMoveErrors = append(javaMoveErrors, err) + javaMoveErrorsLock.Unlock() + } + wg.Done() + }() + } + } + wg.Wait() + if len(javaMoveErrors) > 0 { + return errors.Join(javaMoveErrors...) + } } + if emulateJar { // manifest may be empty, in which case addManifest will fill in a default pathMappings = append(pathMappings, pathMapping{jar.ManifestFile, manifest, zip.Deflate}) jarSort(pathMappings) - } - if sortEntries { + } else { sort.SliceStable(pathMappings, func(i int, j int) bool { return pathMappings[i].dest < pathMappings[j].dest }) @@ -536,7 +593,7 @@ func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest stri if emulateJar && ele.dest == jar.ManifestFile { err = z.addManifest(ele.dest, ele.src, ele.zipMethod) } else { - err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar, srcJar) + err = z.addFile(ele.dest, ele.src, ele.zipMethod, emulateJar) } if err != nil { z.errors <- err @@ -635,7 +692,7 @@ func (z *ZipWriter) write(f io.Writer, pathMappings []pathMapping, manifest stri } // imports (possibly with compression) <src> into the zip at sub-path <dest> -func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar, srcJar bool) error { +func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar bool) error { var fileSize int64 var executable bool @@ -709,21 +766,6 @@ func (z *ZipWriter) addFile(dest, src string, method uint16, emulateJar, srcJar return err } - if srcJar && filepath.Ext(src) == ".java" { - // rewrite the destination using the package path if it can be determined - pkg, err := jar.JavaPackage(r, src) - if err != nil { - // ignore errors for now, leaving the file at in its original location in the zip - } else { - dest = filepath.Join(filepath.Join(strings.Split(pkg, ".")...), filepath.Base(src)) - } - - _, err = r.Seek(0, io.SeekStart) - if err != nil { - return err - } - } - fileSize = s.Size() executable = s.Mode()&0100 != 0 diff --git a/zip/zip_test.go b/zip/zip_test.go index c64c3f499..8f100d8dc 100644 --- a/zip/zip_test.go +++ b/zip/zip_test.go @@ -159,10 +159,10 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ + fh("[", fileEmpty, zip.Store), fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), - fh("[", fileEmpty, zip.Store), }, }, { @@ -261,10 +261,10 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ + fh("[", fileEmpty, zip.Store), fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), - fh("[", fileEmpty, zip.Store), }, }, { @@ -274,10 +274,10 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ + fh("[", fileEmpty, zip.Store), fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), - fh("[", fileEmpty, zip.Store), }, }, { @@ -287,11 +287,11 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ + fh("@", fileC, zip.Deflate), + fh("[", fileEmpty, zip.Store), fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), - fh("@", fileC, zip.Deflate), fh("foo'bar", fileC, zip.Deflate), - fh("[", fileEmpty, zip.Store), }, }, { @@ -463,8 +463,8 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ - fh("foo", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), + fh("foo", fileA, zip.Deflate), }, }, { @@ -477,8 +477,8 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ - fh("prefix/foo", fileA, zip.Deflate), fh("prefix/a/a/b", fileB, zip.Deflate), + fh("prefix/foo", fileA, zip.Deflate), }, }, { @@ -490,8 +490,8 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ - fh("foo", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), + fh("foo", fileA, zip.Deflate), }, }, { @@ -504,8 +504,8 @@ func TestZip(t *testing.T) { compressionLevel: 9, files: []zip.FileHeader{ - fh("foo/bar", fileA, zip.Deflate), fh("b", fileB, zip.Deflate), + fh("foo/bar", fileA, zip.Deflate), }, }, @@ -688,8 +688,8 @@ func TestSrcJar(t *testing.T) { want := []string{ "foo/", - "foo/wrong_package.java", "foo/correct_package.java", + "foo/wrong_package.java", "no_package.java", "src2/", "src2/parse_error.java", |