diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-11-04 00:16:27 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-11-04 00:16:27 +0000 |
commit | eec57ded933d438ad6485f24a7345862691e1927 (patch) | |
tree | 372d632c5767e26a5a4691d2ddd2bf21555ccd2f | |
parent | 26646955a34e62aabf88aad0736cc3837f898581 (diff) | |
parent | 58ffdf8b88a7a12995f4b287b3b4b4a5f063f582 (diff) | |
download | soong-android13-mainline-ipsec-release.tar.gz |
Snap for 9254005 from 58ffdf8b88a7a12995f4b287b3b4b4a5f063f582 to mainline-ipsec-releaseaml_ips_331910010aml_ips_331312000aml_ips_331310000android13-mainline-ipsec-release
Change-Id: I73478c26b454a5192c79db447c4dd9a8c2fbc978
120 files changed, 3386 insertions, 1110 deletions
diff --git a/android/androidmk.go b/android/androidmk.go index 1a9cabd6b..69df3582d 100644 --- a/android/androidmk.go +++ b/android/androidmk.go @@ -366,7 +366,9 @@ func (a *AndroidMkEntries) getDistContributions(mod blueprint.Module) *distContr // Collate the contributions this module makes to the dist. distContributions := &distContributions{} - distContributions.licenseMetadataFile = amod.licenseMetadataFile + if !exemptFromRequiredApplicableLicensesProperty(mod.(Module)) { + distContributions.licenseMetadataFile = amod.licenseMetadataFile + } // Iterate over this module's dist structs, merged from the dist and dists properties. for _, dist := range amod.Dists() { @@ -458,10 +460,12 @@ func generateDistContributionsForMake(distContributions *distContributions) []st ret = append(ret, fmt.Sprintf(".PHONY: %s\n", d.goals)) // Create dist-for-goals calls for each of the copy instructions. for _, c := range d.copies { - ret = append( - ret, - fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n", - c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String())) + if distContributions.licenseMetadataFile != nil { + ret = append( + ret, + fmt.Sprintf("$(if $(strip $(ALL_TARGETS.%s.META_LIC)),,$(eval ALL_TARGETS.%s.META_LIC := %s))\n", + c.from.String(), c.from.String(), distContributions.licenseMetadataFile.String())) + } ret = append( ret, fmt.Sprintf("$(call dist-for-goals,%s,%s:%s)\n", d.goals, c.from.String(), c.dest)) diff --git a/android/apex.go b/android/apex.go index 98b122eae..883bf14b6 100644 --- a/android/apex.go +++ b/android/apex.go @@ -456,7 +456,9 @@ func CheckAvailableForApex(what string, apex_available []string) bool { (what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) || (what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) || // TODO b/243054261 (what == "com.android.bluetooth" && InList("com.android.btservices", apex_available)) || // TODO b/243054261 - (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available)) + (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available)) || + (what == "com.google.mainline.primary.libs") || // TODO b/248601389 + (what == "com.google.mainline.go.primary.libs") // TODO b/248601389 } // Implements ApexModule @@ -712,8 +714,8 @@ type ApexContents struct { // NewApexContents creates and initializes an ApexContents that is suitable // for use with an apex module. -// * contents is a map from a module name to information about its membership within -// the apex. +// - contents is a map from a module name to information about its membership within +// the apex. func NewApexContents(contents map[string]ApexMembership) *ApexContents { return &ApexContents{ contents: contents, diff --git a/android/arch.go b/android/arch.go index cbf77c758..655b00832 100644 --- a/android/arch.go +++ b/android/arch.go @@ -146,10 +146,11 @@ const COMMON_VARIANT = "common" var ( archTypeList []ArchType - Arm = newArch("arm", "lib32") - Arm64 = newArch("arm64", "lib64") - X86 = newArch("x86", "lib32") - X86_64 = newArch("x86_64", "lib64") + Arm = newArch("arm", "lib32") + Arm64 = newArch("arm64", "lib64") + Riscv64 = newArch("riscv64", "lib64") + X86 = newArch("x86", "lib32") + X86_64 = newArch("x86_64", "lib64") Common = ArchType{ Name: COMMON_VARIANT, @@ -317,7 +318,7 @@ var ( Windows = newOsType("windows", Host, true, X86, X86_64) // Android is the OS for target devices that run all of Android, including the Linux kernel // and the Bionic libc runtime. - Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64) + Android = newOsType("android", Device, false, Arm, Arm64, Riscv64, X86, X86_64) // CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which // has dependencies on all the OS variants. @@ -572,26 +573,29 @@ var DarwinUniversalVariantTag = archDepTag{name: "darwin universal binary"} // archMutator splits a module into a variant for each Target requested by the module. Target selection // for a module is in three levels, OsClass, multilib, and then Target. // OsClass selection is determined by: -// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects -// whether the module type can compile for host, device or both. -// - The host_supported and device_supported properties on the module. +// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects +// whether the module type can compile for host, device or both. +// - The host_supported and device_supported properties on the module. +// // If host is supported for the module, the Host and HostCross OsClasses are selected. If device is supported // for the module, the Device OsClass is selected. // Within each selected OsClass, the multilib selection is determined by: -// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or -// target.host.compile_multilib). -// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set. +// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or +// target.host.compile_multilib). +// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set. +// // Valid multilib values include: -// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm). -// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64, -// but may be arm for a 32-bit only build. -// "32": compile for only a single 32-bit Target supported by the OsClass. -// "64": compile for only a single 64-bit Target supported by the OsClass. -// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java). -// "common_first": compile a for a Target that will work on all Targets supported by the OsClass -// (same as "common"), plus a second Target for the preferred Target supported by the OsClass -// (same as "first"). This is used for java_binary that produces a common .jar and a wrapper -// executable script. +// +// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm). +// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64, +// but may be arm for a 32-bit only build. +// "32": compile for only a single 32-bit Target supported by the OsClass. +// "64": compile for only a single 64-bit Target supported by the OsClass. +// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java). +// "common_first": compile a for a Target that will work on all Targets supported by the OsClass +// (same as "common"), plus a second Target for the preferred Target supported by the OsClass +// (same as "first"). This is used for java_binary that produces a common .jar and a wrapper +// executable script. // // Once the list of Targets is determined, the module is split into a variant for each Target. // @@ -1261,11 +1265,13 @@ func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) { // Returns the struct containing the properties specific to the given // architecture type. These look like this in Blueprint files: -// arch: { -// arm64: { -// key: value, -// }, -// }, +// +// arch: { +// arm64: { +// key: value, +// }, +// }, +// // This struct will also contain sub-structs containing to the architecture/CPU // variants and features that themselves contain properties specific to those. func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { @@ -1277,11 +1283,12 @@ func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archT // Returns the struct containing the properties specific to a given multilib // value. These look like this in the Blueprint file: -// multilib: { -// lib32: { -// key: value, -// }, -// }, +// +// multilib: { +// lib32: { +// key: value, +// }, +// }, func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) { archPropValues := reflect.ValueOf(archProperties).Elem() multilibProp := archPropValues.FieldByName("Multilib").Elem() @@ -2054,9 +2061,10 @@ type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVa // arch-variant properties correspond to the values of the properties of the 'propertySet' struct // that are specific to that axis/configuration. Each axis is independent, containing // non-overlapping configs that correspond to the various "arch-variant" support, at this time: -// arches (including multilib) -// oses -// arch+os combinations +// +// arches (including multilib) +// oses +// arch+os combinations // // For example, passing a struct { Foo bool, Bar string } will return an interface{} that can be // type asserted back into the same struct, containing the config-specific property value specified @@ -2209,17 +2217,21 @@ func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySe // Returns a struct matching the propertySet interface, containing properties specific to the targetName // For example, given these arguments: -// propertySet = BaseCompilerProperties -// targetName = "android_arm" +// +// propertySet = BaseCompilerProperties +// targetName = "android_arm" +// // And given this Android.bp fragment: -// target: -// android_arm: { -// srcs: ["foo.c"], -// } -// android_arm64: { -// srcs: ["bar.c"], -// } -// } +// +// target: +// android_arm: { +// srcs: ["foo.c"], +// } +// android_arm64: { +// srcs: ["bar.c"], +// } +// } +// // This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"] func getTargetStructs(ctx ArchVariantContext, archProperties []interface{}, targetName string) []reflect.Value { var propertyStructs []reflect.Value diff --git a/android/arch_test.go b/android/arch_test.go index dd0b11515..8b328b6ac 100644 --- a/android/arch_test.go +++ b/android/arch_test.go @@ -495,6 +495,7 @@ func TestArchProperties(t *testing.T) { arm64: { a: ["arm64"], }, + riscv64: { a: ["riscv64"] }, x86: { a: ["x86"] }, x86_64: { a: ["x86_64"] }, }, diff --git a/android/bazel_paths.go b/android/bazel_paths.go index fa10f62b4..bacb4f642 100644 --- a/android/bazel_paths.go +++ b/android/bazel_paths.go @@ -221,9 +221,13 @@ func directoryHasBlueprint(fs pathtools.FileSystem, prefix string, components [] // Transform a path (if necessary) to acknowledge package boundaries // // e.g. something like -// async_safe/include/async_safe/CHECK.h +// +// async_safe/include/async_safe/CHECK.h +// // might become -// //bionic/libc/async_safe:include/async_safe/CHECK.h +// +// //bionic/libc/async_safe:include/async_safe/CHECK.h +// // if the "async_safe" directory is actually a package and not just a directory. // // In particular, paths that extend into packages are transformed into absolute labels beginning with //. @@ -303,20 +307,21 @@ func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []ba // directory and Bazel target labels, excluding those included in the excludes argument (which // should already be expanded to resolve references to Soong-modules). Valid elements of paths // include: -// * filepath, relative to local module directory, resolves as a filepath relative to the local -// source directory -// * glob, relative to the local module directory, resolves as filepath(s), relative to the local -// module directory. Because Soong does not have a concept of crossing package boundaries, the -// glob as computed by Soong may contain paths that cross package-boundaries that would be -// unknowingly omitted if the glob were handled by Bazel. To allow identification and detect -// (within Bazel) use of paths that cross package boundaries, we expand globs within Soong rather -// than converting Soong glob syntax to Bazel glob syntax. **Invalid for excludes.** -// * other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer -// or OutputFileProducer. These resolve as a Bazel label for a target. If the Bazel target is in -// the local module directory, it will be returned relative to the current package (e.g. -// ":<target>"). Otherwise, it will be returned as an absolute Bazel label (e.g. -// "//path/to/dir:<target>"). If the reference to another module cannot be resolved,the function -// will panic. +// - filepath, relative to local module directory, resolves as a filepath relative to the local +// source directory +// - glob, relative to the local module directory, resolves as filepath(s), relative to the local +// module directory. Because Soong does not have a concept of crossing package boundaries, the +// glob as computed by Soong may contain paths that cross package-boundaries that would be +// unknowingly omitted if the glob were handled by Bazel. To allow identification and detect +// (within Bazel) use of paths that cross package boundaries, we expand globs within Soong rather +// than converting Soong glob syntax to Bazel glob syntax. **Invalid for excludes.** +// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer +// or OutputFileProducer. These resolve as a Bazel label for a target. If the Bazel target is in +// the local module directory, it will be returned relative to the current package (e.g. +// ":<target>"). Otherwise, it will be returned as an absolute Bazel label (e.g. +// "//path/to/dir:<target>"). If the reference to another module cannot be resolved,the function +// will panic. +// // Properties passed as the paths or excludes argument must have been annotated with struct tag // `android:"path"` so that dependencies on other modules will have already been handled by the // path_deps mutator. diff --git a/android/bazel_test.go b/android/bazel_test.go index 482df2abd..87bd18e0a 100644 --- a/android/bazel_test.go +++ b/android/bazel_test.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/android/config.go b/android/config.go index ba95c5a20..b30a52480 100644 --- a/android/config.go +++ b/android/config.go @@ -93,6 +93,11 @@ func (c Config) PrimaryBuilderInvocations() []bootstrap.PrimaryBuilderInvocation return []bootstrap.PrimaryBuilderInvocation{} } +// RunningInsideUnitTest returns true if this code is being run as part of a Soong unit test. +func (c Config) RunningInsideUnitTest() bool { + return c.config.TestProductVariables != nil +} + // A DeviceConfig object represents the configuration for a particular device // being built. For now there will only be one of these, but in the future there // may be multiple devices being built. @@ -403,6 +408,9 @@ func modifyTestConfigToSupportArchMutator(testConfig Config) { }, } + // Make the CommonOS OsType available for all products. + config.Targets[CommonOS] = []Target{commonTargetMap[CommonOS.Name]} + if runtime.GOOS == "darwin" { config.Targets[config.BuildOS] = config.Targets[config.BuildOS][:1] } @@ -749,6 +757,10 @@ func (c *config) PlatformSdkVersion() ApiLevel { return uncheckedFinalApiLevel(*c.productVariables.Platform_sdk_version) } +func (c *config) PlatformSdkFinal() bool { + return Bool(c.productVariables.Platform_sdk_final) +} + func (c *config) PlatformSdkCodename() string { return String(c.productVariables.Platform_sdk_codename) } diff --git a/android/config_bp2build.go b/android/config_bp2build.go index 748be62cc..d6b2bcf97 100644 --- a/android/config_bp2build.go +++ b/android/config_bp2build.go @@ -240,10 +240,12 @@ func (m ExportedStringListDictVariables) asBazel(_ Config, _ ExportedStringVaria // ExportedVariableReferenceDictVariables is a mapping from variable names to a // dictionary which references previously defined variables. This is used to // create a Starlark output such as: -// string_var1 = "string1 -// var_ref_dict_var1 = { -// "key1": string_var1 -// } +// +// string_var1 = "string1 +// var_ref_dict_var1 = { +// "key1": string_var1 +// } +// // This type of variable collection must be expanded last so that it recognizes // previously defined variables. type ExportedVariableReferenceDictVariables map[string]map[string]string diff --git a/android/defaults.go b/android/defaults.go index 54f44bcec..03b2efbac 100644 --- a/android/defaults.go +++ b/android/defaults.go @@ -151,12 +151,12 @@ type DefaultsModuleBase struct { // retrieve the values it is necessary to iterate over properties(). E.g. to get // the commonProperties instance that have the real values: // -// d := myModule.(Defaults) -// for _, props := range d.properties() { -// if cp, ok := props.(*commonProperties); ok { -// ... access property values in cp ... -// } -// } +// d := myModule.(Defaults) +// for _, props := range d.properties() { +// if cp, ok := props.(*commonProperties); ok { +// ... access property values in cp ... +// } +// } // // The rationale is that the properties on a defaults module apply to the // defaultable modules using it, not to the defaults module itself. E.g. setting diff --git a/android/fixture.go b/android/fixture.go index 728f0318f..3a15ad3a5 100644 --- a/android/fixture.go +++ b/android/fixture.go @@ -420,11 +420,13 @@ type FixturePreparer interface { // instances. // // base - a list of already flattened and deduped preparers that will be applied first before -// the list of additional preparers. Any duplicates of these in the additional preparers -// will be ignored. +// +// the list of additional preparers. Any duplicates of these in the additional preparers +// will be ignored. // // preparers - a list of additional unflattened, undeduped preparers that will be applied after the -// base preparers. +// +// base preparers. // // Returns a deduped and flattened list of the preparers starting with the ones in base with any // additional ones from the preparers list added afterwards. @@ -498,10 +500,10 @@ func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer { // FixtureErrorHandler determines how to respond to errors reported by the code under test. // // Some possible responses: -// * Fail the test if any errors are reported, see FixtureExpectsNoErrors. -// * Fail the test if at least one error that matches a pattern is not reported see -// FixtureExpectsAtLeastOneErrorMatchingPattern -// * Fail the test if any unexpected errors are reported. +// - Fail the test if any errors are reported, see FixtureExpectsNoErrors. +// - Fail the test if at least one error that matches a pattern is not reported see +// FixtureExpectsAtLeastOneErrorMatchingPattern +// - Fail the test if any unexpected errors are reported. // // Although at the moment all the error handlers are implemented as simply a wrapper around a // function this is defined as an interface to allow future enhancements, e.g. provide different @@ -628,6 +630,20 @@ type TestResult struct { NinjaDeps []string } +type TestPathContext struct { + *TestResult +} + +var _ PathContext = &TestPathContext{} + +func (t *TestPathContext) Config() Config { + return t.TestResult.Config +} + +func (t *TestPathContext) AddNinjaFileDeps(deps ...string) { + panic("unimplemented") +} + func createFixture(t *testing.T, buildDir string, preparers []*simpleFixturePreparer) Fixture { config := TestConfig(buildDir, nil, "", nil) ctx := NewTestContext(config) @@ -854,10 +870,12 @@ func (r *TestResult) NormalizePathsForTesting(paths Paths) []string { // that produced this result. // // e.g. assuming that this result was created by running: -// GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t) +// +// GroupFixturePreparers(preparer1, preparer2, preparer3).RunTest(t) // // Then this method will be equivalent to running: -// GroupFixturePreparers(preparer1, preparer2, preparer3) +// +// GroupFixturePreparers(preparer1, preparer2, preparer3) // // This is intended for use by tests whose output is Android.bp files to verify that those files // are valid, e.g. tests of the snapshots produced by the sdk module type. diff --git a/android/gen_notice.go b/android/gen_notice.go index 2eb6bec88..008aac5e2 100644 --- a/android/gen_notice.go +++ b/android/gen_notice.go @@ -111,6 +111,9 @@ type genNoticeModule struct { } func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) { + if ctx.ContainsProperty("licenses") { + ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules") + } if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) { ctx.ModuleErrorf("can be html or xml but not both") } @@ -195,6 +198,16 @@ func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) { return nil, fmt.Errorf("unrecognized tag %q", tag) } +var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil) + +// Implements AndroidMkEntriesProvider +func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries { + return []AndroidMkEntries{AndroidMkEntries{ + Class: "ETC", + OutputFile: OptionalPathForPath(m.output), + }} +} + // missingReferencesRule emits an ErrorRule for missing module references. func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) { if len(m.missing) < 1 { diff --git a/android/gen_notice_test.go b/android/gen_notice_test.go index b45ce4f94..99d982bda 100644 --- a/android/gen_notice_test.go +++ b/android/gen_notice_test.go @@ -12,6 +12,19 @@ var genNoticeTests = []struct { expectedErrors []string }{ { + name: "gen_notice must not accept licenses property", + fs: map[string][]byte{ + "top/Android.bp": []byte(` + gen_notice { + name: "top_license", + licenses: ["other_license"], + }`), + }, + expectedErrors: []string{ + `not supported on "gen_notice" modules`, + }, + }, + { name: "bad gen_notice", fs: map[string][]byte{ "top/Android.bp": []byte(` diff --git a/android/makevars.go b/android/makevars.go index a74185a5c..5165a55e2 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -35,7 +35,7 @@ func androidMakeVarsProvider(ctx MakeVarsContext) { ctx.Strict("MIN_SUPPORTED_SDK_VERSION", ctx.Config().MinSupportedSdkVersion().String()) } -/////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// // BaseMakeVarsContext contains the common functions for other packages to use // to declare make variables @@ -173,13 +173,14 @@ type ModuleMakeVarsProvider interface { MakeVars(ctx MakeVarsModuleContext) } -/////////////////////////////////////////////////////////////////////////////// +// ///////////////////////////////////////////////////////////////////////////// func makeVarsSingletonFunc() Singleton { return &makeVarsSingleton{} } type makeVarsSingleton struct { + varsForTesting []makeVarsVariable installsForTesting []byte } @@ -320,7 +321,11 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { ctx.Errorf(err.Error()) } - s.installsForTesting = installsBytes + // Only save state for tests when testing. + if ctx.Config().RunningInsideUnitTest() { + s.varsForTesting = vars + s.installsForTesting = installsBytes + } } func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte { diff --git a/android/module.go b/android/module.go index 6f27f79a7..118ce5038 100644 --- a/android/module.go +++ b/android/module.go @@ -1113,7 +1113,7 @@ func InitAndroidModule(m Module) { // property structs for architecture-specific versions of generic properties tagged with // `android:"arch_variant"`. // -// InitAndroidModule should not be called if InitAndroidArchModule was called. +// InitAndroidModule should not be called if InitAndroidArchModule was called. func InitAndroidArchModule(m Module, hod HostOrDeviceSupported, defaultMultilib Multilib) { InitAndroidModule(m) diff --git a/android/paths.go b/android/paths.go index e7829b961..c3ef7548a 100644 --- a/android/paths.go +++ b/android/paths.go @@ -387,20 +387,21 @@ func ExistentPathsForSources(ctx PathContext, paths []string) Paths { } // PathsForModuleSrc returns a Paths{} containing the resolved references in paths: -// * filepath, relative to local module directory, resolves as a filepath relative to the local -// source directory -// * glob, relative to the local module directory, resolves as filepath(s), relative to the local -// source directory. -// * other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer -// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source -// filepath. +// - filepath, relative to local module directory, resolves as a filepath relative to the local +// source directory +// - glob, relative to the local module directory, resolves as filepath(s), relative to the local +// source directory. +// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer +// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source +// filepath. +// // Properties passed as the paths argument must have been annotated with struct tag // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the // path_deps mutator. // If a requested module is not found as a dependency: -// * if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having +// - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having // missing dependencies -// * otherwise, a ModuleError is thrown. +// - otherwise, a ModuleError is thrown. func PathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths { return PathsForModuleSrcExcludes(ctx, paths, nil) } @@ -414,21 +415,22 @@ type SourceInput struct { // PathsForModuleSrcExcludes returns a Paths{} containing the resolved references in paths, minus // those listed in excludes. Elements of paths and excludes are resolved as: -// * filepath, relative to local module directory, resolves as a filepath relative to the local -// source directory -// * glob, relative to the local module directory, resolves as filepath(s), relative to the local -// source directory. Not valid in excludes. -// * other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer -// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source -// filepath. +// - filepath, relative to local module directory, resolves as a filepath relative to the local +// source directory +// - glob, relative to the local module directory, resolves as filepath(s), relative to the local +// source directory. Not valid in excludes. +// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer +// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source +// filepath. +// // excluding the items (similarly resolved // Properties passed as the paths argument must have been annotated with struct tag // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the // path_deps mutator. // If a requested module is not found as a dependency: -// * if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having +// - if ctx.Config().AllowMissingDependencies() is true, this module to be marked as having // missing dependencies -// * otherwise, a ModuleError is thrown. +// - otherwise, a ModuleError is thrown. func PathsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) Paths { return PathsRelativeToModuleSourceDir(SourceInput{ Context: ctx, @@ -548,13 +550,14 @@ func GetModuleFromPathDep(ctx ModuleWithDepsPathContext, moduleName, tag string) // PathsAndMissingDepsForModuleSrcExcludes returns a Paths{} containing the resolved references in // paths, minus those listed in excludes. Elements of paths and excludes are resolved as: -// * filepath, relative to local module directory, resolves as a filepath relative to the local -// source directory -// * glob, relative to the local module directory, resolves as filepath(s), relative to the local -// source directory. Not valid in excludes. -// * other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer -// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source -// filepath. +// - filepath, relative to local module directory, resolves as a filepath relative to the local +// source directory +// - glob, relative to the local module directory, resolves as filepath(s), relative to the local +// source directory. Not valid in excludes. +// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer +// or OutputFileProducer. These resolve as a filepath to an output filepath or generated source +// filepath. +// // and a list of the module names of missing module dependencies are returned as the second return. // Properties passed as the paths argument must have been annotated with struct tag // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the diff --git a/android/prebuilt.go b/android/prebuilt.go index 584348767..e7f221b6d 100644 --- a/android/prebuilt.go +++ b/android/prebuilt.go @@ -56,7 +56,9 @@ func (t prebuiltDependencyTag) ExcludeFromApexContents() {} var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag var _ ExcludeFromApexContentsTag = PrebuiltDepTag -type PrebuiltProperties struct { +// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an +// Android.bp file. +type UserSuppliedPrebuiltProperties struct { // When prefer is set to true the prebuilt will be used instead of any source module with // a matching name. Prefer *bool `android:"arch_variant"` @@ -70,6 +72,16 @@ type PrebuiltProperties struct { // If specified then the prefer property is ignored in favor of the value of the Soong config // variable. Use_source_config_var *ConfigVarProperties +} + +// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the +// prebuilt properties. +func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) { + *u = p.properties.UserSuppliedPrebuiltProperties +} + +type PrebuiltProperties struct { + UserSuppliedPrebuiltProperties SourceExists bool `blueprint:"mutated"` UsePrebuilt bool `blueprint:"mutated"` diff --git a/android/register.go b/android/register.go index c50583322..c8715b1a1 100644 --- a/android/register.go +++ b/android/register.go @@ -257,20 +257,20 @@ type RegistrationContext interface { // Used to register build components from an init() method, e.g. // -// init() { -// RegisterBuildComponents(android.InitRegistrationContext) -// } +// init() { +// RegisterBuildComponents(android.InitRegistrationContext) +// } // -// func RegisterBuildComponents(ctx android.RegistrationContext) { -// ctx.RegisterModuleType(...) -// ... -// } +// func RegisterBuildComponents(ctx android.RegistrationContext) { +// ctx.RegisterModuleType(...) +// ... +// } // // Extracting the actual registration into a separate RegisterBuildComponents(ctx) function // allows it to be used to initialize test context, e.g. // -// ctx := android.NewTestContext(config) -// RegisterBuildComponents(ctx) +// ctx := android.NewTestContext(config) +// RegisterBuildComponents(ctx) var InitRegistrationContext RegistrationContext = &initRegistrationContext{ moduleTypes: make(map[string]ModuleFactory), singletonTypes: make(map[string]SingletonFactory), diff --git a/android/rule_builder.go b/android/rule_builder.go index 11da36cc0..155fbdf71 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -1031,7 +1031,8 @@ func (c *RuleBuilderCommand) ImplicitTools(paths Paths) *RuleBuilderCommand { // be also added to the dependencies returned by RuleBuilder.Tools. // // It is equivalent to: -// cmd.Tool(ctx.Config().HostToolPath(ctx, tool)) +// +// cmd.Tool(ctx.Config().HostToolPath(ctx, tool)) func (c *RuleBuilderCommand) BuiltTool(tool string) *RuleBuilderCommand { if c.rule.ctx.Config().UseHostMusl() { // If the host is using musl, assume that the tool was built against musl libc and include @@ -1053,7 +1054,8 @@ func (c *RuleBuilderCommand) builtToolWithoutDeps(tool string) *RuleBuilderComma // dependencies returned by RuleBuilder.Tools. // // It is equivalent to: -// cmd.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool)) +// +// cmd.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool)) func (c *RuleBuilderCommand) PrebuiltBuildTool(ctx PathContext, tool string) *RuleBuilderCommand { return c.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool)) } diff --git a/android/sdk.go b/android/sdk.go index a71f7f211..bd2f5d13f 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -74,6 +74,26 @@ type SdkAware interface { sdkAwareWithoutModule } +// minApiLevelForSdkSnapshot provides access to the min_sdk_version for MinApiLevelForSdkSnapshot +type minApiLevelForSdkSnapshot interface { + MinSdkVersion(ctx EarlyModuleContext) SdkSpec +} + +// MinApiLevelForSdkSnapshot returns the ApiLevel of the min_sdk_version of the supplied module. +// +// If the module does not provide a min_sdk_version then it defaults to 1. +func MinApiLevelForSdkSnapshot(ctx EarlyModuleContext, module Module) ApiLevel { + minApiLevel := NoneApiLevel + if m, ok := module.(minApiLevelForSdkSnapshot); ok { + minApiLevel = m.MinSdkVersion(ctx).ApiLevel + } + if minApiLevel == NoneApiLevel { + // The default min API level is 1. + minApiLevel = uncheckedFinalApiLevel(1) + } + return minApiLevel +} + // SdkRef refers to a version of an SDK type SdkRef struct { Name string @@ -430,13 +450,13 @@ func (r *sdkRegistry) uniqueOnceKey() OnceKey { // required for some members but not others. Traits can cause additional information to be output // to the sdk snapshot or replace the default information exported for a member with something else. // e.g. -// * By default cc libraries only export the default image variants to the SDK. However, for some -// members it may be necessary to export specific image variants, e.g. vendor, or recovery. -// * By default cc libraries export all the configured architecture variants except for the native -// bridge architecture variants. However, for some members it may be necessary to export the -// native bridge architecture variants as well. -// * By default cc libraries export the platform variant (i.e. sdk:). However, for some members it -// may be necessary to export the sdk variant (i.e. sdk:sdk). +// - By default cc libraries only export the default image variants to the SDK. However, for some +// members it may be necessary to export specific image variants, e.g. vendor, or recovery. +// - By default cc libraries export all the configured architecture variants except for the native +// bridge architecture variants. However, for some members it may be necessary to export the +// native bridge architecture variants as well. +// - By default cc libraries export the platform variant (i.e. sdk:). However, for some members it +// may be necessary to export the sdk variant (i.e. sdk:sdk). // // A sdk can request a module to provide no traits, one trait or a collection of traits. The exact // behavior of a trait is determined by how SdkMemberType implementations handle the traits. A trait @@ -447,17 +467,17 @@ func (r *sdkRegistry) uniqueOnceKey() OnceKey { // SdkPropertyName(). Each property contains a list of modules that are required to have that trait. // e.g. something like this: // -// sdk { -// name: "sdk", -// ... -// traits: { -// recovery_image: ["module1", "module4", "module5"], -// native_bridge: ["module1", "module2"], -// native_sdk: ["module1", "module3"], -// ... -// }, -// ... -// } +// sdk { +// name: "sdk", +// ... +// traits: { +// recovery_image: ["module1", "module4", "module5"], +// native_bridge: ["module1", "module2"], +// native_sdk: ["module1", "module3"], +// ... +// }, +// ... +// } type SdkMemberTrait interface { // SdkPropertyName returns the name of the traits property on an sdk module. SdkPropertyName() string @@ -639,20 +659,19 @@ func DependencyTagForSdkMemberType(memberType SdkMemberType, export bool) SdkMem // The basic implementation should look something like this, where ModuleType is // the name of the module type being supported. // -// type moduleTypeSdkMemberType struct { -// android.SdkMemberTypeBase -// } +// type moduleTypeSdkMemberType struct { +// android.SdkMemberTypeBase +// } // -// func init() { -// android.RegisterSdkMemberType(&moduleTypeSdkMemberType{ -// SdkMemberTypeBase: android.SdkMemberTypeBase{ -// PropertyName: "module_types", -// }, -// } -// } -// -// ...methods... +// func init() { +// android.RegisterSdkMemberType(&moduleTypeSdkMemberType{ +// SdkMemberTypeBase: android.SdkMemberTypeBase{ +// PropertyName: "module_types", +// }, +// } +// } // +// ...methods... type SdkMemberType interface { // SdkPropertyName returns the name of the member type property on an sdk module. SdkPropertyName() string @@ -716,8 +735,13 @@ type SdkMemberType interface { // have common values. Those fields are cleared and the common value added to the common // properties. // - // A field annotated with a tag of `sdk:"keep"` will be treated as if it - // was not capitalized, i.e. not optimized for common values. + // A field annotated with a tag of `sdk:"ignore"` will be treated as if it + // was not capitalized, i.e. ignored and not optimized for common values. + // + // A field annotated with a tag of `sdk:"keep"` will not be cleared even if the value is common + // across multiple structs. Common values will still be copied into the common property struct. + // So, if the same value is placed in all structs populated from variants that value would be + // copied into all common property structs and so be available in every instance. // // A field annotated with a tag of `android:"arch_variant"` will be allowed to have // values that differ by arch, fields not tagged as such must have common values across @@ -904,18 +928,18 @@ type SdkMemberPropertiesBase struct { // the locations of any of their prebuilt files in the snapshot by os type to prevent them // from colliding. See OsPrefix(). // - // This property is the same for all variants of a member and so would be optimized away - // if it was not explicitly kept. - Os_count int `sdk:"keep"` + // Ignore this property during optimization. This is needed because this property is the same for + // all variants of a member and so would be optimized away if it was not ignored. + Os_count int `sdk:"ignore"` // The os type for which these properties refer. // // Provided to allow a member to differentiate between os types in the locations of their // prebuilt files when it supports more than one os type. // - // This property is the same for all os type specific variants of a member and so would be - // optimized away if it was not explicitly kept. - Os OsType `sdk:"keep"` + // Ignore this property during optimization. This is needed because this property is the same for + // all variants of a member and so would be optimized away if it was not ignored. + Os OsType `sdk:"ignore"` // The setting to use for the compile_multilib property. Compile_multilib string `android:"arch_variant"` diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go index bd7364582..b25f24891 100644 --- a/android/soong_config_modules.go +++ b/android/soong_config_modules.go @@ -190,77 +190,78 @@ type soongConfigModuleTypeModule struct { // // Each soong_config_variable supports an additional value `conditions_default`. The properties // specified in `conditions_default` will only be used under the following conditions: -// bool variable: the variable is unspecified or not set to a true value -// value variable: the variable is unspecified -// string variable: the variable is unspecified or the variable is set to a string unused in the -// given module. For example, string variable `test` takes values: "a" and "b", -// if the module contains a property `a` and `conditions_default`, when test=b, -// the properties under `conditions_default` will be used. To specify that no -// properties should be amended for `b`, you can set `b: {},`. +// +// bool variable: the variable is unspecified or not set to a true value +// value variable: the variable is unspecified +// string variable: the variable is unspecified or the variable is set to a string unused in the +// given module. For example, string variable `test` takes values: "a" and "b", +// if the module contains a property `a` and `conditions_default`, when test=b, +// the properties under `conditions_default` will be used. To specify that no +// properties should be amended for `b`, you can set `b: {},`. // // For example, an Android.bp file could have: // -// soong_config_module_type { -// name: "acme_cc_defaults", -// module_type: "cc_defaults", -// config_namespace: "acme", -// variables: ["board"], -// bool_variables: ["feature"], -// value_variables: ["width"], -// properties: ["cflags", "srcs"], -// } +// soong_config_module_type { +// name: "acme_cc_defaults", +// module_type: "cc_defaults", +// config_namespace: "acme", +// variables: ["board"], +// bool_variables: ["feature"], +// value_variables: ["width"], +// properties: ["cflags", "srcs"], +// } // -// soong_config_string_variable { -// name: "board", -// values: ["soc_a", "soc_b"], -// } +// soong_config_string_variable { +// name: "board", +// values: ["soc_a", "soc_b"], +// } // -// acme_cc_defaults { -// name: "acme_defaults", -// cflags: ["-DGENERIC"], -// soong_config_variables: { -// board: { -// soc_a: { -// cflags: ["-DSOC_A"], -// }, -// soc_b: { -// cflags: ["-DSOC_B"], -// }, -// conditions_default: { -// cflags: ["-DSOC_DEFAULT"], -// }, -// }, -// feature: { -// cflags: ["-DFEATURE"], -// conditions_default: { -// cflags: ["-DFEATURE_DEFAULT"], -// }, -// }, -// width: { -// cflags: ["-DWIDTH=%s"], -// conditions_default: { -// cflags: ["-DWIDTH=DEFAULT"], -// }, -// }, -// }, -// } +// acme_cc_defaults { +// name: "acme_defaults", +// cflags: ["-DGENERIC"], +// soong_config_variables: { +// board: { +// soc_a: { +// cflags: ["-DSOC_A"], +// }, +// soc_b: { +// cflags: ["-DSOC_B"], +// }, +// conditions_default: { +// cflags: ["-DSOC_DEFAULT"], +// }, +// }, +// feature: { +// cflags: ["-DFEATURE"], +// conditions_default: { +// cflags: ["-DFEATURE_DEFAULT"], +// }, +// }, +// width: { +// cflags: ["-DWIDTH=%s"], +// conditions_default: { +// cflags: ["-DWIDTH=DEFAULT"], +// }, +// }, +// }, +// } // -// cc_library { -// name: "libacme_foo", -// defaults: ["acme_defaults"], -// srcs: ["*.cpp"], -// } +// cc_library { +// name: "libacme_foo", +// defaults: ["acme_defaults"], +// srcs: ["*.cpp"], +// } // // If an acme BoardConfig.mk file contained: // -// SOONG_CONFIG_NAMESPACES += acme -// SOONG_CONFIG_acme += \ -// board \ -// feature \ +// SOONG_CONFIG_NAMESPACES += acme +// SOONG_CONFIG_acme += \ +// board \ +// feature \ // -// SOONG_CONFIG_acme_board := soc_a -// SOONG_CONFIG_acme_feature := true -// SOONG_CONFIG_acme_width := 200 +// SOONG_CONFIG_acme_board := soc_a +// SOONG_CONFIG_acme_feature := true +// SOONG_CONFIG_acme_width := 200 // // Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE". func SoongConfigModuleTypeFactory() Module { diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go index 212b752d6..7d21b75bc 100644 --- a/android/soongconfig/modules.go +++ b/android/soongconfig/modules.go @@ -343,23 +343,26 @@ func (defs Bp2BuildSoongConfigDefinitions) String() string { // // For example, the acme_cc_defaults example above would // produce a reflect.Value whose type is: -// *struct { -// Soong_config_variables struct { -// Board struct { -// Soc_a interface{} -// Soc_b interface{} -// } -// } -// } +// +// *struct { +// Soong_config_variables struct { +// Board struct { +// Soc_a interface{} +// Soc_b interface{} +// } +// } +// } +// // And whose value is: -// &{ -// Soong_config_variables: { -// Board: { -// Soc_a: (*struct{ Cflags []string })(nil), -// Soc_b: (*struct{ Cflags []string })(nil), -// }, -// }, -// } +// +// &{ +// Soong_config_variables: { +// Board: { +// Soc_a: (*struct{ Cflags []string })(nil), +// Soc_b: (*struct{ Cflags []string })(nil), +// }, +// }, +// } func CreateProperties(factory blueprint.ModuleFactory, moduleType *ModuleType) reflect.Value { var fields []reflect.StructField diff --git a/android/testing.go b/android/testing.go index 85bdca475..1b36c903a 100644 --- a/android/testing.go +++ b/android/testing.go @@ -667,6 +667,46 @@ func (ctx *TestContext) InstallMakeRulesForTesting(t *testing.T) []InstallMakeRu return parseMkRules(t, ctx.config, nodes) } +// MakeVarVariable provides access to make vars that will be written by the makeVarsSingleton +type MakeVarVariable interface { + // Name is the name of the variable. + Name() string + + // Value is the value of the variable. + Value() string +} + +func (v makeVarsVariable) Name() string { + return v.name +} + +func (v makeVarsVariable) Value() string { + return v.value +} + +// PrepareForTestAccessingMakeVars sets up the test so that MakeVarsForTesting will work. +var PrepareForTestAccessingMakeVars = GroupFixturePreparers( + PrepareForTestWithAndroidMk, + PrepareForTestWithMakevars, +) + +// MakeVarsForTesting returns a filtered list of MakeVarVariable objects that represent the +// variables that will be written out. +// +// It is necessary to use PrepareForTestAccessingMakeVars in tests that want to call this function. +// Along with any other preparers needed to add the make vars. +func (ctx *TestContext) MakeVarsForTesting(filter func(variable MakeVarVariable) bool) []MakeVarVariable { + vars := ctx.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).varsForTesting + result := make([]MakeVarVariable, 0, len(vars)) + for _, v := range vars { + if filter(v) { + result = append(result, v) + } + } + + return result +} + func (ctx *TestContext) Config() Config { return ctx.config } @@ -688,17 +728,17 @@ type TestingBuildParams struct { // // The parts of this structure which are changed are: // * BuildParams -// * Args -// * All Path, Paths, WritablePath and WritablePaths fields. +// - Args +// - All Path, Paths, WritablePath and WritablePaths fields. // // * RuleParams -// * Command -// * Depfile -// * Rspfile -// * RspfileContent -// * SymlinkOutputs -// * CommandDeps -// * CommandOrderOnly +// - Command +// - Depfile +// - Rspfile +// - RspfileContent +// - SymlinkOutputs +// - CommandDeps +// - CommandOrderOnly // // See PathRelativeToTop for more details. // diff --git a/android/variable.go b/android/variable.go index 373891ae4..d6a64d81a 100644 --- a/android/variable.go +++ b/android/variable.go @@ -694,20 +694,20 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp // // If the ProductConfigProperties map contains these items, as parsed from the .bp file: // -// library_linking_strategy: { -// prefer_static: { -// static_libs: [ -// "lib_a", -// "lib_b", -// ], -// }, -// conditions_default: { -// shared_libs: [ -// "lib_a", -// "lib_b", -// ], -// }, -// }, +// library_linking_strategy: { +// prefer_static: { +// static_libs: [ +// "lib_a", +// "lib_b", +// ], +// }, +// conditions_default: { +// shared_libs: [ +// "lib_a", +// "lib_b", +// ], +// }, +// }, // // Static_libs {Library_linking_strategy ANDROID prefer_static} [lib_a lib_b] // Shared_libs {Library_linking_strategy ANDROID conditions_default} [lib_a lib_b] @@ -720,13 +720,13 @@ func ProductVariableProperties(ctx BazelConversionPathContext) ProductConfigProp // instead of putting lib_a and lib_b directly into dynamic_deps without a // select: // -// dynamic_deps = select({ -// "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [], -// "//conditions:default": [ -// "//foo/bar:lib_a", -// "//foo/bar:lib_b", -// ], -// }), +// dynamic_deps = select({ +// "//build/bazel/product_variables:android__library_linking_strategy__prefer_static": [], +// "//conditions:default": [ +// "//foo/bar:lib_a", +// "//foo/bar:lib_b", +// ], +// }), func (props *ProductConfigProperties) zeroValuesForNamespacedVariables() { // A map of product config properties to the zero values of their respective // property value. diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go index aaafdc758..2e8810fe8 100644 --- a/androidmk/androidmk/androidmk.go +++ b/androidmk/androidmk/androidmk.go @@ -421,9 +421,9 @@ func makeVariableToBlueprint(file *bpFile, val *mkparser.MakeString, // For example, if prefix is "foo" and name is "bar" with a value of "baz", then // the following variable will be generated: // -// foo { -// bar: "baz" -// } +// foo { +// bar: "baz" +// } // // If prefix is the empty string and name is "foo" with a value of "bar", the // following variable will be generated (if it is a property): diff --git a/androidmk/parser/make_strings.go b/androidmk/parser/make_strings.go index 803032649..9391117fb 100644 --- a/androidmk/parser/make_strings.go +++ b/androidmk/parser/make_strings.go @@ -38,10 +38,10 @@ import ( // For example, "$(FOO)/bar/baz" will be represented as the // following lists: // -// { -// Strings: ["", "/bar/baz"], -// Variables: ["FOO"] -// } +// { +// Strings: ["", "/bar/baz"], +// Variables: ["FOO"] +// } type MakeString struct { StringPos Pos Strings []string diff --git a/apex/apex.go b/apex/apex.go index 49e0d08d1..d5e2a3db6 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -190,6 +190,10 @@ type apexBundleProperties struct { // with the tool to sign payload contents. Custom_sign_tool *string + // Whether this is a dynamic common lib apex, if so the native shared libs will be placed + // in a special way that include the digest of the lib file under /lib(64)? + Dynamic_common_lib_apex *bool + // Canonical name of this APEX bundle. Used to determine the path to the // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the // apex mutator variations. For override_apex modules, this is the name of the @@ -218,7 +222,7 @@ type ApexNativeDependencies struct { // List of JNI libraries that are embedded inside this APEX. Jni_libs []string - // List of rust dyn libraries + // List of rust dyn libraries that are embedded inside this APEX. Rust_dyn_libs []string // List of native executables that are embedded inside this APEX. @@ -229,6 +233,41 @@ type ApexNativeDependencies struct { // List of filesystem images that are embedded inside this APEX bundle. Filesystems []string + + // List of native libraries to exclude from this APEX. + Exclude_native_shared_libs []string + + // List of JNI libraries to exclude from this APEX. + Exclude_jni_libs []string + + // List of rust dyn libraries to exclude from this APEX. + Exclude_rust_dyn_libs []string + + // List of native executables to exclude from this APEX. + Exclude_binaries []string + + // List of native tests to exclude from this APEX. + Exclude_tests []string + + // List of filesystem images to exclude from this APEX bundle. + Exclude_filesystems []string +} + +// Merge combines another ApexNativeDependencies into this one +func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) { + a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...) + a.Jni_libs = append(a.Jni_libs, b.Jni_libs...) + a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...) + a.Binaries = append(a.Binaries, b.Binaries...) + a.Tests = append(a.Tests, b.Tests...) + a.Filesystems = append(a.Filesystems, b.Filesystems...) + + a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...) + a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...) + a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...) + a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...) + a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...) + a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...) } type apexMultilibProperties struct { @@ -280,6 +319,9 @@ type apexArchBundleProperties struct { Arm64 struct { ApexNativeDependencies } + Riscv64 struct { + ApexNativeDependencies + } X86 struct { ApexNativeDependencies } @@ -664,12 +706,18 @@ func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext, nativeM // Use *FarVariation* to be able to depend on modules having conflicting variations with // this module. This is required since arch variant of an APEX bundle is 'common' but it is // 'arm' or 'arm64' for native shared libs. - ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...) - ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...) - ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...) - ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...) - ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, nativeModules.Rust_dyn_libs...) - ctx.AddFarVariationDependencies(target.Variations(), fsTag, nativeModules.Filesystems...) + ctx.AddFarVariationDependencies(binVariations, executableTag, + android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...) + ctx.AddFarVariationDependencies(binVariations, testTag, + android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...) + ctx.AddFarVariationDependencies(libVariations, jniLibTag, + android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...) + ctx.AddFarVariationDependencies(libVariations, sharedLibTag, + android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...) + ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, + android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...) + ctx.AddFarVariationDependencies(target.Variations(), fsTag, + android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...) } func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) { @@ -737,12 +785,12 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { continue } - var depsList []ApexNativeDependencies + var deps ApexNativeDependencies // Add native modules targeting both ABIs. When multilib.* is omitted for // native_shared_libs/jni_libs/tests, it implies multilib.both - depsList = append(depsList, a.properties.Multilib.Both) - depsList = append(depsList, ApexNativeDependencies{ + deps.Merge(a.properties.Multilib.Both) + deps.Merge(ApexNativeDependencies{ Native_shared_libs: a.properties.Native_shared_libs, Tests: a.properties.Tests, Jni_libs: a.properties.Jni_libs, @@ -753,8 +801,8 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { // binaries, it implies multilib.first isPrimaryAbi := i == 0 if isPrimaryAbi { - depsList = append(depsList, a.properties.Multilib.First) - depsList = append(depsList, ApexNativeDependencies{ + deps.Merge(a.properties.Multilib.First) + deps.Merge(ApexNativeDependencies{ Native_shared_libs: nil, Tests: nil, Jni_libs: nil, @@ -765,32 +813,32 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { // Add native modules targeting either 32-bit or 64-bit ABI switch target.Arch.ArchType.Multilib { case "lib32": - depsList = append(depsList, a.properties.Multilib.Lib32) - depsList = append(depsList, a.properties.Multilib.Prefer32) + deps.Merge(a.properties.Multilib.Lib32) + deps.Merge(a.properties.Multilib.Prefer32) case "lib64": - depsList = append(depsList, a.properties.Multilib.Lib64) + deps.Merge(a.properties.Multilib.Lib64) if !has32BitTarget { - depsList = append(depsList, a.properties.Multilib.Prefer32) + deps.Merge(a.properties.Multilib.Prefer32) } } // Add native modules targeting a specific arch variant switch target.Arch.ArchType { case android.Arm: - depsList = append(depsList, a.archProperties.Arch.Arm.ApexNativeDependencies) + deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies) case android.Arm64: - depsList = append(depsList, a.archProperties.Arch.Arm64.ApexNativeDependencies) + deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies) + case android.Riscv64: + deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies) case android.X86: - depsList = append(depsList, a.archProperties.Arch.X86.ApexNativeDependencies) + deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies) case android.X86_64: - depsList = append(depsList, a.archProperties.Arch.X86_64.ApexNativeDependencies) + deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies) default: panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType)) } - for _, d := range depsList { - addDependenciesForNativeModules(ctx, d, target, imageVariation) - } + addDependenciesForNativeModules(ctx, deps, target, imageVariation) ctx.AddFarVariationDependencies([]blueprint.Variation{ {Mutator: "os", Variation: target.OsVariation()}, {Mutator: "arch", Variation: target.ArchVariation()}, @@ -1454,6 +1502,11 @@ func (a *apexBundle) testOnlyShouldForceCompression() bool { return proptools.Bool(a.properties.Test_only_force_compression) } +// See the dynamic_common_lib_apex property +func (a *apexBundle) dynamic_common_lib_apex() bool { + return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false) +} + // These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its // members) can be sanitized, either forcibly, or by the global configuration. For some of the // sanitizers, extra dependencies can be forcibly added as well. @@ -2440,6 +2493,7 @@ func DefaultsFactory(props ...interface{}) android.Module { module.AddProperties( &apexBundleProperties{}, &apexTargetBundleProperties{}, + &apexArchBundleProperties{}, &overridableProperties{}, ) diff --git a/apex/apex_test.go b/apex/apex_test.go index c425e9c04..510e3501c 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4296,12 +4296,15 @@ func TestApexWithArch(t *testing.T) { name: "myapex", key: "myapex.key", updatable: false, + native_shared_libs: ["mylib.generic"], arch: { arm64: { native_shared_libs: ["mylib.arm64"], + exclude_native_shared_libs: ["mylib.generic"], }, x86_64: { native_shared_libs: ["mylib.x64"], + exclude_native_shared_libs: ["mylib.generic"], }, } } @@ -4313,6 +4316,18 @@ func TestApexWithArch(t *testing.T) { } cc_library { + name: "mylib.generic", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + // TODO: remove //apex_available:platform + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + + cc_library { name: "mylib.arm64", srcs: ["mylib.cpp"], system_shared_libs: [], @@ -4342,6 +4357,7 @@ func TestApexWithArch(t *testing.T) { // Ensure that apex variant is created for the direct dep ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000") + ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.generic"), "android_arm64_armv8-a_shared_apex10000") ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000") // Ensure that both direct and indirect deps are copied into apex @@ -8842,19 +8858,7 @@ func TestApexJavaCoverage(t *testing.T) { android.FixtureWithRootAndroidBp(bp), dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"), dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"), - android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - }), - // need to mock jacocoagent here to satisfy dependency added for - // instrumented libraries at build time - android.FixtureAddFile("jacocoagent/Android.bp", []byte(` - java_library { - name: "jacocoagent", - srcs: ["Test.java"], - system_modules: "none", - sdk_version: "none", - } - `)), + java.PrepareForTestWithJacocoInstrumentation, ).RunTest(t) // Make sure jacoco ran on both mylib and mybootclasspathlib diff --git a/apex/builder.go b/apex/builder.go index 1956b4447..6fb2bb0c4 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -39,6 +39,7 @@ func init() { pctx.Import("android/soong/cc/config") pctx.Import("android/soong/java") pctx.HostBinToolVariable("apexer", "apexer") + pctx.HostBinToolVariable("apexer_with_DCLA_preprocessing", "apexer_with_DCLA_preprocessing") // ART minimal builds (using the master-art manifest) do not have the "frameworks/base" // projects, and hence cannot build 'aapt2'. Use the SDK prebuilt instead. hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) { @@ -115,7 +116,35 @@ var ( Rspfile: "${out}.copy_commands", RspfileContent: "${copy_commands}", Description: "APEX ${image_dir} => ${out}", - }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type") + }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", + "opt_flags", "manifest") + + DCLAApexRule = pctx.StaticRule("DCLAApexRule", blueprint.RuleParams{ + Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + + `(. ${out}.copy_commands) && ` + + `APEXER_TOOL_PATH=${tool_path} ` + + `${apexer_with_DCLA_preprocessing} ` + + `--apexer ${apexer} ` + + `--canned_fs_config ${canned_fs_config} ` + + `${image_dir} ` + + `${out} ` + + `-- ` + + `--include_build_info ` + + `--force ` + + `--payload_type image ` + + `--key ${key} ` + + `--file_contexts ${file_contexts} ` + + `--manifest ${manifest} ` + + `${opt_flags} `, + CommandDeps: []string{"${apexer_with_DCLA_preprocessing}", "${apexer}", "${avbtool}", "${e2fsdroid}", + "${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", + "${sload_f2fs}", "${make_erofs}", "${soong_zip}", "${zipalign}", "${aapt2}", + "prebuilts/sdk/current/public/android.jar"}, + Rspfile: "${out}.copy_commands", + RspfileContent: "${copy_commands}", + Description: "APEX ${image_dir} => ${out}", + }, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", + "opt_flags", "manifest", "is_DCLA") zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{ Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` + @@ -659,22 +688,41 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string()) - ctx.Build(pctx, android.BuildParams{ - Rule: apexRule, - Implicits: implicitInputs, - Output: unsignedOutputFile, - Description: "apex (" + apexType.name() + ")", - Args: map[string]string{ - "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, - "image_dir": imageDir.String(), - "copy_commands": strings.Join(copyCommands, " && "), - "manifest": a.manifestPbOut.String(), - "file_contexts": fileContexts.String(), - "canned_fs_config": cannedFsConfig.String(), - "key": a.privateKeyFile.String(), - "opt_flags": strings.Join(optFlags, " "), - }, - }) + if a.dynamic_common_lib_apex() { + ctx.Build(pctx, android.BuildParams{ + Rule: DCLAApexRule, + Implicits: implicitInputs, + Output: unsignedOutputFile, + Description: "apex (" + apexType.name() + ")", + Args: map[string]string{ + "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, + "image_dir": imageDir.String(), + "copy_commands": strings.Join(copyCommands, " && "), + "manifest": a.manifestPbOut.String(), + "file_contexts": fileContexts.String(), + "canned_fs_config": cannedFsConfig.String(), + "key": a.privateKeyFile.String(), + "opt_flags": strings.Join(optFlags, " "), + }, + }) + } else { + ctx.Build(pctx, android.BuildParams{ + Rule: apexRule, + Implicits: implicitInputs, + Output: unsignedOutputFile, + Description: "apex (" + apexType.name() + ")", + Args: map[string]string{ + "tool_path": outHostBinDir + ":" + prebuiltSdkToolsBinDir, + "image_dir": imageDir.String(), + "copy_commands": strings.Join(copyCommands, " && "), + "manifest": a.manifestPbOut.String(), + "file_contexts": fileContexts.String(), + "canned_fs_config": cannedFsConfig.String(), + "key": a.privateKeyFile.String(), + "opt_flags": strings.Join(optFlags, " "), + }, + }) + } // TODO(jiyong): make the two rules below as separate functions apexProtoFile := android.PathForModuleOut(ctx, a.Name()+".pb"+suffix) diff --git a/apex/key.go b/apex/key.go index 829410ed2..6090b65d6 100644 --- a/apex/key.go +++ b/apex/key.go @@ -105,7 +105,7 @@ func (m *apexKey) GenerateAndroidBuildActions(ctx android.ModuleContext) { m.keyName = pubKeyName } -//////////////////////////////////////////////////////////////////////// +// ////////////////////////////////////////////////////////////////////// // apex_keys_text type apexKeysText struct { output android.OutputPath diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 187e0df09..609a9d297 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -364,16 +364,16 @@ func (p *prebuiltCommon) DepIsInSameApex(ctx android.BaseModuleContext, dep andr // While it may be possible to provide sufficient information to determine whether two prebuilt_apex // modules were compatible it would be a lot of work and would not provide much benefit for a couple // of reasons: -// * The number of prebuilt_apex modules that will be exporting files for the same module will be -// low as the prebuilt_apex only exports files for the direct dependencies that require it and -// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a -// few com.android.art* apex files that contain the same contents and could export files for the -// same modules but only one of them needs to do so. Contrast that with source apex modules which -// need apex specific variants for every module that contributes code to the apex, whether direct -// or indirect. -// * The build cost of a prebuilt_apex variant is generally low as at worst it will involve some -// extra copying of files. Contrast that with source apex modules that has to build each variant -// from source. +// - The number of prebuilt_apex modules that will be exporting files for the same module will be +// low as the prebuilt_apex only exports files for the direct dependencies that require it and +// very few modules are direct dependencies of multiple prebuilt_apex modules, e.g. there are a +// few com.android.art* apex files that contain the same contents and could export files for the +// same modules but only one of them needs to do so. Contrast that with source apex modules which +// need apex specific variants for every module that contributes code to the apex, whether direct +// or indirect. +// - The build cost of a prebuilt_apex variant is generally low as at worst it will involve some +// extra copying of files. Contrast that with source apex modules that has to build each variant +// from source. func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { // Collect direct dependencies into contents. @@ -500,6 +500,9 @@ type ApexFileProperties struct { Arm64 struct { Src *string `android:"path"` } + Riscv64 struct { + Src *string `android:"path"` + } X86 struct { Src *string `android:"path"` } @@ -527,6 +530,8 @@ func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, src = String(p.Arch.Arm.Src) case android.Arm64: src = String(p.Arch.Arm64.Src) + case android.Riscv64: + src = String(p.Arch.Riscv64.Src) case android.X86: src = String(p.Arch.X86.Src) case android.X86_64: @@ -703,28 +708,29 @@ var _ prebuiltApexModuleCreator = (*Prebuilt)(nil) // 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. +// 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. +// 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. +// 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 +// 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() diff --git a/bazel/configurability.go b/bazel/configurability.go index 7355ac7d3..e5c142917 100644 --- a/bazel/configurability.go +++ b/bazel/configurability.go @@ -21,10 +21,11 @@ import ( const ( // ArchType names in arch.go - archArm = "arm" - archArm64 = "arm64" - archX86 = "x86" - archX86_64 = "x86_64" + archArm = "arm" + archArm64 = "arm64" + archRiscv64 = "riscv64" + archX86 = "x86" + archX86_64 = "x86_64" // OsType names in arch.go osAndroid = "android" @@ -37,6 +38,7 @@ const ( // Targets in arch.go osArchAndroidArm = "android_arm" osArchAndroidArm64 = "android_arm64" + osArchAndroidRiscv64 = "android_riscv64" osArchAndroidX86 = "android_x86" osArchAndroidX86_64 = "android_x86_64" osArchDarwinArm64 = "darwin_arm64" @@ -75,6 +77,7 @@ var ( platformArchMap = map[string]string{ archArm: "//build/bazel/platforms/arch:arm", archArm64: "//build/bazel/platforms/arch:arm64", + archRiscv64: "//build/bazel/platforms/arch:riscv64", archX86: "//build/bazel/platforms/arch:x86", archX86_64: "//build/bazel/platforms/arch:x86_64", ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map. @@ -95,6 +98,7 @@ var ( platformOsArchMap = map[string]string{ osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm", osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64", + osArchAndroidRiscv64: "//build/bazel/platforms/os_arch:android_riscv64", osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86", osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64", osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64", @@ -116,7 +120,7 @@ var ( // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results // in a cyclic dependency. osToArchMap = map[string][]string{ - osAndroid: {archArm, archArm64, archX86, archX86_64}, + osAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64}, osLinux: {archX86, archX86_64}, osLinuxMusl: {archX86, archX86_64}, osDarwin: {archArm64, archX86_64}, diff --git a/bazel/properties.go b/bazel/properties.go index f9560319e..a3555f87d 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -1071,15 +1071,18 @@ func (sla *StringListAttribute) SortedConfigurationAxes() []ConfigurationAxis { // DeduplicateAxesFromBase ensures no duplication of items between the no-configuration value and // configuration-specific values. For example, if we would convert this StringListAttribute as: -// ["a", "b", "c"] + select({ -// "//condition:one": ["a", "d"], -// "//conditions:default": [], -// }) +// +// ["a", "b", "c"] + select({ +// "//condition:one": ["a", "d"], +// "//conditions:default": [], +// }) +// // after this function, we would convert this StringListAttribute as: -// ["a", "b", "c"] + select({ -// "//condition:one": ["d"], -// "//conditions:default": [], -// }) +// +// ["a", "b", "c"] + select({ +// "//condition:one": ["d"], +// "//conditions:default": [], +// }) func (sla *StringListAttribute) DeduplicateAxesFromBase() { base := sla.Value for axis, configToList := range sla.ConfigurableValues { diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go index 0f3ca79b5..7c83109e6 100644 --- a/bp2build/build_conversion_test.go +++ b/bp2build/build_conversion_test.go @@ -323,6 +323,7 @@ custom { x86_64: { arch_paths: ["x86_64.txt"] }, arm: { arch_paths: ["arm.txt"] }, arm64: { arch_paths: ["arm64.txt"] }, + riscv64: { arch_paths: ["riscv64.txt"] }, }, target: { linux: { arch_paths: ["linux.txt"] }, @@ -355,6 +356,10 @@ custom { "arm64.txt", "lib64.txt", ], + "//build/bazel/platforms/arch:riscv64": [ + "riscv64.txt", + "lib64.txt", + ], "//build/bazel/platforms/arch:x86": [ "x86.txt", "lib32.txt", diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index be10e866d..70c34c001 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -835,6 +835,10 @@ cc_library_static { "not-for-lib32.c", "for-lib64.c", ], + "//build/bazel/platforms/arch:riscv64": [ + "not-for-lib32.c", + "for-lib64.c", + ], "//build/bazel/platforms/arch:x86": [ "not-for-lib64.c", "for-lib32.c", @@ -866,6 +870,7 @@ func TestCcLibrarySTaticArchMultilibSrcsExcludeSrcs(t *testing.T) { "for-lib64.c": "", "not-for-arm.c": "", "not-for-arm64.c": "", + "not-for-riscv64.c": "", "not-for-x86.c": "", "not-for-x86_64.c": "", "not-for-lib32.c": "", @@ -880,6 +885,7 @@ cc_library_static { arch: { arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] }, arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] }, + riscv64: { srcs: ["for-riscv64.c"], exclude_srcs: ["not-for-riscv64.c"] }, x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] }, x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] }, }, @@ -895,6 +901,7 @@ cc_library_static { "//build/bazel/platforms/arch:arm": [ "not-for-arm64.c", "not-for-lib64.c", + "not-for-riscv64.c", "not-for-x86.c", "not-for-x86_64.c", "for-arm.c", @@ -903,15 +910,26 @@ cc_library_static { "//build/bazel/platforms/arch:arm64": [ "not-for-arm.c", "not-for-lib32.c", + "not-for-riscv64.c", "not-for-x86.c", "not-for-x86_64.c", "for-arm64.c", "for-lib64.c", ], + "//build/bazel/platforms/arch:riscv64": [ + "not-for-arm.c", + "not-for-arm64.c", + "not-for-lib32.c", + "not-for-x86.c", + "not-for-x86_64.c", + "for-riscv64.c", + "for-lib64.c", + ], "//build/bazel/platforms/arch:x86": [ "not-for-arm.c", "not-for-arm64.c", "not-for-lib64.c", + "not-for-riscv64.c", "not-for-x86_64.c", "for-x86.c", "for-lib32.c", @@ -920,6 +938,7 @@ cc_library_static { "not-for-arm.c", "not-for-arm64.c", "not-for-lib32.c", + "not-for-riscv64.c", "not-for-x86.c", "for-x86_64.c", "for-lib64.c", @@ -929,6 +948,7 @@ cc_library_static { "not-for-arm64.c", "not-for-lib32.c", "not-for-lib64.c", + "not-for-riscv64.c", "not-for-x86.c", "not-for-x86_64.c", ], diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go index 3cf896903..41dbe6a5a 100644 --- a/bp2build/cc_prebuilt_library_conversion_test.go +++ b/bp2build/cc_prebuilt_library_conversion_test.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go index 3feb1f155..b1a937840 100644 --- a/bp2build/cc_prebuilt_library_static_test.go +++ b/bp2build/cc_prebuilt_library_static_test.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go index 94b28dc50..ddaa98aa3 100644 --- a/bpfix/bpfix/bpfix.go +++ b/bpfix/bpfix/bpfix.go @@ -553,7 +553,9 @@ func indicateAttributeError(mod *parser.Module, attributeName string, format str // If a variable is LOCAL_MODULE, get its value from the 'name' attribute. // This handles the statement -// LOCAL_SRC_FILES := $(LOCAL_MODULE) +// +// LOCAL_SRC_FILES := $(LOCAL_MODULE) +// // which occurs often. func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expression { if varLocalName, ok := val.(*parser.Variable); ok { @@ -567,9 +569,9 @@ func resolveLocalModule(mod *parser.Module, val parser.Expression) parser.Expres } // etcPrebuiltModuleUpdate contains information on updating certain parts of a defined module such as: -// * changing the module type from prebuilt_etc to a different one -// * stripping the prefix of the install path based on the module type -// * appending additional boolean properties to the prebuilt module +// - changing the module type from prebuilt_etc to a different one +// - stripping the prefix of the install path based on the module type +// - appending additional boolean properties to the prebuilt module type etcPrebuiltModuleUpdate struct { // The prefix of the install path defined in local_module_path. The prefix is removed from local_module_path // before setting the 'filename' attribute. diff --git a/cc/afdo.go b/cc/afdo.go index 66e973284..fb66bbe52 100644 --- a/cc/afdo.go +++ b/cc/afdo.go @@ -66,8 +66,9 @@ func (afdo *afdo) AfdoEnabled() bool { } // Get list of profile file names, ordered by level of specialisation. For example: -// 1. libfoo_arm64.afdo -// 2. libfoo.afdo +// 1. libfoo_arm64.afdo +// 2. libfoo.afdo +// // Add more specialisation as needed. func getProfileFiles(ctx android.BaseModuleContext, moduleName string) []string { var files []string diff --git a/cc/api_level.go b/cc/api_level.go index fd145a9e2..8c2b2c2ac 100644 --- a/cc/api_level.go +++ b/cc/api_level.go @@ -28,6 +28,8 @@ func minApiForArch(ctx android.BaseModuleContext, return ctx.Config().MinSupportedSdkVersion() case android.Arm64, android.X86_64: return android.FirstLp64Version + case android.Riscv64: + return android.FutureApiLevel default: panic(fmt.Errorf("Unknown arch %q", arch)) } diff --git a/cc/builder.go b/cc/builder.go index ea06839a9..c390a93ed 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -1151,7 +1151,3 @@ func transformArchiveRepack(ctx android.ModuleContext, inputFile android.Path, }, }) } - -func mingwCmd(toolchain config.Toolchain, cmd string) string { - return filepath.Join(toolchain.GccRoot(), "bin", toolchain.GccTriple()+"-"+cmd) -} diff --git a/cc/config/Android.bp b/cc/config/Android.bp index 1a21c1361..de163d9d3 100644 --- a/cc/config/Android.bp +++ b/cc/config/Android.bp @@ -21,6 +21,7 @@ bootstrap_go_package { "arm_device.go", "arm64_device.go", + "riscv64_device.go", "x86_device.go", "x86_64_device.go", diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go index 66087e6f0..d7f96183a 100644 --- a/cc/config/arm64_device.go +++ b/cc/config/arm64_device.go @@ -74,7 +74,7 @@ var ( "-mcpu=kryo", }, "kryo385": []string{ - // Use cortex-a53 because kryo385 is not supported in GCC/clang. + // Use cortex-a53 because kryo385 is not supported in clang. "-mcpu=cortex-a53", }, "exynos-m1": []string{ @@ -86,16 +86,7 @@ var ( } ) -const ( - arm64GccVersion = "4.9" -) - func init() { - pctx.StaticVariable("arm64GccVersion", arm64GccVersion) - - pctx.SourcePathVariable("Arm64GccRoot", - "prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}") - exportedVars.ExportStringListStaticVariable("Arm64Ldflags", arm64Ldflags) exportedVars.ExportStringListStaticVariable("Arm64Lldflags", arm64Lldflags) @@ -164,24 +155,12 @@ func (t *toolchainArm64) Name() string { return "arm64" } -func (t *toolchainArm64) GccRoot() string { - return "${config.Arm64GccRoot}" -} - -func (t *toolchainArm64) GccTriple() string { - return "aarch64-linux-android" -} - -func (t *toolchainArm64) GccVersion() string { - return arm64GccVersion -} - func (t *toolchainArm64) IncludeFlags() string { return "" } func (t *toolchainArm64) ClangTriple() string { - return t.GccTriple() + return "aarch64-linux-android" } func (t *toolchainArm64) Cflags() string { diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go index d702c6145..b53a09782 100644 --- a/cc/config/arm_device.go +++ b/cc/config/arm_device.go @@ -79,7 +79,7 @@ var ( "cortex-a7": []string{ "-mcpu=cortex-a7", "-mfpu=neon-vfpv4", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -91,7 +91,7 @@ var ( "cortex-a15": []string{ "-mcpu=cortex-a15", "-mfpu=neon-vfpv4", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -100,7 +100,7 @@ var ( "cortex-a53": []string{ "-mcpu=cortex-a53", "-mfpu=neon-fp-armv8", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -109,7 +109,7 @@ var ( "cortex-a55": []string{ "-mcpu=cortex-a55", "-mfpu=neon-fp-armv8", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -118,7 +118,7 @@ var ( "cortex-a75": []string{ "-mcpu=cortex-a55", "-mfpu=neon-fp-armv8", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -127,7 +127,7 @@ var ( "cortex-a76": []string{ "-mcpu=cortex-a55", "-mfpu=neon-fp-armv8", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -136,7 +136,7 @@ var ( "krait": []string{ "-mcpu=krait", "-mfpu=neon-vfpv4", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -147,16 +147,16 @@ var ( // even though clang does. "-mcpu=cortex-a53", "-mfpu=neon-fp-armv8", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 "-D__ARM_FEATURE_LPAE=1", }, "kryo385": []string{ - // Use cortex-a53 because kryo385 is not supported in GCC/clang. + // Use cortex-a53 because kryo385 is not supported in clang. "-mcpu=cortex-a53", - // Fake an ARM compiler flag as these processors support LPAE which GCC/clang + // Fake an ARM compiler flag as these processors support LPAE which clang // don't advertise. // TODO This is a hack and we need to add it for each processor that supports LPAE until some // better solution comes around. See Bug 27340895 @@ -166,17 +166,12 @@ var ( ) const ( - name = "arm" - armGccVersion = "4.9" - gccTriple = "arm-linux-androideabi" - clangTriple = "armv7a-linux-androideabi" + name = "arm" + ndkTriple = "arm-linux-androideabi" + clangTriple = "armv7a-linux-androideabi" ) func init() { - pctx.StaticVariable("armGccVersion", armGccVersion) - - pctx.SourcePathVariable("ArmGccRoot", "prebuilts/gcc/${HostPrebuiltTag}/arm/arm-linux-androideabi-${armGccVersion}") - // Just exported. Not created as a Ninja static variable. exportedVars.ExportString("ArmClangTriple", clangTriple) @@ -255,18 +250,6 @@ func (t *toolchainArm) Name() string { return name } -func (t *toolchainArm) GccRoot() string { - return "${config.ArmGccRoot}" -} - -func (t *toolchainArm) GccTriple() string { - return gccTriple -} - -func (t *toolchainArm) GccVersion() string { - return armGccVersion -} - func (t *toolchainArm) IncludeFlags() string { return "" } @@ -278,7 +261,7 @@ func (t *toolchainArm) ClangTriple() string { func (t *toolchainArm) ndkTriple() string { // Use current NDK include path, while ClangTriple is changed. - return t.GccTriple() + return ndkTriple } func (t *toolchainArm) ToolchainCflags() string { diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go index 5e3f7c7d6..1667ad7c1 100644 --- a/cc/config/darwin_host.go +++ b/cc/config/darwin_host.go @@ -75,10 +75,6 @@ var ( ) ) -const ( - darwinGccVersion = "4.2.1" -) - func init() { pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string { return getMacTools(ctx).sdkRoot @@ -100,12 +96,6 @@ func init() { return getMacTools(ctx).toolPath }) - pctx.StaticVariable("DarwinGccVersion", darwinGccVersion) - pctx.SourcePathVariable("DarwinGccRoot", - "prebuilts/gcc/${HostPrebuiltTag}/host/i686-apple-darwin-${DarwinGccVersion}") - - pctx.StaticVariable("DarwinGccTriple", "i686-apple-darwin11") - pctx.StaticVariable("DarwinCflags", strings.Join(darwinCflags, " ")) pctx.StaticVariable("DarwinLdflags", strings.Join(darwinLdflags, " ")) pctx.StaticVariable("DarwinLldflags", strings.Join(darwinLdflags, " ")) @@ -194,30 +184,6 @@ func (t *toolchainDarwinX86) Name() string { return "x86_64" } -func (t *toolchainDarwinArm) GccRoot() string { - panic("unimplemented") -} - -func (t *toolchainDarwinArm) GccTriple() string { - panic("unimplemented") -} - -func (t *toolchainDarwinArm) GccVersion() string { - panic("unimplemented") -} - -func (t *toolchainDarwinX86) GccRoot() string { - return "${config.DarwinGccRoot}" -} - -func (t *toolchainDarwinX86) GccTriple() string { - return "${config.DarwinGccTriple}" -} - -func (t *toolchainDarwinX86) GccVersion() string { - return darwinGccVersion -} - func (t *toolchainDarwin) IncludeFlags() string { return "" } diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go new file mode 100644 index 000000000..d8918f164 --- /dev/null +++ b/cc/config/riscv64_device.go @@ -0,0 +1,140 @@ +// Copyright 2022 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 config + +import ( + "fmt" + "strings" + + "android/soong/android" +) + +var ( + riscv64Cflags = []string{ + // Help catch common 32/64-bit errors. + "-Werror=implicit-function-declaration", + } + + riscv64ArchVariantCflags = map[string][]string{} + + riscv64Ldflags = []string{ + "-Wl,--hash-style=gnu", + "-Wl,-z,separate-code", + } + + riscv64Lldflags = append(riscv64Ldflags, + "-Wl,-z,max-page-size=4096") + + riscv64Cppflags = []string{} + + riscv64CpuVariantCflags = map[string][]string{} +) + +const () + +func init() { + + exportedVars.ExportStringListStaticVariable("Riscv64Ldflags", riscv64Ldflags) + exportedVars.ExportStringListStaticVariable("Riscv64Lldflags", riscv64Lldflags) + + exportedVars.ExportStringListStaticVariable("Riscv64Cflags", riscv64Cflags) + exportedVars.ExportStringListStaticVariable("Riscv64Cppflags", riscv64Cppflags) + + exportedVars.ExportVariableReferenceDict("Riscv64ArchVariantCflags", riscv64ArchVariantCflagsVar) + exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantCflags", riscv64CpuVariantCflagsVar) + exportedVars.ExportVariableReferenceDict("Riscv64CpuVariantLdflags", riscv64CpuVariantLdflags) +} + +var ( + riscv64ArchVariantCflagsVar = map[string]string{} + + riscv64CpuVariantCflagsVar = map[string]string{} + + riscv64CpuVariantLdflags = map[string]string{} +) + +type toolchainRiscv64 struct { + toolchainBionic + toolchain64Bit + + ldflags string + lldflags string + toolchainCflags string +} + +func (t *toolchainRiscv64) Name() string { + return "riscv64" +} + +func (t *toolchainRiscv64) IncludeFlags() string { + return "" +} + +func (t *toolchainRiscv64) ClangTriple() string { + return "riscv64-linux-android" +} + +func (t *toolchainRiscv64) Cflags() string { + return "${config.Riscv64Cflags}" +} + +func (t *toolchainRiscv64) Cppflags() string { + return "${config.Riscv64Cppflags}" +} + +func (t *toolchainRiscv64) Ldflags() string { + return t.ldflags +} + +func (t *toolchainRiscv64) Lldflags() string { + return t.lldflags +} + +func (t *toolchainRiscv64) ToolchainCflags() string { + return t.toolchainCflags +} + +func (toolchainRiscv64) LibclangRuntimeLibraryArch() string { + return "riscv64" +} + +func riscv64ToolchainFactory(arch android.Arch) Toolchain { + switch arch.ArchVariant { + case "": + default: + panic(fmt.Sprintf("Unknown Riscv64 architecture version: %q", arch.ArchVariant)) + } + + toolchainCflags := []string{riscv64ArchVariantCflagsVar[arch.ArchVariant]} + toolchainCflags = append(toolchainCflags, + variantOrDefault(riscv64CpuVariantCflagsVar, arch.CpuVariant)) + + extraLdflags := variantOrDefault(riscv64CpuVariantLdflags, arch.CpuVariant) + return &toolchainRiscv64{ + ldflags: strings.Join([]string{ + "${config.Riscv64Ldflags}", + extraLdflags, + }, " "), + lldflags: strings.Join([]string{ + "${config.Riscv64Lldflags}", + extraLdflags, + }, " "), + toolchainCflags: strings.Join(toolchainCflags, " "), + } +} + +func init() { + registerToolchainFactory(android.Android, android.Riscv64, riscv64ToolchainFactory) +} diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go index 7175fdc1a..e78e16a4b 100644 --- a/cc/config/toolchain.go +++ b/cc/config/toolchain.go @@ -72,11 +72,6 @@ func findToolchain(os android.OsType, arch android.Arch) (Toolchain, error) { type Toolchain interface { Name() string - GccRoot() string - GccTriple() string - // GccVersion should return a real value, not a ninja reference - GccVersion() string - IncludeFlags() string ClangTriple() string diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go index aebda0b51..e2b0f062a 100644 --- a/cc/config/x86_64_device.go +++ b/cc/config/x86_64_device.go @@ -80,17 +80,7 @@ var ( } ) -const ( - x86_64GccVersion = "4.9" -) - func init() { - - pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion) - - pctx.SourcePathVariable("X86_64GccRoot", - "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}") - exportedVars.ExportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"}) exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"}) @@ -128,24 +118,12 @@ func (t *toolchainX86_64) Name() string { return "x86_64" } -func (t *toolchainX86_64) GccRoot() string { - return "${config.X86_64GccRoot}" -} - -func (t *toolchainX86_64) GccTriple() string { - return "x86_64-linux-android" -} - -func (t *toolchainX86_64) GccVersion() string { - return x86_64GccVersion -} - func (t *toolchainX86_64) IncludeFlags() string { return "" } func (t *toolchainX86_64) ClangTriple() string { - return t.GccTriple() + return "x86_64-linux-android" } func (t *toolchainX86_64) ToolchainLdflags() string { diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go index 421b08354..3001ab405 100644 --- a/cc/config/x86_device.go +++ b/cc/config/x86_device.go @@ -88,16 +88,7 @@ var ( } ) -const ( - x86GccVersion = "4.9" -) - func init() { - pctx.StaticVariable("x86GccVersion", x86GccVersion) - - pctx.SourcePathVariable("X86GccRoot", - "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}") - exportedVars.ExportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"}) exportedVars.ExportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"}) @@ -134,18 +125,6 @@ func (t *toolchainX86) Name() string { return "x86" } -func (t *toolchainX86) GccRoot() string { - return "${config.X86GccRoot}" -} - -func (t *toolchainX86) GccTriple() string { - return "x86_64-linux-android" -} - -func (t *toolchainX86) GccVersion() string { - return x86GccVersion -} - func (t *toolchainX86) IncludeFlags() string { return "" } diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go index 976cc25be..96a53bff3 100644 --- a/cc/config/x86_linux_bionic_host.go +++ b/cc/config/x86_linux_bionic_host.go @@ -66,13 +66,20 @@ var ( "host_bionic_linker_script") ) +const ( + x86_64GccVersion = "4.9" +) + func init() { + pctx.StaticVariable("LinuxBionicCflags", strings.Join(linuxBionicCflags, " ")) pctx.StaticVariable("LinuxBionicLdflags", strings.Join(linuxBionicLdflags, " ")) pctx.StaticVariable("LinuxBionicLldflags", strings.Join(linuxBionicLdflags, " ")) // Use the device gcc toolchain for now - pctx.StaticVariable("LinuxBionicGccRoot", "${X86_64GccRoot}") + pctx.StaticVariable("LinuxBionicGccVersion", x86_64GccVersion) + pctx.SourcePathVariable("LinuxBionicGccRoot", + "prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${LinuxBionicGccVersion}") } type toolchainLinuxBionic struct { @@ -84,18 +91,6 @@ func (t *toolchainLinuxBionic) Name() string { return "x86_64" } -func (t *toolchainLinuxBionic) GccRoot() string { - return "${config.LinuxBionicGccRoot}" -} - -func (t *toolchainLinuxBionic) GccTriple() string { - return "x86_64-linux-android" -} - -func (t *toolchainLinuxBionic) GccVersion() string { - return "4.9" -} - func (t *toolchainLinuxBionic) IncludeFlags() string { return "" } diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go index 4e8fd7752..d928838ff 100644 --- a/cc/config/x86_linux_host.go +++ b/cc/config/x86_linux_host.go @@ -179,18 +179,6 @@ func (t *toolchainLinuxX8664) Name() string { return "x86_64" } -func (t *toolchainLinux) GccRoot() string { - return "${config.LinuxGccRoot}" -} - -func (t *toolchainLinux) GccTriple() string { - return "${config.LinuxGccTriple}" -} - -func (t *toolchainLinux) GccVersion() string { - return linuxGccVersion -} - func (t *toolchainLinux) IncludeFlags() string { return "" } diff --git a/cc/config/x86_windows_host.go b/cc/config/x86_windows_host.go index 2c8321100..565128037 100644 --- a/cc/config/x86_windows_host.go +++ b/cc/config/x86_windows_host.go @@ -173,24 +173,12 @@ func (t *toolchainWindowsX8664) Name() string { return "x86_64" } -func (t *toolchainWindows) GccRoot() string { - return "${config.WindowsGccRoot}" -} - -func (t *toolchainWindows) GccTriple() string { - return "${config.WindowsGccTriple}" -} - func (t *toolchainWindows) ToolchainCflags() string { - return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin") + return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin") } func (t *toolchainWindows) ToolchainLdflags() string { - return "-B" + filepath.Join(t.GccRoot(), t.GccTriple(), "bin") -} - -func (t *toolchainWindows) GccVersion() string { - return windowsGccVersion + return "-B" + filepath.Join("${config.WindowsGccRoot}", "${config.WindowsGccTriple}", "bin") } func (t *toolchainWindows) IncludeFlags() string { diff --git a/cc/fuzz.go b/cc/fuzz.go index 23d81d600..1cbd5572b 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -93,10 +93,10 @@ func UnstrippedOutputFile(module android.Module) android.Path { // IsValidSharedDependency takes a module and determines if it is a unique shared library // that should be installed in the fuzz target output directories. This function // returns true, unless: -// - The module is not an installable shared library, or -// - The module is a header or stub, or -// - The module is a prebuilt and its source is available, or -// - The module is a versioned member of an SDK snapshot. +// - The module is not an installable shared library, or +// - The module is a header or stub, or +// - The module is a prebuilt and its source is available, or +// - The module is a versioned member of an SDK snapshot. func IsValidSharedDependency(dependency android.Module) bool { // TODO(b/144090547): We should be parsing these modules using // ModuleDependencyTag instead of the current brute-force checking. diff --git a/cc/genrule.go b/cc/genrule.go index 239064f1c..4ef990c35 100644 --- a/cc/genrule.go +++ b/cc/genrule.go @@ -41,13 +41,13 @@ type GenruleExtraProperties struct { // variations. The following environment variables will be set when the command // execute: // -// CC_ARCH the name of the architecture the command is being executed for +// CC_ARCH the name of the architecture the command is being executed for // -// CC_MULTILIB "lib32" if the architecture the command is being executed for is 32-bit, -// "lib64" if it is 64-bit. +// CC_MULTILIB "lib32" if the architecture the command is being executed for is 32-bit, +// "lib64" if it is 64-bit. // -// CC_NATIVE_BRIDGE the name of the subdirectory that native bridge libraries are stored in if -// the architecture has native bridge enabled, empty if it is disabled. +// CC_NATIVE_BRIDGE the name of the subdirectory that native bridge libraries are stored in if +// the architecture has native bridge enabled, empty if it is disabled. func GenRuleFactory() android.Module { module := genrule.NewGenRule() diff --git a/cc/image.go b/cc/image.go index 3a0857b21..cb7f3c927 100644 --- a/cc/image.go +++ b/cc/image.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/cc/makevars.go b/cc/makevars.go index 6752f8cde..e4a9cf7ff 100644 --- a/cc/makevars.go +++ b/cc/makevars.go @@ -315,8 +315,6 @@ func makeVarsToolchain(ctx android.MakeVarsContext, secondPrefix string, ctx.Strict(makePrefix+"LD", "${config.ClangBin}/lld") ctx.Strict(makePrefix+"NDK_TRIPLE", config.NDKTriple(toolchain)) ctx.Strict(makePrefix+"TOOLS_PREFIX", "${config.ClangBin}/llvm-") - // TODO: GCC version is obsolete now that GCC has been removed. - ctx.Strict(makePrefix+"GCC_VERSION", toolchain.GccVersion()) } if target.Os.Class == android.Host { diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index 56fd5fc81..ef38a064a 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -148,12 +148,12 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // to the sysroot base + "usr/include" + to directory + directory component. // ndk_headers requires the license file to be specified. Example: // -// Given: -// sysroot base = "ndk/sysroot" -// from = "include/foo" -// to = "bar" -// header = "include/foo/woodly/doodly.h" -// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h" +// Given: +// sysroot base = "ndk/sysroot" +// from = "include/foo" +// to = "bar" +// header = "include/foo/woodly/doodly.h" +// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h" func ndkHeadersFactory() android.Module { module := &headerModule{} module.AddProperties(&module.properties) @@ -275,15 +275,17 @@ func versionedNdkHeadersFactory() android.Module { return module } -// preprocessed_ndk_header { -// name: "foo", -// preprocessor: "foo.sh", -// srcs: [...], -// to: "android", -// } +// preprocessed_ndk_header { +// name: "foo", +// preprocessor: "foo.sh", +// srcs: [...], +// to: "android", +// } // // Will invoke the preprocessor as: -// $preprocessor -o $SYSROOT/usr/include/android/needs_preproc.h $src +// +// $preprocessor -o $SYSROOT/usr/include/android/needs_preproc.h $src +// // For each src in srcs. type preprocessedHeadersProperties struct { // The preprocessor to run. Must be a program inside the source directory diff --git a/cc/ndk_library.go b/cc/ndk_library.go index 5ef41eae5..241054058 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -84,12 +84,11 @@ var ( // // Example: // -// ndk_library { -// name: "libfoo", -// symbol_file: "libfoo.map.txt", -// first_version: "9", -// } -// +// ndk_library { +// name: "libfoo", +// symbol_file: "libfoo.map.txt", +// first_version: "9", +// } type libraryProperties struct { // Relative path to the symbol map. // An example file can be seen here: TODO(danalbert): Make an example. diff --git a/cc/prebuilt.go b/cc/prebuilt.go index f54c6f8d6..e0c28cefb 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -341,10 +341,10 @@ type bazelPrebuiltLibraryStaticAttributes struct { // TODO(b/228623543): The below is not entirely true until the bug is fixed. For now, both targets are always generated // Implements bp2build for cc_prebuilt_library modules. This will generate: -// * Only a prebuilt_library_static if the shared.enabled property is set to false across all variants. -// * Only a prebuilt_library_shared if the static.enabled property is set to false across all variants -// * Both a prebuilt_library_static and prebuilt_library_shared if the aforementioned properties are not false across -// all variants +// - Only a prebuilt_library_static if the shared.enabled property is set to false across all variants. +// - Only a prebuilt_library_shared if the static.enabled property is set to false across all variants +// - Both a prebuilt_library_static and prebuilt_library_shared if the aforementioned properties are not false across +// all variants // // In all cases, prebuilt_library_static target names will be appended with "_bp2build_cc_library_static". func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) { diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index 9d40ad058..792ffe364 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -4,7 +4,7 @@ // 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 +// 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, @@ -263,12 +263,12 @@ type BaseSnapshotDecoratorProperties struct { // version, snapshot arch, etc. It also adds a special suffix to Soong module name, so it doesn't // collide with source modules. e.g. the following example module, // -// vendor_snapshot_static { -// name: "libbase", -// arch: "arm64", -// version: 30, -// ... -// } +// vendor_snapshot_static { +// name: "libbase", +// arch: "arm64", +// version: 30, +// ... +// } // // will be seen as "libbase.vendor_static.30.arm64" by Soong. type BaseSnapshotDecorator struct { @@ -370,7 +370,6 @@ func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *BaseSnapshotDecorato } } -// // Module definitions for snapshots of libraries (shared, static, header). // // Modules (vendor|recovery)_snapshot_(shared|static|header) are defined here. Shared libraries and @@ -630,7 +629,6 @@ func RecoverySnapshotHeaderFactory() android.Module { var _ snapshotSanitizer = (*snapshotLibraryDecorator)(nil) -// // Module definitions for snapshots of executable binaries. // // Modules (vendor|recovery)_snapshot_binary are defined here. They have their prebuilt executable @@ -728,7 +726,6 @@ func snapshotBinaryFactory(image SnapshotImage, moduleSuffix string) android.Mod return module.Init() } -// // Module definitions for snapshots of object files (*.o). // // Modules (vendor|recovery)_snapshot_object are defined here. They have their prebuilt object diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index de50ef50f..cf4617da3 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go index 65a2b0c9e..f2c8545bc 100644 --- a/cc/vendor_public_library.go +++ b/cc/vendor_public_library.go @@ -28,17 +28,16 @@ var ( // // Example: // -// vendor_public_library { -// name: "libfoo", -// symbol_file: "libfoo.map.txt", -// export_public_headers: ["libfoo_headers"], -// } -// -// cc_headers { -// name: "libfoo_headers", -// export_include_dirs: ["include"], -// } -// +// vendor_public_library { +// name: "libfoo", +// symbol_file: "libfoo.map.txt", +// export_public_headers: ["libfoo_headers"], +// } +// +// cc_headers { +// name: "libfoo_headers", +// export_include_dirs: ["include"], +// } type vendorPublicLibraryProperties struct { // Relative path to the symbol map. Symbol_file *string diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index e7c05aca8..77e6f6ffe 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go index 31b6d10dd..37819a4be 100644 --- a/cc/vndk_prebuilt.go +++ b/cc/vndk_prebuilt.go @@ -29,26 +29,25 @@ var ( // // Example: // -// vndk_prebuilt_shared { -// name: "libfoo", -// version: "27", -// target_arch: "arm64", -// vendor_available: true, -// product_available: true, -// vndk: { -// enabled: true, -// }, -// export_include_dirs: ["include/external/libfoo/vndk_include"], -// arch: { -// arm64: { -// srcs: ["arm/lib64/libfoo.so"], -// }, -// arm: { -// srcs: ["arm/lib/libfoo.so"], -// }, -// }, -// } -// +// vndk_prebuilt_shared { +// name: "libfoo", +// version: "27", +// target_arch: "arm64", +// vendor_available: true, +// product_available: true, +// vndk: { +// enabled: true, +// }, +// export_include_dirs: ["include/external/libfoo/vndk_include"], +// arch: { +// arm64: { +// srcs: ["arm/lib64/libfoo.so"], +// }, +// arm: { +// srcs: ["arm/lib/libfoo.so"], +// }, +// }, +// } type vndkPrebuiltProperties struct { // VNDK snapshot version. Version *string @@ -250,25 +249,25 @@ func vndkPrebuiltSharedLibrary() *Module { // vndk_prebuilt_shared installs Vendor Native Development kit (VNDK) snapshot // shared libraries for system build. Example: // -// vndk_prebuilt_shared { -// name: "libfoo", -// version: "27", -// target_arch: "arm64", -// vendor_available: true, -// product_available: true, -// vndk: { -// enabled: true, -// }, -// export_include_dirs: ["include/external/libfoo/vndk_include"], -// arch: { -// arm64: { -// srcs: ["arm/lib64/libfoo.so"], -// }, -// arm: { -// srcs: ["arm/lib/libfoo.so"], -// }, -// }, -// } +// vndk_prebuilt_shared { +// name: "libfoo", +// version: "27", +// target_arch: "arm64", +// vendor_available: true, +// product_available: true, +// vndk: { +// enabled: true, +// }, +// export_include_dirs: ["include/external/libfoo/vndk_include"], +// arch: { +// arm64: { +// srcs: ["arm/lib64/libfoo.so"], +// }, +// arm: { +// srcs: ["arm/lib/libfoo.so"], +// }, +// }, +// } func VndkPrebuiltSharedFactory() android.Module { module := vndkPrebuiltSharedLibrary() return module.Init() diff --git a/cmd/extract_apks/bundle_proto/Android.bp b/cmd/extract_apks/bundle_proto/Android.bp new file mode 100644 index 000000000..e56c0fb32 --- /dev/null +++ b/cmd/extract_apks/bundle_proto/Android.bp @@ -0,0 +1,13 @@ +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +python_library_host { + name: "config_proto", + srcs: [ + "config.proto", + ], + proto: { + canonical_path_from_root: false, + }, +} diff --git a/cmd/extract_apks/bundle_proto/config.proto b/cmd/extract_apks/bundle_proto/config.proto index d6fac030e..946bd9af0 100644 --- a/cmd/extract_apks/bundle_proto/config.proto +++ b/cmd/extract_apks/bundle_proto/config.proto @@ -26,6 +26,9 @@ message BundleConfig { ASSET_ONLY = 2; } BundleType type = 8; + + // Configuration for locales. + Locales locales = 9; } message Bundletool { @@ -40,6 +43,48 @@ message Compression { // the name of the modules, and using forward slash ("/") as a name separator. // Examples: "res/raw/**", "assets/**/*.uncompressed", etc. repeated string uncompressed_glob = 1; + + enum AssetModuleCompression { + UNSPECIFIED = 0; + // Assets are left uncompressed in the generated asset module. + UNCOMPRESSED = 1; + // Assets are compressed in the generated asset module. + // This option can be overridden at a finer granularity by specifying + // files or folders to keep uncompressed in `uncompressed_glob`. + // This option should only be used if the app is able to handle compressed + // asset module content at runtime (some runtime APIs may misbehave). + COMPRESSED = 2; + } + + // Default compression strategy for install-time asset modules. + // If the compression strategy indicates to compress a file and the same file + // matches one of the `uncompressed_glob` values, the `uncompressed_glob` + // takes precedence (the file is left uncompressed in the generated APK). + // + // If unspecified, asset module content is left uncompressed in the + // generated asset modules. + // + // Note: this flag only configures the compression strategy for install-time + // asset modules; the content of on-demand and fast-follow asset modules is + // always kept uncompressed. + AssetModuleCompression install_time_asset_module_default_compression = 2; + + enum ApkCompressionAlgorithm { + // Default in the current version of bundletool is zlib deflate algorithm + // with compression level 9 for the application's resources and compression + // level 6 for other entries. + // + // This is a good trade-off between size of final APK and size of patches + // which are used to update the application from previous to next version. + DEFAULT_APK_COMPRESSION_ALGORITHM = 0; + + // 7zip implementation of deflate algorithm which gives smaller APK size + // but size of patches required to update the application are larger. + P7ZIP = 1; + } + + // Compression algorithm which is used to compress entries in final APKs. + ApkCompressionAlgorithm apk_compression_algorithm = 3; } // Resources to keep in the master split. @@ -55,12 +100,40 @@ message Optimizations { // This is for uncompressing native libraries on M+ devices (L+ devices on // instant apps). UncompressNativeLibraries uncompress_native_libraries = 2; - // This is for uncompressing dex files on P+ devices. + // This is for uncompressing dex files. UncompressDexFiles uncompress_dex_files = 3; // Configuration for the generation of standalone APKs. // If no StandaloneConfig is set, the configuration is inherited from // splits_config. StandaloneConfig standalone_config = 4; + + // Optimizations that are applied to resources. + ResourceOptimizations resource_optimizations = 5; + + // Configuration for archiving the app. + StoreArchive store_archive = 6; +} + +message ResourceOptimizations { + // Whether to use sparse encoding for resource tables. + // Resources in sparse resource table are accessed using a binary search tree. + // This decreases APK size at the cost of resource retrieval performance. + SparseEncoding sparse_encoding = 1; + + enum SparseEncoding { + // Previously 'ENFORCED'. This option is deprecated because of issues found + // in Android O up to Android Sv2 and causes segfaults in + // Resources#getIdentifier. + reserved 1; + reserved "ENFORCED"; + + // Disables sparse encoding. + UNSPECIFIED = 0; + // Generates special APKs for Android SDK +32 with sparse resource tables. + // Devices with Android SDK below 32 will still receive APKs with regular + // resource tables. + VARIANT_FOR_SDK_32 = 2; + } } message UncompressNativeLibraries { @@ -68,9 +141,41 @@ message UncompressNativeLibraries { } message UncompressDexFiles { + // A new variant with uncompressed dex will be generated. The sdk targeting + // of the variant is determined by 'uncompressed_dex_target_sdk'. + bool enabled = 1; + + // If 'enabled' field is set, this will determine the sdk targeting of the + // generated variant. + UncompressedDexTargetSdk uncompressed_dex_target_sdk = 2; + + enum UncompressedDexTargetSdk { + // Q+ variant will be generated. + UNSPECIFIED = 0; + // S+ variant will be generated. + SDK_31 = 1; + } +} + +message StoreArchive { + // Archive is an app state that allows an official app store to reclaim device + // storage and disable app functionality temporarily until the user interacts + // with the app again. Upon interaction the latest available version of the + // app will be restored while leaving user data unaffected. + // Enabled by default. bool enabled = 1; } +message Locales { + // Instructs bundletool to generate locale config and inject it into + // AndroidManifest.xml. A locale is marked as supported by the application if + // there is at least one resource value in this locale. Be very careful with + // this setting because if some of your libraries expose resources in some + // locales which are not actually supported by your application it will mark + // this locale as supported. Disabled by default. + bool inject_locale_config = 1; +} + // Optimization configuration used to generate Split APKs. message SplitsConfig { repeated SplitDimension split_dimension = 1; @@ -82,8 +187,28 @@ message StandaloneConfig { repeated SplitDimension split_dimension = 1; // Whether 64 bit libraries should be stripped from Standalone APKs. bool strip_64_bit_libraries = 2; + // Dex merging strategy that should be applied to produce Standalone APKs. + DexMergingStrategy dex_merging_strategy = 3; + + enum DexMergingStrategy { + // Strategy that does dex merging for applications that have minimum SDK + // below 21 to ensure dex files from all modules are merged into one or + // mainDexList is applied when merging into one dex is not possible. For + // applications with minSdk >= 21 dex files from all modules are copied into + // standalone APK as is because Android supports multiple dex files natively + // starting from Android 5.0. + MERGE_IF_NEEDED = 0; + // Requires to copy dex files from all modules into standalone APK as is. + // If an application supports SDKs below 21 this strategy puts + // responsibility of providing dex files compatible with legacy multidex on + // application developers. + NEVER_MERGE = 1; + } } +// BEGIN-INTERNAL +// LINT.IfChange +// END-INTERNAL message SplitDimension { enum Value { UNSPECIFIED_VALUE = 0; @@ -92,8 +217,9 @@ message SplitDimension { LANGUAGE = 3; TEXTURE_COMPRESSION_FORMAT = 4; // BEGIN-INTERNAL - GRAPHICS_API = 5; + GRAPHICS_API = 5 [deprecated = true]; // END-INTERNAL + DEVICE_TIER = 6; } Value value = 1; @@ -105,11 +231,14 @@ message SplitDimension { // the targeting is encoded in the directory name (e.g: assets/foo#tcf_etc1) SuffixStripping suffix_stripping = 3; } +// BEGIN-INTERNAL +// LINT.ThenChange(//depot/google3/wireless/android/vending/developer/proto/storage/app/apk_bundle.proto) +// END-INTERNAL message SuffixStripping { // If set to 'true', indicates that the targeting suffix should be removed - // from assets paths for this dimension when splits (or asset slices) are - // generated. + // from assets paths for this dimension when splits (e.g: "asset packs") or + // standalone/universal APKs are generated. // This only applies to assets. // For example a folder with path "assets/level1_textures#tcf_etc1" // would be outputted to "assets/level1_textures". File contents are @@ -117,9 +246,9 @@ message SuffixStripping { bool enabled = 1; // The default suffix to be used for the cases where separate slices can't - // be generated for this dimension. In the case of standalone/universal APKs - // generation, stripping the suffix can lead to file name collisions. This - // default suffix defines the directories to retain. The others are + // be generated for this dimension - typically for standalone or universal + // APKs. + // This default suffix defines the directories to retain. The others are // discarded: standalone/universal APKs will contain only directories // targeted at this value for the dimension. // @@ -135,6 +264,15 @@ message SuffixStripping { message ApexConfig { // Configuration for processing of APKs embedded in an APEX image. repeated ApexEmbeddedApkConfig apex_embedded_apk_config = 1; + + // Explicit list of supported ABIs. + // Default: See ApexBundleValidator.REQUIRED_ONE_OF_ABI_SETS + repeated SupportedAbiSet supported_abi_set = 2; +} + +// Represents a set of ABIs which must be supported by a single APEX image. +message SupportedAbiSet { + repeated string abi = 1; } message ApexEmbeddedApkConfig { diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go index f8844fc94..e0638b8ed 100644 --- a/cmd/pom2bp/pom2bp.go +++ b/cmd/pom2bp/pom2bp.go @@ -150,6 +150,7 @@ var sdkVersion string var defaultMinSdkVersion string var useVersion string var staticDeps bool +var writeCmd bool var jetifier bool func InList(s string, list []string) bool { @@ -810,6 +811,9 @@ Usage: %s [--rewrite <regex>=<replace>] [--exclude <module>] [--extra-static-lib -use-version <version> If the maven directory contains multiple versions of artifacts and their pom files, -use-version can be used to only write Android.bp files for a specific version of those artifacts. + -write-cmd + Whether to write the command line arguments used to generate the build file as a comment at + the top of the build file itself. -jetifier Sets jetifier: true for all modules. <dir> @@ -836,6 +840,7 @@ Usage: %s [--rewrite <regex>=<replace>] [--exclude <module>] [--extra-static-lib flag.StringVar(&defaultMinSdkVersion, "default-min-sdk-version", "24", "Default min_sdk_version to use, if one is not available from AndroidManifest.xml. Default: 24") flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version") flag.BoolVar(&staticDeps, "static-deps", false, "Statically include direct dependencies") + flag.BoolVar(&writeCmd, "write-cmd", true, "Write command line arguments as a comment") flag.BoolVar(&jetifier, "jetifier", false, "Sets jetifier: true on all modules") flag.StringVar(®en, "regen", "", "Rewrite specified file") flag.BoolVar(&pom2build, "pom2build", false, "If true, will generate a Bazel BUILD file *instead* of a .bp file") @@ -962,8 +967,13 @@ Usage: %s [--rewrite <regex>=<replace>] [--exclude <module>] [--extra-static-lib if pom2build { commentString = "#" } - fmt.Fprintln(buf, commentString, "Automatically generated with:") - fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " ")) + + fmt.Fprintln(buf, commentString, "This is a generated file. Do not modify directly.") + + if writeCmd { + fmt.Fprintln(buf, commentString, "Automatically generated with:") + fmt.Fprintln(buf, commentString, "pom2bp", strings.Join(proptools.ShellEscapeList(os.Args[1:]), " ")) + } depsTemplate := bpDepsTemplate template := bpTemplate diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go index 4f7451d0c..91e3540dd 100644 --- a/cmd/sbox/sbox.go +++ b/cmd/sbox/sbox.go @@ -208,7 +208,6 @@ func run() error { // // returns an exec.Cmd that can be ran from within sbox context if no error, or nil if error. // caller must ensure script is cleaned up if function succeeds. -// func createCommandScript(rawCommand, scriptPath, scriptPathInSandbox string) (*exec.Cmd, error) { err := os.WriteFile(scriptPath, []byte(rawCommand), 0644) if err != nil { diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go index 36513b64b..6000cf4be 100644 --- a/dexpreopt/class_loader_context.go +++ b/dexpreopt/class_loader_context.go @@ -25,11 +25,11 @@ import ( ) // This comment describes the following: -// 1. the concept of class loader context (CLC) and its relation to classpath -// 2. how PackageManager constructs CLC from shared libraries and their dependencies -// 3. build-time vs. run-time CLC and why this matters for dexpreopt -// 4. manifest fixer: a tool that adds missing <uses-library> tags to the manifests -// 5. build system support for CLC +// 1. the concept of class loader context (CLC) and its relation to classpath +// 2. how PackageManager constructs CLC from shared libraries and their dependencies +// 3. build-time vs. run-time CLC and why this matters for dexpreopt +// 4. manifest fixer: a tool that adds missing <uses-library> tags to the manifests +// 5. build system support for CLC // // 1. Class loader context // ----------------------- @@ -59,15 +59,16 @@ import ( // loaders are not duplicated (at runtime there is a single class loader instance for each library). // // Example: A has <uses-library> tags B, C and D; C has <uses-library tags> B and D; -// D has <uses-library> E; B and E have no <uses-library> dependencies. The CLC is: -// A -// ├── B -// ├── C -// │ ├── B -// │ └── D -// │ └── E -// └── D -// └── E +// +// D has <uses-library> E; B and E have no <uses-library> dependencies. The CLC is: +// A +// ├── B +// ├── C +// │ ├── B +// │ └── D +// │ └── E +// └── D +// └── E // // CLC defines the lookup order of libraries when resolving Java classes used by the library/app. // The lookup order is important because libraries may contain duplicate classes, and the class is @@ -188,7 +189,6 @@ import ( // rule generation phase. // // ClassLoaderContext is a structure that represents CLC. -// type ClassLoaderContext struct { // The name of the library. Name string @@ -253,7 +253,6 @@ func (c *ClassLoaderContext) excludeLibs(excludedLibs []string) (*ClassLoaderCon // generates a build rule that includes conditional CLC for all versions, extracts the target SDK // version from the manifest, and filters the CLCs based on that version. Exact final CLC that is // passed to dex2oat is unknown to the build system, and gets known only at Ninja stage. -// type ClassLoaderContextMap map[int][]*ClassLoaderContext // Compatibility libraries. Some are optional, and some are required: this is the default that @@ -502,7 +501,6 @@ func (clcMap ClassLoaderContextMap) ExcludeLibs(excludedLibs []string) ClassLoad // constructs class loader context on device. // // TODO(b/132357300): remove "android.hidl.manager" and "android.hidl.base" for non-system apps. -// func fixClassLoaderContext(clcMap ClassLoaderContextMap) { required, optional := clcMap.UsesLibs() usesLibs := append(required, optional...) diff --git a/etc/snapshot_etc.go b/etc/snapshot_etc.go index b54a8a6ec..0d65ab6b6 100644 --- a/etc/snapshot_etc.go +++ b/etc/snapshot_etc.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/finder/finder.go b/finder/finder.go index b4834b16b..596129088 100644 --- a/finder/finder.go +++ b/finder/finder.go @@ -732,15 +732,15 @@ func (f *Finder) parseCacheEntry(bytes []byte) ([]dirFullInfo, error) { // because we know this separator won't appear in the json that we're parsing. // // The newline byte can only appear in a UTF-8 stream if the newline character appears, because: -// - The newline character is encoded as "0000 1010" in binary ("0a" in hex) -// - UTF-8 dictates that bytes beginning with a "0" bit are never emitted as part of a multibyte -// character. +// - The newline character is encoded as "0000 1010" in binary ("0a" in hex) +// - UTF-8 dictates that bytes beginning with a "0" bit are never emitted as part of a multibyte +// character. // // We know that the newline character will never appear in our json string, because: -// - If a newline character appears as part of a data string, then json encoding will -// emit two characters instead: '\' and 'n'. -// - The json encoder that we use doesn't emit the optional newlines between any of its -// other outputs. +// - If a newline character appears as part of a data string, then json encoding will +// emit two characters instead: '\' and 'n'. +// - The json encoder that we use doesn't emit the optional newlines between any of its +// other outputs. const lineSeparator = byte('\n') func (f *Finder) readLine(reader *bufio.Reader) ([]byte, error) { diff --git a/genrule/genrule.go b/genrule/genrule.go index c52ddee53..d54274346 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -912,9 +912,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { var Bool = proptools.Bool var String = proptools.String -// // Defaults -// type Defaults struct { android.ModuleBase android.DefaultsModuleBase diff --git a/java/Android.bp b/java/Android.bp index df0d1eb3d..d66e0953f 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -43,6 +43,7 @@ bootstrap_go_package { "dexpreopt_bootjars.go", "dexpreopt_check.go", "dexpreopt_config.go", + "dexpreopt_config_testing.go", "droiddoc.go", "droidstubs.go", "fuzz.go", @@ -85,6 +86,7 @@ bootstrap_go_package { "dex_test.go", "dexpreopt_test.go", "dexpreopt_bootjars_test.go", + "dexpreopt_config_test.go", "droiddoc_test.go", "droidstubs_test.go", "hiddenapi_singleton_test.go", diff --git a/java/aar.go b/java/aar.go index 00ff7e774..2ddd1882e 100644 --- a/java/aar.go +++ b/java/aar.go @@ -268,7 +268,7 @@ var extractAssetsRule = pctx.AndroidStaticRule("extractAssets", func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string, - extraLinkFlags ...string) { + enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) { transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags := aaptLibs(ctx, sdkContext, classLoaderContexts) @@ -281,14 +281,15 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkCon manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile) manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{ - SdkContext: sdkContext, - ClassLoaderContexts: classLoaderContexts, - IsLibrary: a.isLibrary, - UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs, - UsesNonSdkApis: a.usesNonSdkApis, - UseEmbeddedDex: a.useEmbeddedDex, - HasNoCode: a.hasNoCode, - LoggingParent: a.LoggingParent, + SdkContext: sdkContext, + ClassLoaderContexts: classLoaderContexts, + IsLibrary: a.isLibrary, + UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs, + UsesNonSdkApis: a.usesNonSdkApis, + UseEmbeddedDex: a.useEmbeddedDex, + HasNoCode: a.hasNoCode, + LoggingParent: a.LoggingParent, + EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion, }) // Add additional manifest files to transitive manifests. @@ -531,7 +532,7 @@ func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.aapt.isLibrary = true a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) - a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil) + a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false) a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() diff --git a/java/android_manifest.go b/java/android_manifest.go index 1553564c2..cde7d1075 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -43,13 +43,12 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger", // targetSdkVersion for manifest_fixer // When TARGET_BUILD_APPS is not empty, this method returns 10000 for modules targeting an unreleased SDK // This enables release builds (that run with TARGET_BUILD_APPS=[val...]) to target APIs that have not yet been finalized as part of an SDK -func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext android.SdkContext) string { - targetSdkVersionSpec := sdkContext.TargetSdkVersion(ctx) - // Return 10000 for modules targeting "current" if either - // 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty) - // 2. The module is run as part of MTS, and should be testable on stable branches +func targetSdkVersionForManifestFixer(ctx android.ModuleContext, params ManifestFixerParams) string { + targetSdkVersionSpec := params.SdkContext.TargetSdkVersion(ctx) + + // Check if we want to return 10000 // TODO(b/240294501): Determine the rules for handling test apexes - if targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module())) { + if shouldReturnFinalOrFutureInt(ctx, targetSdkVersionSpec, params.EnforceDefaultTargetSdkVersion) { return strconv.Itoa(android.FutureApiLevel.FinalOrFutureInt()) } targetSdkVersion, err := targetSdkVersionSpec.EffectiveVersionString(ctx) @@ -59,6 +58,17 @@ func targetSdkVersionForManifestFixer(ctx android.ModuleContext, sdkContext andr return targetSdkVersion } +// Return true for modules targeting "current" if either +// 1. The module is built in unbundled mode (TARGET_BUILD_APPS not empty) +// 2. The module is run as part of MTS, and should be testable on stable branches +// Do not return 10000 if we are enforcing default targetSdkVersion and sdk has been finalised +func shouldReturnFinalOrFutureInt(ctx android.ModuleContext, targetSdkVersionSpec android.SdkSpec, enforceDefaultTargetSdkVersion bool) bool { + if enforceDefaultTargetSdkVersion && ctx.Config().PlatformSdkFinal() { + return false + } + return targetSdkVersionSpec.ApiLevel.IsPreview() && (ctx.Config().UnbundledBuildApps() || includedInMts(ctx.Module())) +} + // Helper function that casts android.Module to java.androidTestApp // If this type conversion is possible, it queries whether the test app is included in an MTS suite func includedInMts(module android.Module) bool { @@ -69,15 +79,17 @@ func includedInMts(module android.Module) bool { } type ManifestFixerParams struct { - SdkContext android.SdkContext - ClassLoaderContexts dexpreopt.ClassLoaderContextMap - IsLibrary bool - UseEmbeddedNativeLibs bool - UsesNonSdkApis bool - UseEmbeddedDex bool - HasNoCode bool - TestOnly bool - LoggingParent string + SdkContext android.SdkContext + ClassLoaderContexts dexpreopt.ClassLoaderContextMap + IsLibrary bool + DefaultManifestVersion string + UseEmbeddedNativeLibs bool + UsesNonSdkApis bool + UseEmbeddedDex bool + HasNoCode bool + TestOnly bool + LoggingParent string + EnforceDefaultTargetSdkVersion bool } // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml @@ -136,7 +148,7 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, var argsMapper = make(map[string]string) if params.SdkContext != nil { - targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params.SdkContext) + targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params) args = append(args, "--targetSdkVersion ", targetSdkVersion) if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { diff --git a/java/app.go b/java/app.go index c7fdc0c47..04db0d4d8 100755 --- a/java/app.go +++ b/java/app.go @@ -101,6 +101,15 @@ type appProperties struct { PreventInstall bool `blueprint:"mutated"` IsCoverageVariant bool `blueprint:"mutated"` + // It can be set to test the behaviour of default target sdk version. + // Only required when updatable: false. It is an error if updatable: true and this is false. + Enforce_default_target_sdk_version *bool + + // If set, the targetSdkVersion for the target is set to the latest default API level. + // This would be by default false, unless updatable: true or + // enforce_default_target_sdk_version: true in which case this defaults to true. + EnforceDefaultTargetSdkVersion bool `blueprint:"mutated"` + // Whether this app is considered mainline updatable or not. When set to true, this will enforce // additional rules to make sure an app can safely be updated. Default is false. // Prefer using other specific properties if build behaviour must be changed; avoid using this @@ -296,6 +305,18 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } + + if !BoolDefault(a.appProperties.Enforce_default_target_sdk_version, true) { + ctx.PropertyErrorf("enforce_default_target_sdk_version", "Updatable apps must enforce default target sdk version") + } + // TODO(b/227460469) after all the modules removes the target sdk version, throw an error if the target sdk version is explicitly set. + if a.deviceProperties.Target_sdk_version == nil { + a.SetEnforceDefaultTargetSdkVersion(true) + } + } + + if Bool(a.appProperties.Enforce_default_target_sdk_version) { + a.SetEnforceDefaultTargetSdkVersion(true) } a.checkPlatformAPI(ctx) @@ -424,7 +445,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) { a.aapt.splitNames = a.appProperties.Package_splits a.aapt.LoggingParent = String(a.overridableAppProperties.Logging_parent) a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, - a.usesLibraryProperties.Exclude_uses_libs, aaptLinkFlags...) + a.usesLibraryProperties.Exclude_uses_libs, a.enforceDefaultTargetSdkVersion(), aaptLinkFlags...) // apps manifests are handled by aapt, don't let Module see them a.properties.Manifest = nil @@ -589,6 +610,16 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + var noticeAssetPath android.WritablePath + if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") { + // The rule to create the notice file can't be generated yet, as the final output path + // for the apk isn't known yet. Add the path where the notice file will be generated to the + // aapt rules now before calling aaptBuildActions, the rule to create the notice file will + // be generated later. + noticeAssetPath = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz") + a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath) + } + // Process all building blocks, from AAPT to certificates. a.aaptBuildActions(ctx) @@ -663,7 +694,8 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) } - if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") { + if a.aapt.noticeFile.Valid() { + // Generating the notice file rule has to be here after a.outputFile is known. noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz") android.BuildNoticeHtmlOutputFromLicenseMetadata( ctx, noticeFile, "", "", @@ -672,13 +704,11 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { android.PathForModuleInstall(ctx).String() + "/", a.outputFile.String(), }) - noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz") builder := android.NewRuleBuilder(pctx, ctx) builder.Command().Text("cp"). Input(noticeFile). Output(noticeAssetPath) builder.Build("notice_dir", "Building notice dir") - a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath) } for _, split := range a.aapt.splits { @@ -848,6 +878,14 @@ func (a *AndroidApp) buildAppDependencyInfo(ctx android.ModuleContext) { a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, a.MinSdkVersion(ctx).String(), depsInfo) } +func (a *AndroidApp) enforceDefaultTargetSdkVersion() bool { + return a.appProperties.EnforceDefaultTargetSdkVersion +} + +func (a *AndroidApp) SetEnforceDefaultTargetSdkVersion(val bool) { + a.appProperties.EnforceDefaultTargetSdkVersion = val +} + func (a *AndroidApp) Updatable() bool { return Bool(a.appProperties.Updatable) } diff --git a/java/app_import.go b/java/app_import.go index 58c01a447..52e37b053 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -461,19 +461,19 @@ func createVariantGroupType(variants []string, variantGroupName string) reflect. // android_app_import imports a prebuilt apk with additional processing specified in the module. // DPI-specific apk source files can be specified using dpi_variants. Example: // -// android_app_import { -// name: "example_import", -// apk: "prebuilts/example.apk", -// dpi_variants: { -// mdpi: { -// apk: "prebuilts/example_mdpi.apk", -// }, -// xhdpi: { -// apk: "prebuilts/example_xhdpi.apk", -// }, -// }, -// presigned: true, -// } +// android_app_import { +// name: "example_import", +// apk: "prebuilts/example.apk", +// dpi_variants: { +// mdpi: { +// apk: "prebuilts/example_mdpi.apk", +// }, +// xhdpi: { +// apk: "prebuilts/example_xhdpi.apk", +// }, +// }, +// presigned: true, +// } func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} module.AddProperties(&module.properties) diff --git a/java/app_set.go b/java/app_set.go index 694b1670e..d99fadb34 100644 --- a/java/app_set.go +++ b/java/app_set.go @@ -90,10 +90,11 @@ func (as *AndroidAppSet) APKCertsFile() android.Path { } var TargetCpuAbi = map[string]string{ - "arm": "ARMEABI_V7A", - "arm64": "ARM64_V8A", - "x86": "X86", - "x86_64": "X86_64", + "arm": "ARMEABI_V7A", + "arm64": "ARM64_V8A", + "riscv64": "RISCV64", + "x86": "X86", + "x86_64": "X86_64", } func SupportedAbis(ctx android.ModuleContext) []string { diff --git a/java/app_test.go b/java/app_test.go index 2297ea993..83b47bdc9 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -3049,6 +3049,179 @@ func TestTargetSdkVersionManifestFixer(t *testing.T) { } } +func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) { + platform_sdk_codename := "Tiramisu" + platform_sdk_version := 33 + testCases := []struct { + name string + platform_sdk_final bool + targetSdkVersionInBp *string + targetSdkVersionExpected *string + updatable bool + }{ + { + name: "Non-Updatable Module: Android.bp has older targetSdkVersion", + targetSdkVersionInBp: proptools.StringPtr("29"), + targetSdkVersionExpected: proptools.StringPtr("29"), + updatable: false, + }, + { + name: "Updatable Module: Android.bp has older targetSdkVersion", + targetSdkVersionInBp: proptools.StringPtr("30"), + targetSdkVersionExpected: proptools.StringPtr("30"), + updatable: true, + }, + { + name: "Updatable Module: Android.bp has no targetSdkVersion", + targetSdkVersionExpected: proptools.StringPtr("10000"), + updatable: true, + }, + { + name: "[SDK finalised] Non-Updatable Module: Android.bp has older targetSdkVersion", + platform_sdk_final: true, + targetSdkVersionInBp: proptools.StringPtr("30"), + targetSdkVersionExpected: proptools.StringPtr("30"), + updatable: false, + }, + { + name: "[SDK finalised] Updatable Module: Android.bp has older targetSdkVersion", + platform_sdk_final: true, + targetSdkVersionInBp: proptools.StringPtr("30"), + targetSdkVersionExpected: proptools.StringPtr("30"), + updatable: true, + }, + { + name: "[SDK finalised] Updatable Module: Android.bp has targetSdkVersion as platform sdk codename", + platform_sdk_final: true, + targetSdkVersionInBp: proptools.StringPtr(platform_sdk_codename), + targetSdkVersionExpected: proptools.StringPtr("33"), + updatable: true, + }, + { + name: "[SDK finalised] Updatable Module: Android.bp has no targetSdkVersion", + platform_sdk_final: true, + targetSdkVersionExpected: proptools.StringPtr("33"), + updatable: true, + }, + } + for _, testCase := range testCases { + bp := fmt.Sprintf(` + android_app { + name: "foo", + sdk_version: "current", + min_sdk_version: "29", + target_sdk_version: "%v", + updatable: %t, + enforce_default_target_sdk_version: %t + } + `, proptools.String(testCase.targetSdkVersionInBp), testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable + + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Platform_version_active_codenames = []string{platform_sdk_codename} + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) + + result := fixture.RunTestWithBp(t, bp) + foo := result.ModuleForTests("foo", "android_common") + + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+*testCase.targetSdkVersionExpected) + } +} + +func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { + platform_sdk_codename := "Tiramisu" + platform_sdk_version := 33 + testCases := []struct { + name string + enforceDefaultTargetSdkVersion bool + expectedError string + platform_sdk_final bool + targetSdkVersionInBp string + targetSdkVersionExpected string + updatable bool + }{ + { + name: "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion", + enforceDefaultTargetSdkVersion: false, + targetSdkVersionInBp: "29", + targetSdkVersionExpected: "29", + updatable: false, + }, + { + name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion", + enforceDefaultTargetSdkVersion: true, + platform_sdk_final: true, + targetSdkVersionInBp: "current", + targetSdkVersionExpected: "33", + updatable: true, + }, + { + name: "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion", + enforceDefaultTargetSdkVersion: true, + platform_sdk_final: false, + targetSdkVersionInBp: "current", + targetSdkVersionExpected: "10000", + updatable: false, + }, + { + name: "Not enforcing Target SDK Version for Updatable app", + enforceDefaultTargetSdkVersion: false, + expectedError: "Updatable apps must enforce default target sdk version", + targetSdkVersionInBp: "29", + targetSdkVersionExpected: "29", + updatable: true, + }, + } + for _, testCase := range testCases { + errExpected := testCase.expectedError != "" + bp := fmt.Sprintf(` + android_app { + name: "foo", + enforce_default_target_sdk_version: %t, + sdk_version: "current", + min_sdk_version: "29", + target_sdk_version: "%v", + updatable: %t + } + `, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable) + + fixture := android.GroupFixturePreparers( + PrepareForTestWithJavaDefaultModules, + android.PrepareForTestWithAllowMissingDependencies, + android.PrepareForTestWithAndroidMk, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + // explicitly set following platform variables to make the test deterministic + variables.Platform_sdk_final = &testCase.platform_sdk_final + variables.Platform_sdk_version = &platform_sdk_version + variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build_apps = []string{"sampleModule"} + }), + ) + + errorHandler := android.FixtureExpectsNoErrors + if errExpected { + errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError) + } + result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp) + + if !errExpected { + foo := result.ModuleForTests("foo", "android_common") + manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected) + } + } +} + func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) { result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, diff --git a/java/base.go b/java/base.go index 58c16492d..4e7b18c46 100644 --- a/java/base.go +++ b/java/base.go @@ -649,6 +649,10 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { return false } +func (j *Module) setInstrument(value bool) { + j.properties.Instrument = value +} + func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version)) } @@ -783,9 +787,6 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } else if j.shouldInstrumentStatic(ctx) { ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent") } - if j.shouldInstrument(ctx) { - ctx.AddVariationDependencies(nil, libTag, "jacocoagent") - } if j.useCompose() { ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, @@ -880,7 +881,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB epEnabled := j.properties.Errorprone.Enabled if (ctx.Config().RunErrorProne() && epEnabled == nil) || Bool(epEnabled) { - if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil { + if config.ErrorProneClasspath == nil && !ctx.Config().RunningInsideUnitTest() { ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?") } @@ -1414,10 +1415,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.headerJarFile = j.implementationJarFile } - if j.shouldInstrumentInApex(ctx) { - j.properties.Instrument = true - } - // enforce syntax check to jacoco filters for any build (http://b/183622051) specs := j.jacocoModuleToZipCommand(ctx) if ctx.Failed() { @@ -1937,6 +1934,9 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case bootClasspathTag: deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...) case libTag, instrumentationForTag: + if _, ok := module.(*Plugin); ok { + ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a libs dependency", otherName) + } deps.classpath = append(deps.classpath, dep.HeaderJars...) deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...) @@ -1945,6 +1945,9 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case java9LibTag: deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...) case staticLibTag: + if _, ok := module.(*Plugin); ok { + ctx.ModuleErrorf("a java_plugin (%s) cannot be used as a static_libs dependency", otherName) + } deps.classpath = append(deps.classpath, dep.HeaderJars...) deps.staticJars = append(deps.staticJars, dep.ImplementationJars...) deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars...) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index c3053f88d..6bd98d482 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -257,14 +257,14 @@ type commonBootclasspathFragment interface { // Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the // module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a // versioned sdk. - produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput + produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput // produceBootImageFiles will attempt to produce rules to create the boot image files at the paths // predefined in the bootImageConfig. // // If it could not create the files then it will return nil. Otherwise, it will return a map from // android.ArchType to the predefined paths of the boot image files. - produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch + produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs } var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil) @@ -583,23 +583,24 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // Perform hidden API processing. hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) - var bootImageFilesByArch bootImageFilesByArch + var bootImageFiles bootImageOutputs if imageConfig != nil { // Delegate the production of the boot image files to a module type specific method. common := ctx.Module().(commonBootclasspathFragment) - bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig) + bootImageFiles = common.produceBootImageFiles(ctx, imageConfig) if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { // Zip the boot image files up, if available. This will generate the zip file in a // predefined location. - buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch) + buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch) // Copy the dex jars of this fragment's content modules to their predefined locations. copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule) } - for _, variant := range imageConfig.apexVariants() { - arch := variant.target.Arch.ArchType.String() + for _, variant := range bootImageFiles.variants { + archType := variant.config.target.Arch.ArchType + arch := archType.String() for _, install := range variant.deviceInstalls { // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT. installDir := strings.TrimPrefix(filepath.Dir(install.To), "/") @@ -620,7 +621,7 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo // A prebuilt fragment cannot contribute to an apex. if !android.IsModulePrebuilt(ctx.Module()) { // Provide the apex content info. - b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFilesByArch) + b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles) } } else { // Versioned fragments are not needed by make. @@ -663,7 +664,7 @@ func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageCo // provideApexContentInfo creates, initializes and stores the apex content info for use by other // modules. -func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFilesByArch bootImageFilesByArch) { +func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) { // Construct the apex content info from the config. info := BootclasspathFragmentApexContentInfo{ // Populate the apex content info with paths to the dex jars. @@ -674,14 +675,14 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC info.modules = imageConfig.modules global := dexpreopt.GetGlobalConfig(ctx) if !global.DisableGenerateProfile { - info.profilePathOnHost = imageConfig.profilePathOnHost + info.profilePathOnHost = bootImageFiles.profile info.profileInstallPathInApex = imageConfig.profileInstallPathInApex } info.shouldInstallBootImageInApex = imageConfig.shouldInstallInApex() } - info.bootImageFilesByArch = bootImageFilesByArch + info.bootImageFilesByArch = bootImageFiles.byArch // Make the apex content info available for other modules. ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) @@ -761,7 +762,7 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. // Delegate the production of the hidden API all-flags.csv file to a module type specific method. common := ctx.Module().(commonBootclasspathFragment) - output := common.produceHiddenAPIOutput(ctx, contents, input) + output := common.produceHiddenAPIOutput(ctx, contents, fragments, input) // If the source or prebuilts module does not provide a signature patterns file then generate one // from the flags. @@ -769,7 +770,7 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. // their own. if output.SignaturePatternsPath == nil { output.SignaturePatternsPath = buildRuleSignaturePatternsFile( - ctx, output.AllFlagsPath, []string{"*"}, nil, nil) + ctx, output.AllFlagsPath, []string{"*"}, nil, nil, "") } // Initialize a HiddenAPIInfo structure. @@ -840,30 +841,15 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul // isTestFragment returns true if the current module is a test bootclasspath_fragment. func (b *BootclasspathFragmentModule) isTestFragment() bool { - if b.testFragment { - return true - } - - // TODO(b/194063708): Once test fragments all use bootclasspath_fragment_test - // Some temporary exceptions until all test fragments use the - // bootclasspath_fragment_test module type. - name := b.BaseModuleName() - if strings.HasPrefix(name, "test_") { - return true - } - if name == "apex.apexd_test_bootclasspath-fragment" { - return true - } - - return false + return b.testFragment } -// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files) -// for the fragment as well as encoding the flags in the boot dex jars. -func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { +// generateHiddenApiFlagRules generates rules to generate hidden API flags and compute the signature +// patterns file. +func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput { // Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the // paths to the created files. - output := hiddenAPIRulesForBootclasspathFragment(ctx, contents, input) + flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix) // If the module specifies split_packages or package_prefixes then use those to generate the // signature patterns. @@ -871,8 +857,8 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC packagePrefixes := input.PackagePrefixes singlePackages := input.SinglePackages if splitPackages != nil || packagePrefixes != nil || singlePackages != nil { - output.SignaturePatternsPath = buildRuleSignaturePatternsFile( - ctx, output.AllFlagsPath, splitPackages, packagePrefixes, singlePackages) + flagOutput.SignaturePatternsPath = buildRuleSignaturePatternsFile( + ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages, suffix) } else if !b.isTestFragment() { ctx.ModuleErrorf(`Must specify at least one of the split_packages, package_prefixes and single_packages properties If this is a new bootclasspath_fragment or you are unsure what to do add the @@ -884,14 +870,76 @@ func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleC should specify here. If you are happy with its suggestions then you can add the --fix option and it will fix them for you.`, b.BaseModuleName()) } + return flagOutput +} + +// produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files) +// for the fragment as well as encoding the flags in the boot dex jars. +func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { + // Gather information about the boot dex files for the boot libraries provided by this fragment. + bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents) + + // Generate the flag file needed to encode into the dex files. + flagOutput := b.generateHiddenApiFlagRules(ctx, contents, input, bootDexInfoByModule, "") + + // Encode those flags into the dex files of the contents of this fragment. + encodedBootDexFilesByModule := hiddenAPIEncodeRulesForBootclasspathFragment(ctx, bootDexInfoByModule, flagOutput.AllFlagsPath) + + // Store that information for return for use by other rules. + output := &HiddenAPIOutput{ + HiddenAPIFlagOutput: flagOutput, + EncodedBootDexFilesByModule: encodedBootDexFilesByModule, + } + + // Get the ApiLevel associated with SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE, defaulting to current + // if not set. + config := ctx.Config() + targetApiLevel := android.ApiLevelOrPanic(ctx, + config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "current")) + + // Filter the contents list to remove any modules that do not support the target build release. + // The current build release supports all the modules. + contentsForSdkSnapshot := []android.Module{} + for _, module := range contents { + // If the module has a min_sdk_version that is higher than the target build release then it will + // not work on the target build release and so must not be included in the sdk snapshot. + minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module) + if minApiLevel.GreaterThan(targetApiLevel) { + continue + } + + contentsForSdkSnapshot = append(contentsForSdkSnapshot, module) + } + + var flagFilesByCategory FlagFilesByCategory + if len(contentsForSdkSnapshot) != len(contents) { + // The sdk snapshot has different contents to the runtime fragment so it is not possible to + // reuse the hidden API information generated for the fragment. So, recompute that information + // for the sdk snapshot. + filteredInput := b.createHiddenAPIFlagInput(ctx, contentsForSdkSnapshot, fragments) + + // Gather information about the boot dex files for the boot libraries provided by this fragment. + filteredBootDexInfoByModule := extractBootDexInfoFromModules(ctx, contentsForSdkSnapshot) + flagOutput = b.generateHiddenApiFlagRules(ctx, contentsForSdkSnapshot, filteredInput, filteredBootDexInfoByModule, "-for-sdk-snapshot") + flagFilesByCategory = filteredInput.FlagFilesByCategory + } else { + // The sdk snapshot has the same contents as the runtime fragment so reuse that information. + flagFilesByCategory = input.FlagFilesByCategory + } + + // Make the information available for the sdk snapshot. + ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{ + FlagFilesByCategory: flagFilesByCategory, + HiddenAPIFlagOutput: flagOutput, + }) return output } // produceBootImageFiles builds the boot image files from the source if it is required. -func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch { +func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { if SkipDexpreoptBootJars(ctx) { - return nil + return bootImageOutputs{} } // Only generate the boot image if the configuration does not skip it. @@ -903,21 +951,21 @@ func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleCo // // If it could not create the files then it will return nil. Otherwise, it will return a map from // android.ArchType to the predefined paths of the boot image files. -func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch { +func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { global := dexpreopt.GetGlobalConfig(ctx) if !shouldBuildBootImages(ctx.Config(), global) { - return nil + return bootImageOutputs{} } // Bootclasspath fragment modules that are for the platform do not produce a boot image. apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo) if apexInfo.IsForPlatform() { - return nil + return bootImageOutputs{} } // Bootclasspath fragment modules that are versioned do not produce a boot image. if android.IsModuleInVersionedSdk(ctx.Module()) { - return nil + return bootImageOutputs{} } // Build a profile for the image config and then use that to build the boot image. @@ -927,11 +975,11 @@ func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android. buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) // Build boot image files for the android variants. - androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) + bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) // Return the boot image files for the android variants for inclusion in an APEX and to be zipped // up for the dist. - return androidBootImageFilesByArch + return bootImageFiles } func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries { @@ -1049,7 +1097,7 @@ func (b *bootclasspathFragmentSdkMemberProperties) PopulateFromVariant(ctx andro // Get the hidden API information from the module. mctx := ctx.SdkModuleContext() - hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoProvider).(HiddenAPIInfo) + hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk) b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory // Copy all the generated file paths. @@ -1191,7 +1239,7 @@ func (module *PrebuiltBootclasspathFragmentModule) Name() string { } // produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified. -func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { +func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path { if src == nil { return defaultPath @@ -1232,14 +1280,14 @@ func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx an } // produceBootImageFiles extracts the boot image files from the APEX if available. -func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch { +func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs { if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) { - return nil + return bootImageOutputs{} } di := android.FindDeapexerProviderForModule(ctx) if di == nil { - return nil // An error has been reported by FindDeapexerProviderForModule. + return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule. } profile := (android.WritablePath)(nil) @@ -1257,8 +1305,17 @@ func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and // If the boot image files for the android variants are in the prebuilt apex, we must use those // rather than building new ones because those boot image files are going to be used on device. files := bootImageFilesByArch{} + bootImageFiles := bootImageOutputs{ + byArch: files, + profile: profile, + } for _, variant := range imageConfig.apexVariants() { arch := variant.target.Arch.ArchType + bootImageFiles.variants = append(bootImageFiles.variants, bootImageVariantOutputs{ + variant, + // No device installs needed when installed in APEX. + nil, + }) for _, toPath := range variant.imagesDeps { apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base()) // Get the path to the file that the deapexer extracted from the prebuilt apex file. @@ -1276,11 +1333,11 @@ func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx and }) } } - return files + return bootImageFiles } else { if profile == nil { ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex") - return nil + return bootImageOutputs{} } // Build boot image files for the android variants from the dex files provided by the contents // of this module. diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 2bfb255af..2541f14ff 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -96,23 +96,6 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin } func TestBootclasspathFragment_Coverage(t *testing.T) { - prepareForTestWithFrameworkCoverage := android.GroupFixturePreparers( - android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - "EMMA_INSTRUMENT_FRAMEWORK": "true", - }), - // need to mock jacocoagent here to satisfy dependency added for - // instrumented libraries at build time - android.FixtureAddFile("jacocoagent/Android.bp", []byte(` - java_library { - name: "jacocoagent", - srcs: ["Test.java"], - system_modules: "none", - sdk_version: "none", - } - `)), - ) - prepareWithBp := android.FixtureWithRootAndroidBp(` bootclasspath_fragment { name: "myfragment", @@ -191,7 +174,7 @@ func TestBootclasspathFragment_Coverage(t *testing.T) { t.Run("with coverage", func(t *testing.T) { result := android.GroupFixturePreparers( - prepareForTestWithFrameworkCoverage, + prepareForTestWithFrameworkJacocoInstrumentation, preparer, ).RunTest(t) checkContents(t, result, "mybootlib", "coveragelib") @@ -425,22 +408,6 @@ func TestBootclasspathFragment_Test(t *testing.T) { }, } - bootclasspath_fragment { - name: "test_fragment", - contents: ["mysdklibrary"], - hidden_api: { - split_packages: [], - }, - } - - bootclasspath_fragment { - name: "apex.apexd_test_bootclasspath-fragment", - contents: ["mysdklibrary"], - hidden_api: { - split_packages: [], - }, - } - bootclasspath_fragment_test { name: "a_test_fragment", contents: ["mysdklibrary"], @@ -462,12 +429,6 @@ func TestBootclasspathFragment_Test(t *testing.T) { fragment := result.Module("myfragment", "android_common").(*BootclasspathFragmentModule) android.AssertBoolEquals(t, "not a test fragment", false, fragment.isTestFragment()) - fragment = result.Module("test_fragment", "android_common").(*BootclasspathFragmentModule) - android.AssertBoolEquals(t, "is a test fragment by prefix", true, fragment.isTestFragment()) - fragment = result.Module("a_test_fragment", "android_common").(*BootclasspathFragmentModule) android.AssertBoolEquals(t, "is a test fragment by type", true, fragment.isTestFragment()) - - fragment = result.Module("apex.apexd_test_bootclasspath-fragment", "android_common").(*BootclasspathFragmentModule) - android.AssertBoolEquals(t, "is a test fragment by name", true, fragment.isTestFragment()) } diff --git a/java/classpath_element.go b/java/classpath_element.go index 753e7f888..496291678 100644 --- a/java/classpath_element.go +++ b/java/classpath_element.go @@ -97,11 +97,11 @@ type ClasspathElementContext interface { // the list with its Contents field. // // Requirements/Assumptions: -// * A fragment can be associated with more than one apex but each apex must only be associated with -// a single fragment from the fragments list. -// * All of a fragment's contents must appear as a contiguous block in the same order in the -// libraries list. -// * Each library must only appear in a single fragment. +// - A fragment can be associated with more than one apex but each apex must only be associated with +// a single fragment from the fragments list. +// - All of a fragment's contents must appear as a contiguous block in the same order in the +// libraries list. +// - Each library must only appear in a single fragment. // // The apex is used to identify which libraries belong to which fragment. First a mapping is created // from apex to fragment. Then the libraries are iterated over and any library in an apex is @@ -109,13 +109,15 @@ type ClasspathElementContext interface { // standalone and have their own element. // // e.g. Given the following input: -// libraries: com.android.art:core-oj, com.android.art:core-libart, framework, ext -// fragments: com.android.art:art-bootclasspath-fragment +// +// libraries: com.android.art:core-oj, com.android.art:core-libart, framework, ext +// fragments: com.android.art:art-bootclasspath-fragment // // Then this will return: -// ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]), -// ClasspathLibraryElement(framework), -// ClasspathLibraryElement(ext), +// +// ClasspathFragmentElement(art-bootclasspath-fragment, [core-oj, core-libart]), +// ClasspathLibraryElement(framework), +// ClasspathLibraryElement(ext), func CreateClasspathElements(ctx ClasspathElementContext, libraries []android.Module, fragments []android.Module) ClasspathElements { // Create a map from apex name to the fragment module. This makes it easy to find the fragment // associated with a particular apex. diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 3d91aec91..2deb47252 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -234,6 +234,11 @@ func init() { } // Target-independent description of a boot image. +// +// WARNING: All fields in this struct should be initialized in the genBootImageConfigs function. +// Failure to do so can lead to data races if there is no synchronization enforced ordering between +// the writer and the reader. Fields which break this rule are marked as deprecated and should be +// removed and replaced with something else, e.g. providers. type bootImageConfig struct { // If this image is an extension, the image that it extends. extends *bootImageConfig @@ -274,14 +279,15 @@ type bootImageConfig struct { zip android.WritablePath // Rules which should be used in make to install the outputs. + // + // Deprecated: Not initialized correctly, see struct comment. profileInstalls android.RuleBuilderInstalls // Path to the license metadata file for the module that built the profile. + // + // Deprecated: Not initialized correctly, see struct comment. profileLicenseMetadataFile android.OptionalPath - // Path to the image profile file on host (or empty, if profile is not generated). - profilePathOnHost android.Path - // Target-dependent fields. variants []*bootImageVariant @@ -290,6 +296,8 @@ type bootImageConfig struct { } // Target-dependent description of a boot image. +// +// WARNING: The warning comment on bootImageConfig applies here too. type bootImageVariant struct { *bootImageConfig @@ -320,14 +328,23 @@ type bootImageVariant struct { primaryImagesDeps android.Paths // Rules which should be used in make to install the outputs on host. - installs android.RuleBuilderInstalls - vdexInstalls android.RuleBuilderInstalls - unstrippedInstalls android.RuleBuilderInstalls + // + // Deprecated: Not initialized correctly, see struct comment. + installs android.RuleBuilderInstalls - // Rules which should be used in make to install the outputs on device. - deviceInstalls android.RuleBuilderInstalls + // Rules which should be used in make to install the vdex outputs on host. + // + // Deprecated: Not initialized correctly, see struct comment. + vdexInstalls android.RuleBuilderInstalls + + // Rules which should be used in make to install the unstripped outputs on host. + // + // Deprecated: Not initialized correctly, see struct comment. + unstrippedInstalls android.RuleBuilderInstalls // Path to the license metadata file for the module that built the image. + // + // Deprecated: Not initialized correctly, see struct comment. licenseMetadataFile android.OptionalPath } @@ -424,7 +441,6 @@ func (image *bootImageConfig) shouldInstallInApex() bool { // // The location is passed as an argument to the ART tools like dex2oat instead of the real path. // ART tools will then reconstruct the architecture-specific real path. -// func (image *bootImageVariant) imageLocations() (imageLocationsOnHost []string, imageLocationsOnDevice []string) { if image.extends != nil { imageLocationsOnHost, imageLocationsOnDevice = image.extends.getVariant(image.target).imageLocations() @@ -555,7 +571,7 @@ func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJars // boot image files. // // The paths are returned because they are needed elsewhere in Soong, e.g. for populating an APEX. -func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch { +func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageOutputs { return buildBootImageForOsType(ctx, image, profile, android.Android) } @@ -570,21 +586,38 @@ func buildBootImageVariantsForBuildOs(ctx android.ModuleContext, image *bootImag buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS) } +// bootImageOutputs encapsulates information about boot images that were created/obtained by +// commonBootclasspathFragment.produceBootImageFiles. +type bootImageOutputs struct { + // Map from arch to the paths to the boot image files created/obtained for that arch. + byArch bootImageFilesByArch + + variants []bootImageVariantOutputs + + // The path to the profile file created/obtained for the boot image. + profile android.WritablePath +} + // buildBootImageForOsType takes a bootImageConfig, a profile file and an android.OsType // boot image files are required for and it creates rules to build the boot image // files for all the required architectures for them. // // It returns a map from android.ArchType to the predefined paths of the boot image files. -func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageFilesByArch { +func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageOutputs { filesByArch := bootImageFilesByArch{} + imageOutputs := bootImageOutputs{ + byArch: filesByArch, + profile: profile, + } for _, variant := range image.variants { if variant.target.Os == requiredOsType { - buildBootImageVariant(ctx, variant, profile) + variantOutputs := buildBootImageVariant(ctx, variant, profile) + imageOutputs.variants = append(imageOutputs.variants, variantOutputs) filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths() } } - return filesByArch + return imageOutputs } // buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files. @@ -612,8 +645,13 @@ func buildBootImageZipInPredefinedLocation(ctx android.ModuleContext, image *boo rule.Build("zip_"+image.name, "zip "+image.name+" image") } +type bootImageVariantOutputs struct { + config *bootImageVariant + deviceInstalls android.RuleBuilderInstalls +} + // Generate boot image build rules for a specific target. -func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) { +func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs { globalSoong := dexpreopt.GetGlobalSoongConfig(ctx) global := dexpreopt.GetGlobalConfig(ctx) @@ -771,11 +809,20 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p rule.Build(image.name+"JarsDexpreopt_"+image.target.String(), "dexpreopt "+image.name+" jars "+arch.String()) // save output and installed files for makevars + // TODO - these are always the same and so should be initialized in genBootImageConfigs image.installs = rule.Installs() image.vdexInstalls = vdexInstalls image.unstrippedInstalls = unstrippedInstalls - image.deviceInstalls = deviceInstalls - image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) + + // Only set the licenseMetadataFile from the active module. + if isActiveModule(ctx.Module()) { + image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile()) + } + + return bootImageVariantOutputs{ + image, + deviceInstalls, + } } const failureMessage = `ERROR: Dex2oat failed to compile a boot image. @@ -829,8 +876,6 @@ func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) and rule.Build("bootJarsProfile", "profile boot jars") - image.profilePathOnHost = profile - return profile } diff --git a/java/dexpreopt_config_test.go b/java/dexpreopt_config_test.go new file mode 100644 index 000000000..b704d09d2 --- /dev/null +++ b/java/dexpreopt_config_test.go @@ -0,0 +1,35 @@ +// Copyright 2022 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 java + +import ( + "runtime" + "testing" + + "android/soong/android" +) + +func TestBootImageConfig(t *testing.T) { + if runtime.GOOS != "linux" { + t.Skipf("Skipping as boot image config test is only supported on linux not %s", runtime.GOOS) + } + + result := android.GroupFixturePreparers( + PrepareForBootImageConfigTest, + ).RunTest(t) + + CheckArtBootImageConfig(t, result) + CheckFrameworkBootImageConfig(t, result) +} diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go new file mode 100644 index 000000000..1c236d8af --- /dev/null +++ b/java/dexpreopt_config_testing.go @@ -0,0 +1,768 @@ +// Copyright 2022 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. + +// Testing support for dexpreopt config. +// +// The bootImageConfig/bootImageVariant structs returned by genBootImageConfigs are used in many +// places in the build and are currently mutated in a number of those locations. This provides +// comprehensive tests of the fields in those structs to ensure that they have been initialized +// correctly and where relevant, mutated correctly. +// +// This is used in TestBootImageConfig to verify that the + +package java + +import ( + "fmt" + "strings" + "testing" + + "android/soong/android" +) + +// PrepareForBootImageConfigTest is the minimal set of preparers that are needed to be able to use +// the Check*BootImageConfig methods define here. +var PrepareForBootImageConfigTest = android.GroupFixturePreparers( + android.PrepareForTestWithArchMutator, + android.PrepareForTestAccessingMakeVars, + FixtureConfigureBootJars("com.android.art:core1", "com.android.art:core2", "platform:framework"), +) + +// normalizedInstall represents a android.RuleBuilderInstall that has been normalized to remove +// test specific parts of the From path. +type normalizedInstall struct { + from string + to string +} + +// normalizeInstalls converts a slice of android.RuleBuilderInstall into a slice of +// normalizedInstall to allow them to be compared using android.AssertDeepEquals. +func normalizeInstalls(installs android.RuleBuilderInstalls) []normalizedInstall { + var normalized []normalizedInstall + for _, install := range installs { + normalized = append(normalized, normalizedInstall{ + from: install.From.RelativeToTop().String(), + to: install.To, + }) + } + return normalized +} + +// assertInstallsEqual normalized the android.RuleBuilderInstalls and compares against the expected +// normalizedInstalls. +func assertInstallsEqual(t *testing.T, message string, expected []normalizedInstall, actual android.RuleBuilderInstalls) { + t.Helper() + normalizedActual := normalizeInstalls(actual) + android.AssertDeepEquals(t, message, expected, normalizedActual) +} + +// expectedConfig encapsulates the expected properties that will be set in a bootImageConfig +// +// Each field <x> in here is compared against the corresponding field <x> in bootImageConfig. +type expectedConfig struct { + name string + stem string + dir string + symbolsDir string + installDirOnDevice string + installDirOnHost string + profileInstallPathInApex string + modules android.ConfiguredJarList + dexPaths []string + dexPathsDeps []string + zip string + variants []*expectedVariant + + // Mutated fields + profileInstalls []normalizedInstall + profileLicenseMetadataFile string +} + +// expectedVariant encapsulates the expected properties that will be set in a bootImageVariant +// +// Each field <x> in here is compared against the corresponding field <x> in bootImageVariant +// except for archType which is compared against the target.Arch.ArchType field in bootImageVariant. +type expectedVariant struct { + archType android.ArchType + dexLocations []string + dexLocationsDeps []string + imagePathOnHost string + imagePathOnDevice string + imagesDeps []string + primaryImages string + primaryImagesDeps []string + + // Mutated fields + installs []normalizedInstall + vdexInstalls []normalizedInstall + unstrippedInstalls []normalizedInstall + licenseMetadataFile string +} + +// CheckArtBootImageConfig checks the status of the fields of the bootImageConfig and +// bootImageVariant structures that are returned from artBootImageConfig. +// +// This is before any fields are mutated. +func CheckArtBootImageConfig(t *testing.T, result *android.TestResult) { + checkArtBootImageConfig(t, result, false, "") +} + +// getArtImageConfig gets the ART bootImageConfig that was created during the test. +func getArtImageConfig(result *android.TestResult) *bootImageConfig { + pathCtx := &android.TestPathContext{TestResult: result} + imageConfig := artBootImageConfig(pathCtx) + return imageConfig +} + +// checkArtBootImageConfig checks the ART boot image. +// +// mutated is true if this is called after fields in the image have been mutated by the ART +// bootclasspath_fragment and false otherwise. +func checkArtBootImageConfig(t *testing.T, result *android.TestResult, mutated bool, expectedLicenseMetadataFile string) { + imageConfig := getArtImageConfig(result) + + expected := &expectedConfig{ + name: "art", + stem: "boot", + dir: "out/soong/test_device/dex_artjars", + symbolsDir: "out/soong/test_device/dex_artjars_unstripped", + installDirOnDevice: "system/framework", + installDirOnHost: "apex/art_boot_images/javalib", + profileInstallPathInApex: "etc/boot-image.prof", + modules: android.CreateTestConfiguredJarList([]string{"com.android.art:core1", "com.android.art:core2"}), + dexPaths: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar"}, + dexPathsDeps: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar"}, + zip: "out/soong/test_device/dex_artjars/art.zip", + variants: []*expectedVariant{ + { + archType: android.Arm64, + dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"}, + dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"}, + imagePathOnHost: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", + imagePathOnDevice: "/system/framework/arm64/boot.art", + imagesDeps: []string{ + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", + to: "/apex/art_boot_images/javalib/arm64/boot.art", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat", + to: "/apex/art_boot_images/javalib/arm64/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art", + to: "/apex/art_boot_images/javalib/arm64/boot-core2.art", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat", + to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex", + to: "/apex/art_boot_images/javalib/arm64/boot.vdex", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex", + to: "/apex/art_boot_images/javalib/arm64/boot-core2.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat", + to: "/apex/art_boot_images/javalib/arm64/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat", + to: "/apex/art_boot_images/javalib/arm64/boot-core2.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.Arm, + dexLocations: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"}, + dexLocationsDeps: []string{"/apex/com.android.art/javalib/core1.jar", "/apex/com.android.art/javalib/core2.jar"}, + imagePathOnHost: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art", + imagePathOnDevice: "/system/framework/arm/boot.art", + imagesDeps: []string{ + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art", + to: "/apex/art_boot_images/javalib/arm/boot.art", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat", + to: "/apex/art_boot_images/javalib/arm/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art", + to: "/apex/art_boot_images/javalib/arm/boot-core2.art", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat", + to: "/apex/art_boot_images/javalib/arm/boot-core2.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex", + to: "/apex/art_boot_images/javalib/arm/boot.vdex", + }, + { + from: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex", + to: "/apex/art_boot_images/javalib/arm/boot-core2.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat", + to: "/apex/art_boot_images/javalib/arm/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat", + to: "/apex/art_boot_images/javalib/arm/boot-core2.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.X86_64, + dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"}, + dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"}, + imagePathOnHost: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art", + imagePathOnDevice: "/system/framework/x86_64/boot.art", + imagesDeps: []string{ + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art", + to: "/apex/art_boot_images/javalib/x86_64/boot.art", + }, { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat", + to: "/apex/art_boot_images/javalib/x86_64/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art", + to: "/apex/art_boot_images/javalib/x86_64/boot-core2.art", + }, { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex", + to: "/apex/art_boot_images/javalib/x86_64/boot.vdex", + }, + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex", + to: "/apex/art_boot_images/javalib/x86_64/boot-core2.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat", + to: "/apex/art_boot_images/javalib/x86_64/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + to: "/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.X86, + dexLocations: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"}, + dexLocationsDeps: []string{"host/linux-x86/apex/com.android.art/javalib/core1.jar", "host/linux-x86/apex/com.android.art/javalib/core2.jar"}, + imagePathOnHost: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art", + imagePathOnDevice: "/system/framework/x86/boot.art", + imagesDeps: []string{ + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art", + to: "/apex/art_boot_images/javalib/x86/boot.art", + }, { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat", + to: "/apex/art_boot_images/javalib/x86/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art", + to: "/apex/art_boot_images/javalib/x86/boot-core2.art", + }, { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat", + to: "/apex/art_boot_images/javalib/x86/boot-core2.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex", + to: "/apex/art_boot_images/javalib/x86/boot.vdex", + }, + { + from: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex", + to: "/apex/art_boot_images/javalib/x86/boot-core2.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat", + to: "/apex/art_boot_images/javalib/x86/boot.oat", + }, + { + from: "out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat", + to: "/apex/art_boot_images/javalib/x86/boot-core2.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + }, + } + + checkBootImageConfig(t, imageConfig, mutated, expected) +} + +// getFrameworkImageConfig gets the framework bootImageConfig that was created during the test. +func getFrameworkImageConfig(result *android.TestResult) *bootImageConfig { + pathCtx := &android.TestPathContext{TestResult: result} + imageConfig := defaultBootImageConfig(pathCtx) + return imageConfig +} + +// CheckFrameworkBootImageConfig checks the status of the fields of the bootImageConfig and +// bootImageVariant structures that are returned from defaultBootImageConfig. +// +// This is before any fields are mutated. +func CheckFrameworkBootImageConfig(t *testing.T, result *android.TestResult) { + checkFrameworkBootImageConfig(t, result, false, "") +} + +// checkFrameworkBootImageConfig checks the framework boot image. +// +// mutated is true if this is called after fields in the image have been mutated by the +// platform_bootclasspath and false otherwise. +func checkFrameworkBootImageConfig(t *testing.T, result *android.TestResult, mutated bool, expectedLicenseMetadataFile string) { + imageConfig := getFrameworkImageConfig(result) + + expected := &expectedConfig{ + name: "boot", + stem: "boot", + dir: "out/soong/test_device/dex_bootjars", + symbolsDir: "out/soong/test_device/dex_bootjars_unstripped", + installDirOnDevice: "system/framework", + installDirOnHost: "system/framework", + profileInstallPathInApex: "", + modules: android.CreateTestConfiguredJarList([]string{"platform:framework"}), + dexPaths: []string{"out/soong/test_device/dex_bootjars_input/framework.jar"}, + dexPathsDeps: []string{"out/soong/test_device/dex_artjars_input/core1.jar", "out/soong/test_device/dex_artjars_input/core2.jar", "out/soong/test_device/dex_bootjars_input/framework.jar"}, + zip: "out/soong/test_device/dex_bootjars/boot.zip", + variants: []*expectedVariant{ + { + archType: android.Arm64, + dexLocations: []string{"/system/framework/framework.jar"}, + dexLocationsDeps: []string{ + "/apex/com.android.art/javalib/core1.jar", + "/apex/com.android.art/javalib/core2.jar", + "/system/framework/framework.jar", + }, + imagePathOnHost: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art", + imagePathOnDevice: "/system/framework/arm64/boot-framework.art", + imagesDeps: []string{ + "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art", + "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat", + "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex", + }, + primaryImages: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", + primaryImagesDeps: []string{ + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art", + to: "/system/framework/arm64/boot-framework.art", + }, + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat", + to: "/system/framework/arm64/boot-framework.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex", + to: "/system/framework/arm64/boot-framework.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat", + to: "/system/framework/arm64/boot-framework.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.Arm, + dexLocations: []string{"/system/framework/framework.jar"}, + dexLocationsDeps: []string{ + "/apex/com.android.art/javalib/core1.jar", + "/apex/com.android.art/javalib/core2.jar", + "/system/framework/framework.jar", + }, + imagePathOnHost: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art", + imagePathOnDevice: "/system/framework/arm/boot-framework.art", + imagesDeps: []string{ + "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art", + "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat", + "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex", + }, + primaryImages: "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art", + primaryImagesDeps: []string{ + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat", + "out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art", + to: "/system/framework/arm/boot-framework.art", + }, + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat", + to: "/system/framework/arm/boot-framework.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex", + to: "/system/framework/arm/boot-framework.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat", + to: "/system/framework/arm/boot-framework.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.X86_64, + dexLocations: []string{"host/linux-x86/system/framework/framework.jar"}, + dexLocationsDeps: []string{ + "host/linux-x86/apex/com.android.art/javalib/core1.jar", + "host/linux-x86/apex/com.android.art/javalib/core2.jar", + "host/linux-x86/system/framework/framework.jar", + }, + imagePathOnHost: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art", + imagePathOnDevice: "/system/framework/x86_64/boot-framework.art", + imagesDeps: []string{ + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art", + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat", + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex", + }, + primaryImages: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art", + primaryImagesDeps: []string{ + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art", + to: "/system/framework/x86_64/boot-framework.art", + }, + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat", + to: "/system/framework/x86_64/boot-framework.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex", + to: "/system/framework/x86_64/boot-framework.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat", + to: "/system/framework/x86_64/boot-framework.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + { + archType: android.X86, + dexLocations: []string{"host/linux-x86/system/framework/framework.jar"}, + dexLocationsDeps: []string{ + "host/linux-x86/apex/com.android.art/javalib/core1.jar", + "host/linux-x86/apex/com.android.art/javalib/core2.jar", + "host/linux-x86/system/framework/framework.jar", + }, + imagePathOnHost: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art", + imagePathOnDevice: "/system/framework/x86/boot-framework.art", + imagesDeps: []string{ + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art", + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat", + "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex", + }, + primaryImages: "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art", + primaryImagesDeps: []string{ + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat", + "out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex", + }, + installs: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art", + to: "/system/framework/x86/boot-framework.art", + }, + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat", + to: "/system/framework/x86/boot-framework.oat", + }, + }, + vdexInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex", + to: "/system/framework/x86/boot-framework.vdex", + }, + }, + unstrippedInstalls: []normalizedInstall{ + { + from: "out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat", + to: "/system/framework/x86/boot-framework.oat", + }, + }, + licenseMetadataFile: expectedLicenseMetadataFile, + }, + }, + profileInstalls: []normalizedInstall{ + {from: "out/soong/test_device/dex_bootjars/boot.bprof", to: "/system/etc/boot-image.bprof"}, + {from: "out/soong/test_device/dex_bootjars/boot.prof", to: "/system/etc/boot-image.prof"}, + }, + profileLicenseMetadataFile: expectedLicenseMetadataFile, + } + + checkBootImageConfig(t, imageConfig, mutated, expected) +} + +// clearMutatedFields clears fields in the expectedConfig that correspond to fields in the +// bootImageConfig/bootImageVariant structs which are mutated outside the call to +// genBootImageConfigs. +// +// This allows the resulting expectedConfig struct to be compared against the values of those boot +// image structs immediately the call to genBootImageConfigs. If this is not called then the +// expectedConfig struct will expect the boot image structs to have been mutated by the ART +// bootclasspath_fragment and the platform_bootclasspath. +func clearMutatedFields(expected *expectedConfig) { + expected.profileInstalls = nil + expected.profileLicenseMetadataFile = "" + for _, variant := range expected.variants { + variant.installs = nil + variant.vdexInstalls = nil + variant.unstrippedInstalls = nil + variant.licenseMetadataFile = "" + } +} + +// checkBootImageConfig checks a boot image against the expected contents. +// +// If mutated is false then this will clear any mutated fields in the expected contents back to the +// zero value so that they will match the unmodified values in the boot image. +// +// It runs the checks in an image specific subtest of the current test. +func checkBootImageConfig(t *testing.T, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) { + if !mutated { + clearMutatedFields(expected) + } + + t.Run(imageConfig.name, func(t *testing.T) { + nestedCheckBootImageConfig(t, imageConfig, expected) + }) +} + +// nestedCheckBootImageConfig does the work of comparing the image against the expected values and +// is run in an image specific subtest. +func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expected *expectedConfig) { + android.AssertStringEquals(t, "name", expected.name, imageConfig.name) + android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem) + android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir) + android.AssertPathRelativeToTopEquals(t, "symbolsDir", expected.symbolsDir, imageConfig.symbolsDir) + android.AssertStringEquals(t, "installDirOnDevice", expected.installDirOnDevice, imageConfig.installDirOnDevice) + android.AssertStringEquals(t, "installDirOnHost", expected.installDirOnHost, imageConfig.installDirOnHost) + android.AssertStringEquals(t, "profileInstallPathInApex", expected.profileInstallPathInApex, imageConfig.profileInstallPathInApex) + android.AssertDeepEquals(t, "modules", expected.modules, imageConfig.modules) + android.AssertPathsRelativeToTopEquals(t, "dexPaths", expected.dexPaths, imageConfig.dexPaths.Paths()) + android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths()) + // dexPathsByModule is just a different representation of the other information in the config. + android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip) + assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, imageConfig.profileInstalls) + android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, imageConfig.profileLicenseMetadataFile.RelativeToTop().String()) + + android.AssertIntEquals(t, "variant count", 4, len(imageConfig.variants)) + for i, variant := range imageConfig.variants { + expectedVariant := expected.variants[i] + t.Run(variant.target.Arch.ArchType.String(), func(t *testing.T) { + android.AssertDeepEquals(t, "archType", expectedVariant.archType, variant.target.Arch.ArchType) + android.AssertDeepEquals(t, "dexLocations", expectedVariant.dexLocations, variant.dexLocations) + android.AssertDeepEquals(t, "dexLocationsDeps", expectedVariant.dexLocationsDeps, variant.dexLocationsDeps) + android.AssertPathRelativeToTopEquals(t, "imagePathOnHost", expectedVariant.imagePathOnHost, variant.imagePathOnHost) + android.AssertStringEquals(t, "imagePathOnDevice", expectedVariant.imagePathOnDevice, variant.imagePathOnDevice) + android.AssertPathsRelativeToTopEquals(t, "imagesDeps", expectedVariant.imagesDeps, variant.imagesDeps.Paths()) + android.AssertPathRelativeToTopEquals(t, "primaryImages", expectedVariant.primaryImages, variant.primaryImages) + android.AssertPathsRelativeToTopEquals(t, "primaryImagesDeps", expectedVariant.primaryImagesDeps, variant.primaryImagesDeps) + assertInstallsEqual(t, "installs", expectedVariant.installs, variant.installs) + assertInstallsEqual(t, "vdexInstalls", expectedVariant.vdexInstalls, variant.vdexInstalls) + assertInstallsEqual(t, "unstrippedInstalls", expectedVariant.unstrippedInstalls, variant.unstrippedInstalls) + android.AssertStringEquals(t, "licenseMetadataFile", expectedVariant.licenseMetadataFile, variant.licenseMetadataFile.RelativeToTop().String()) + }) + } +} + +// CheckMutatedArtBootImageConfig checks the mutated fields in the bootImageConfig/Variant for ART. +func CheckMutatedArtBootImageConfig(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) { + checkArtBootImageConfig(t, result, true, expectedLicenseMetadataFile) + + // Check the dexpreopt make vars. Do it in here as it depends on the expected license metadata + // file at the moment and it + checkDexpreoptMakeVars(t, result, expectedLicenseMetadataFile) +} + +// CheckMutatedFrameworkBootImageConfig checks the mutated fields in the bootImageConfig/Variant for framework. +func CheckMutatedFrameworkBootImageConfig(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) { + checkFrameworkBootImageConfig(t, result, true, expectedLicenseMetadataFile) +} + +// checkDexpreoptMakeVars checks the DEXPREOPT_ prefixed make vars produced by dexpreoptBootJars +// singleton. +func checkDexpreoptMakeVars(t *testing.T, result *android.TestResult, expectedLicenseMetadataFile string) { + vars := result.MakeVarsForTesting(func(variable android.MakeVarVariable) bool { + return strings.HasPrefix(variable.Name(), "DEXPREOPT_") + }) + + out := &strings.Builder{} + for _, v := range vars { + fmt.Fprintf(out, "%s=%s\n", v.Name(), android.StringRelativeToTop(result.Config, v.Value())) + } + format := ` +DEXPREOPT_BOOTCLASSPATH_DEX_FILES=out/soong/test_device/dex_artjars_input/core1.jar out/soong/test_device/dex_artjars_input/core2.jar out/soong/test_device/dex_bootjars_input/framework.jar +DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS=/apex/com.android.art/javalib/core1.jar /apex/com.android.art/javalib/core2.jar /system/framework/framework.jar +DEXPREOPT_BOOT_JARS_MODULES=platform:framework +DEXPREOPT_GEN=out/host/linux-x86/bin/dexpreopt_gen +DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art:/apex/art_boot_images/javalib/arm/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art:/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art:/apex/art_boot_images/javalib/arm64/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art:/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art:/apex/art_boot_images/javalib/x86/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art:/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art:/apex/art_boot_images/javalib/x86_64/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art:/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art:/system/framework/arm/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art:/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art:/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat +DEXPREOPT_IMAGE_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art:/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat +DEXPREOPT_IMAGE_DEPS_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex +DEXPREOPT_IMAGE_DEPS_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.art out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.oat out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex +DEXPREOPT_IMAGE_DEPS_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex +DEXPREOPT_IMAGE_DEPS_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.art out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex +DEXPREOPT_IMAGE_DEPS_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.oat out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex +DEXPREOPT_IMAGE_DEPS_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.oat out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex +DEXPREOPT_IMAGE_DEPS_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex +DEXPREOPT_IMAGE_DEPS_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.oat out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex +DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm=%[1]s +DEXPREOPT_IMAGE_LICENSE_METADATA_art_arm64=%[1]s +DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86=%[1]s +DEXPREOPT_IMAGE_LICENSE_METADATA_art_host_x86_64=%[1]s +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_arm64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_LICENSE_METADATA_boot_host_x86_64=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEart=/system/framework/boot.art +DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICEboot=/system/framework/boot.art:/system/framework/boot-framework.art +DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTart=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art +DEXPREOPT_IMAGE_LOCATIONS_ON_HOSTboot=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/boot.art:out/soong/test_device/dex_bootjars/android/system/framework/boot-framework.art +DEXPREOPT_IMAGE_NAMES=art boot +DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED=out/soong/test_device/dex_bootjars/boot.bprof:/system/etc/boot-image.bprof out/soong/test_device/dex_bootjars/boot.prof:/system/etc/boot-image.prof +DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA=out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot.oat:/apex/art_boot_images/javalib/arm/boot.oat out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm/boot-core2.oat:/apex/art_boot_images/javalib/arm/boot-core2.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot.oat:/apex/art_boot_images/javalib/arm64/boot.oat out/soong/test_device/dex_artjars_unstripped/android/apex/art_boot_images/javalib/arm64/boot-core2.oat:/apex/art_boot_images/javalib/arm64/boot-core2.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot.oat:/apex/art_boot_images/javalib/x86/boot.oat out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.oat:/apex/art_boot_images/javalib/x86/boot-core2.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.oat:/apex/art_boot_images/javalib/x86_64/boot.oat out/soong/test_device/dex_artjars_unstripped/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.oat:/apex/art_boot_images/javalib/x86_64/boot-core2.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm/boot-framework.oat:/system/framework/arm/boot-framework.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars_unstripped/android/system/framework/arm64/boot-framework.oat:/system/framework/arm64/boot-framework.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86/boot-framework.oat:/system/framework/x86/boot-framework.oat +DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars_unstripped/linux_glibc/system/framework/x86_64/boot-framework.oat:/system/framework/x86_64/boot-framework.oat +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.vdex:/apex/art_boot_images/javalib/arm/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot-core2.vdex:/apex/art_boot_images/javalib/arm/boot-core2.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.vdex:/apex/art_boot_images/javalib/arm64/boot.vdex out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot-core2.vdex:/apex/art_boot_images/javalib/arm64/boot-core2.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.vdex:/apex/art_boot_images/javalib/x86/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot-core2.vdex:/apex/art_boot_images/javalib/x86/boot-core2.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.vdex:/apex/art_boot_images/javalib/x86_64/boot.vdex out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot-core2.vdex:/apex/art_boot_images/javalib/x86_64/boot-core2.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.vdex:/system/framework/arm/boot-framework.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.vdex:/system/framework/arm64/boot-framework.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.vdex:/system/framework/x86/boot-framework.vdex +DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.vdex:/system/framework/x86_64/boot-framework.vdex +DEXPREOPT_IMAGE_ZIP_art=out/soong/test_device/dex_artjars/art.zip +DEXPREOPT_IMAGE_ZIP_boot=out/soong/test_device/dex_bootjars/boot.zip +DEXPREOPT_IMAGE_art_arm=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm/boot.art +DEXPREOPT_IMAGE_art_arm64=out/soong/test_device/dex_artjars/android/apex/art_boot_images/javalib/arm64/boot.art +DEXPREOPT_IMAGE_art_host_x86=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86/boot.art +DEXPREOPT_IMAGE_art_host_x86_64=out/soong/test_device/dex_artjars/linux_glibc/apex/art_boot_images/javalib/x86_64/boot.art +DEXPREOPT_IMAGE_boot_arm=out/soong/test_device/dex_bootjars/android/system/framework/arm/boot-framework.art +DEXPREOPT_IMAGE_boot_arm64=out/soong/test_device/dex_bootjars/android/system/framework/arm64/boot-framework.art +DEXPREOPT_IMAGE_boot_host_x86=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86/boot-framework.art +DEXPREOPT_IMAGE_boot_host_x86_64=out/soong/test_device/dex_bootjars/linux_glibc/system/framework/x86_64/boot-framework.art +` + expected := strings.TrimSpace(fmt.Sprintf(format, expectedLicenseMetadataFile)) + actual := strings.TrimSpace(out.String()) + android.AssertStringEquals(t, "vars", expected, actual) +} diff --git a/java/droiddoc.go b/java/droiddoc.go index 023d61912..c1182652f 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -158,9 +158,7 @@ type DroiddocProperties struct { Compat_config *string `android:"path"` } -// // Common flags passed down to build rule -// type droiddocBuilderFlags struct { bootClasspathArgs string classpathArgs string @@ -193,9 +191,7 @@ func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersio return false } -// // Javadoc -// type Javadoc struct { android.ModuleBase android.DefaultableModuleBase @@ -544,9 +540,7 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("javadoc", "javadoc") } -// // Droiddoc -// type Droiddoc struct { Javadoc @@ -823,9 +817,7 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { rule.Build("javadoc", desc) } -// // Exported Droiddoc Directory -// var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"} type ExportedDroiddocDirProperties struct { @@ -858,9 +850,7 @@ func (d *ExportedDroiddocDir) GenerateAndroidBuildActions(ctx android.ModuleCont d.deps = android.PathsForModuleSrc(ctx, []string{filepath.Join(path, "**/*")}) } -// // Defaults -// type DocDefaults struct { android.ModuleBase android.DefaultsModuleBase diff --git a/java/droidstubs.go b/java/droidstubs.go index d705a4d6b..ec554ac89 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -42,9 +42,7 @@ func RegisterStubsBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory) } -// // Droidstubs -// type Droidstubs struct { Javadoc android.SdkBase diff --git a/java/genrule.go b/java/genrule.go index 5047c412f..208e1f43b 100644 --- a/java/genrule.go +++ b/java/genrule.go @@ -43,23 +43,23 @@ func RegisterGenRuleBuildComponents(ctx android.RegistrationContext) { // // Use a java_genrule to package generated java resources: // -// java_genrule { -// name: "generated_resources", -// tools: [ -// "generator", -// "soong_zip", -// ], -// srcs: ["generator_inputs/**/*"], -// out: ["generated_android_icu4j_resources.jar"], -// cmd: "$(location generator) $(in) -o $(genDir) " + -// "&& $(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res", -// } +// java_genrule { +// name: "generated_resources", +// tools: [ +// "generator", +// "soong_zip", +// ], +// srcs: ["generator_inputs/**/*"], +// out: ["generated_android_icu4j_resources.jar"], +// cmd: "$(location generator) $(in) -o $(genDir) " + +// "&& $(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res", +// } // -// java_library { -// name: "lib_with_generated_resources", -// srcs: ["src/**/*.java"], -// static_libs: ["generated_resources"], -// } +// java_library { +// name: "lib_with_generated_resources", +// srcs: ["src/**/*.java"], +// static_libs: ["generated_resources"], +// } func GenRuleFactory() android.Module { module := genrule.NewGenRule() diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index 7b678037c..5474ae11e 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -594,6 +594,23 @@ func (i *HiddenAPIInfo) FlagSubset() SignatureCsvSubset { var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{}) +// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use +// by the sdk snapshot. +// +// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API +// processing. +type HiddenAPIInfoForSdk struct { + // FlagFilesByCategory maps from the flag file category to the paths containing information for + // that category. + FlagFilesByCategory FlagFilesByCategory + + // The output from the hidden API processing needs to be made available to other modules. + HiddenAPIFlagOutput +} + +// Provides hidden API info for the sdk snapshot. +var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{}) + // ModuleStubDexJars contains the stub dex jars provided by a single module. // // It maps a *HiddenAPIScope to the path to stub dex jars appropriate for that scope. See @@ -1024,8 +1041,11 @@ func (s SignatureCsvSubsets) RelativeToTop() []string { // patterns that will select a subset of the monolithic flags. func buildRuleSignaturePatternsFile( ctx android.ModuleContext, flagsPath android.Path, - splitPackages []string, packagePrefixes []string, singlePackages []string) android.Path { - patternsFile := android.PathForModuleOut(ctx, "modular-hiddenapi", "signature-patterns.csv") + splitPackages []string, packagePrefixes []string, singlePackages []string, + suffix string) android.Path { + hiddenApiSubDir := "modular-hiddenapi" + suffix + + patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv") // Create a rule to validate the output from the following rule. rule := android.NewRuleBuilder(pctx, ctx) @@ -1042,7 +1062,7 @@ func buildRuleSignaturePatternsFile( FlagForEachArg("--package-prefix ", packagePrefixes). FlagForEachArg("--single-package ", singlePackages). FlagWithOutput("--output ", patternsFile) - rule.Build("hiddenAPISignaturePatterns", "hidden API signature patterns") + rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix) return patternsFile } @@ -1116,8 +1136,8 @@ func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name strin return validFile } -// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the -// bootclasspath and then encode the flags into the boot dex files. +// hiddenAPIFlagRulesForBootclasspathFragment will generate all the flags for a fragment of the +// bootclasspath. // // It takes: // * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind. @@ -1130,31 +1150,27 @@ func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name strin // * metadata.csv // * index.csv // * all-flags.csv -// * encoded boot dex files -func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { - hiddenApiSubDir := "modular-hiddenapi" - - // Gather information about the boot dex files for the boot libraries provided by this fragment. - bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents) +func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput { + hiddenApiSubDir := "modular-hiddenapi" + suffix // Generate the stub-flags.csv. stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv") - buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil) + buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil) // Extract the classes jars from the contents. classesJars := extractClassesJarsFromModules(contents) // Generate the set of flags from the annotations in the source code. annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv") - buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV) + buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV) // Generate the metadata from the annotations in the source code. metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv") - buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV) + buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV) // Generate the index file from the CSV files in the classes jars. indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv") - buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV) + buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV) // Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files // containing dex signatures of all the removed APIs. In the monolithic files that is done by @@ -1162,59 +1178,60 @@ func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents // signatures, see the combined-removed-dex module. This does that automatically by using the // *removed.txt files retrieved from the java_sdk_library modules that are specified in the // stub_libs and contents properties of a bootclasspath_fragment. - removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles) + removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles) // Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex // files. allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv") - buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures) - - // Encode the flags into the boot dex files. - encodedBootDexJarsByModule := map[string]android.Path{} - outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath - for _, name := range android.SortedStringKeys(bootDexInfoByModule) { - bootDexInfo := bootDexInfoByModule[name] - unencodedDex := bootDexInfo.path - encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir) - encodedBootDexJarsByModule[name] = encodedDex - } + buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures) // Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be // compared against the monolithic stub flags. filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv") - buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags", - "modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV, + buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix, + "modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV, HIDDENAPI_STUB_FLAGS_IMPL_FLAGS) // Generate the filtered-flags.csv file which contains the filtered flags that will be compared // against the monolithic flags. filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv") - buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags", - "modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV, + buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix, + "modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV, HIDDENAPI_FLAGS_CSV_IMPL_FLAGS) // Store the paths in the info for use by other modules and sdk snapshot generation. - output := HiddenAPIOutput{ - HiddenAPIFlagOutput: HiddenAPIFlagOutput{ - AnnotationFlagsPath: annotationFlagsCSV, - MetadataPath: metadataCSV, - IndexPath: indexCSV, - StubFlagsPath: stubFlagsCSV, - AllFlagsPath: allFlagsCSV, - FilteredStubFlagsPath: filteredStubFlagsCSV, - FilteredFlagsPath: filteredFlagsCSV, - }, - EncodedBootDexFilesByModule: encodedBootDexJarsByModule, + return HiddenAPIFlagOutput{ + AnnotationFlagsPath: annotationFlagsCSV, + MetadataPath: metadataCSV, + IndexPath: indexCSV, + StubFlagsPath: stubFlagsCSV, + AllFlagsPath: allFlagsCSV, + FilteredStubFlagsPath: filteredStubFlagsCSV, + FilteredFlagsPath: filteredFlagsCSV, + } +} + +// hiddenAPIEncodeRulesForBootclasspathFragment generates rules to encode hidden API flags into the +// dex jars in bootDexInfoByModule. +func hiddenAPIEncodeRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, allFlagsCSV android.Path) bootDexJarByModule { + // Encode the flags into the boot dex files. + encodedBootDexJarsByModule := bootDexJarByModule{} + outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath + for _, name := range android.SortedStringKeys(bootDexInfoByModule) { + bootDexInfo := bootDexInfoByModule[name] + unencodedDex := bootDexInfo.path + encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, bootDexInfo.minSdkVersion, outputDir) + encodedBootDexJarsByModule[name] = encodedDex } - return &output + return encodedBootDexJarsByModule } -func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath { +func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath { if len(removedTxtFiles) == 0 { return android.OptionalPath{} } - output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt") + output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt") rule := android.NewRuleBuilder(pctx, ctx) rule.Command(). @@ -1222,7 +1239,7 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedT Flag("--no-banner"). Inputs(removedTxtFiles). FlagWithOutput("--dex-api ", output) - rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures") + rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix) return android.OptionalPathForPath(output) } diff --git a/java/jacoco.go b/java/jacoco.go index e11c2ce69..f8012b852 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -47,6 +47,34 @@ var ( "strippedJar", "stripSpec", "tmpDir", "tmpJar") ) +func jacocoDepsMutator(ctx android.BottomUpMutatorContext) { + type instrumentable interface { + shouldInstrument(ctx android.BaseModuleContext) bool + shouldInstrumentInApex(ctx android.BaseModuleContext) bool + setInstrument(value bool) + } + + j, ok := ctx.Module().(instrumentable) + if !ctx.Module().Enabled() || !ok { + return + } + + if j.shouldInstrumentInApex(ctx) { + j.setInstrument(true) + } + + if j.shouldInstrument(ctx) && ctx.ModuleName() != "jacocoagent" { + // We can use AddFarVariationDependencies here because, since this dep + // is added as libs only (i.e. a compiletime CLASSPATH entry only), + // the first variant of jacocoagent is sufficient to prevent + // compile time errors. + // At this stage in the build, AddVariationDependencies is not always + // able to procure a variant of jacocoagent that matches the calling + // module. + ctx.AddFarVariationDependencies(ctx.Module().Target().Variations(), libTag, "jacocoagent") + } +} + // Instruments a jar using the Jacoco command line interface. Uses stripSpec to extract a subset // of the classes in inputJar into strippedJar, instruments strippedJar into tmpJar, and then // combines the classes in tmpJar with inputJar (preferring the instrumented classes in tmpJar) diff --git a/java/java.go b/java/java.go index f98f1e88c..e46712349 100644 --- a/java/java.go +++ b/java/java.go @@ -65,6 +65,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { // to support the checks in dexpreoptDisabled(). ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel() + // needs access to ApexInfoProvider which is available after variant creation + ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel() }) ctx.RegisterSingletonType("logtags", LogtagsSingleton) diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 24f8253ae..f0de7a4d8 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -436,10 +436,10 @@ func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android. profile := bootImageProfileRule(ctx, imageConfig) // Build boot image files for the android variants. - androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) + androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile) // Zip the android variant boot image files up. - buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFilesByArch) + buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch) // Build boot image files for the host variants. There are use directly by ART host side tests. buildBootImageVariantsForBuildOs(ctx, imageConfig, profile) diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go index 1c4249507..655021fc4 100644 --- a/java/platform_compat_config.go +++ b/java/platform_compat_config.go @@ -280,7 +280,7 @@ func platformCompatConfigSingletonFactory() android.Singleton { return &platformCompatConfigSingleton{} } -//============== merged_compat_config ================= +// ============== merged_compat_config ================= type globalCompatConfigProperties struct { // name of the file into which the metadata will be copied. Filename *string diff --git a/java/rro.go b/java/rro.go index c98cbbd2d..b136e3f0d 100644 --- a/java/rro.go +++ b/java/rro.go @@ -142,7 +142,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC aaptLinkFlags = append(aaptLinkFlags, "--rename-overlay-target-package "+*r.overridableProperties.Target_package_name) } - r.aapt.buildActions(ctx, r, nil, nil, aaptLinkFlags...) + r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...) // Sign the built package _, certificates := collectAppDeps(ctx, r, false, false) diff --git a/java/sdk_library.go b/java/sdk_library.go index 591e90f99..a2fc04482 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -65,8 +65,27 @@ type apiScope struct { name string // The api scope that this scope extends. + // + // This organizes the scopes into an extension hierarchy. + // + // If set this means that the API provided by this scope includes the API provided by the scope + // set in this field. extends *apiScope + // The next api scope that a library that uses this scope can access. + // + // This organizes the scopes into an access hierarchy. + // + // If set this means that a library that can access this API can also access the API provided by + // the scope set in this field. + // + // A module that sets sdk_version: "<scope>_current" should have access to the <scope> API of + // every java_sdk_library that it depends on. If the library does not provide an API for <scope> + // then it will traverse up this access hierarchy to find an API that it does provide. + // + // If this is not set then it defaults to the scope set in extends. + canAccess *apiScope + // The legacy enabled status for a specific scope can be dependent on other // properties that have been specified on the library so it is provided by // a function that can determine the status by examining those properties. @@ -107,7 +126,7 @@ type apiScope struct { // The scope specific prefix to add to the api file base of "current.txt" or "removed.txt". apiFilePrefix string - // The scope specific prefix to add to the sdk library module name to construct a scope specific + // The scope specific suffix to add to the sdk library module name to construct a scope specific // module name. moduleSuffix string @@ -193,6 +212,11 @@ func initApiScope(scope *apiScope) *apiScope { } } + // By default, a library that can access a scope can also access the scope it extends. + if scope.canAccess == nil { + scope.canAccess = scope.extends + } + // Escape any special characters in the arguments. This is needed because droidstubs // passes these directly to the shell command. scope.droidstubsArgs = proptools.ShellEscapeList(scopeSpecificArgs) @@ -310,6 +334,14 @@ var ( apiScopeSystemServer = initApiScope(&apiScope{ name: "system-server", extends: apiScopePublic, + + // The system-server scope can access the module-lib scope. + // + // A module that provides a system-server API is appended to the standard bootclasspath that is + // used by the system server. So, it should be able to access module-lib APIs provided by + // libraries on the bootclasspath. + canAccess: apiScopeModuleLib, + // The system-server scope is disabled by default in legacy mode. // // Enabling this would break existing usages. @@ -539,7 +571,7 @@ type sdkLibraryProperties struct { } // TODO: determines whether to create HTML doc or not - //Html_doc *bool + // Html_doc *bool } // Paths to outputs from java_sdk_library and java_sdk_library_import. @@ -926,7 +958,7 @@ func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePath // If this does not support the requested api scope then find the closest available // scope it does support. Returns nil if no such scope is available. func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths { - for s := scope; s != nil; s = s.extends { + for s := scope; s != nil; s = s.canAccess { if paths := c.findScopePaths(s); paths != nil { return paths } @@ -1354,7 +1386,7 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) // Provide additional information for inclusion in an sdk's generated .info file. additionalSdkInfo := map[string]interface{}{} additionalSdkInfo["dist_stem"] = module.distStem() - baseModuleName := module.BaseModuleName() + baseModuleName := module.distStem() scopes := map[string]interface{}{} additionalSdkInfo["scopes"] = scopes for scope, scopePaths := range module.scopePaths { @@ -2129,11 +2161,12 @@ var _ SdkLibraryDependency = (*SdkLibraryImport)(nil) // The type of a structure that contains a field of type sdkLibraryScopeProperties // for each apiscope in allApiScopes, e.g. something like: -// struct { -// Public sdkLibraryScopeProperties -// System sdkLibraryScopeProperties -// ... -// } +// +// struct { +// Public sdkLibraryScopeProperties +// System sdkLibraryScopeProperties +// ... +// } var allScopeStructType = createAllScopePropertiesStructType() // Dynamically create a structure type for each apiscope in allApiScopes. @@ -2235,8 +2268,9 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl Sdk_version *string Libs []string Jars []string - Prefer *bool Compile_dex *bool + + android.UserSuppliedPrebuiltProperties }{} props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope)) props.Sdk_version = scopeProperties.Sdk_version @@ -2246,7 +2280,7 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl props.Jars = scopeProperties.Jars // The imports are preferred if the java_sdk_library_import is preferred. - props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) + props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) // The imports need to be compiled to dex if the java_sdk_library_import requests it. compileDex := module.properties.Compile_dex @@ -2260,16 +2294,18 @@ func (module *SdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl func (module *SdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { props := struct { - Name *string - Srcs []string - Prefer *bool + Name *string + Srcs []string + + android.UserSuppliedPrebuiltProperties }{} props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope)) props.Srcs = scopeProperties.Stub_srcs - mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) // The stubs source is preferred if the java_sdk_library_import is preferred. - props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) + props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt) + + mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) } // Add the dependencies on the child module in the component deps mutator so that it @@ -2556,9 +2592,7 @@ func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseMo return requiredFilesFromPrebuiltApexForImport(name) } -// // java_sdk_library_xml -// type sdkLibraryXml struct { android.ModuleBase android.DefaultableModuleBase @@ -2905,6 +2939,18 @@ var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{ type sdkLibrarySdkMemberProperties struct { android.SdkMemberPropertiesBase + // Stem name for files in the sdk snapshot. + // + // This is used to construct the path names of various sdk library files in the sdk snapshot to + // make sure that they match the finalized versions of those files in prebuilts/sdk. + // + // This property is marked as keep so that it will be kept in all instances of this struct, will + // not be cleared but will be copied to common structs. That is needed because this field is used + // to construct many file names for other parts of this struct and so it needs to be present in + // all structs. If it was not marked as keep then it would be cleared in some structs and so would + // be unavailable for generating file names if there were other properties that were still set. + Stem string `sdk:"keep"` + // Scope to per scope properties. Scopes map[*apiScope]*scopeProperties @@ -2966,6 +3012,9 @@ type scopeProperties struct { func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { sdk := variant.(*SdkLibrary) + // Copy the stem name for files in the sdk snapshot. + s.Stem = sdk.distStem() + s.Scopes = make(map[*apiScope]*scopeProperties) for _, apiScope := range allApiScopes { paths := sdk.findScopePaths(apiScope) @@ -3018,6 +3067,8 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo propertySet.AddProperty("permitted_packages", s.Permitted_packages) } + stem := s.Stem + for _, apiScope := range allApiScopes { if properties, ok := s.Scopes[apiScope]; ok { scopeSet := propertySet.AddPropertySet(apiScope.propertyName) @@ -3026,7 +3077,7 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo var jars []string for _, p := range properties.Jars { - dest := filepath.Join(scopeDir, ctx.Name()+"-stubs.jar") + dest := filepath.Join(scopeDir, stem+"-stubs.jar") ctx.SnapshotBuilder().CopyToSnapshot(p, dest) jars = append(jars, dest) } @@ -3034,31 +3085,31 @@ func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberCo if ctx.SdkModuleContext().Config().IsEnvTrue("SOONG_SDK_SNAPSHOT_USE_SRCJAR") { // Copy the stubs source jar into the snapshot zip as is. - srcJarSnapshotPath := filepath.Join(scopeDir, ctx.Name()+".srcjar") + srcJarSnapshotPath := filepath.Join(scopeDir, stem+".srcjar") ctx.SnapshotBuilder().CopyToSnapshot(properties.StubsSrcJar, srcJarSnapshotPath) scopeSet.AddProperty("stub_srcs", []string{srcJarSnapshotPath}) } else { // Merge the stubs source jar into the snapshot zip so that when it is unpacked // the source files are also unpacked. - snapshotRelativeDir := filepath.Join(scopeDir, ctx.Name()+"_stub_sources") + snapshotRelativeDir := filepath.Join(scopeDir, stem+"_stub_sources") ctx.SnapshotBuilder().UnzipToSnapshot(properties.StubsSrcJar, snapshotRelativeDir) scopeSet.AddProperty("stub_srcs", []string{snapshotRelativeDir}) } if properties.CurrentApiFile != nil { - currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(ctx.Name()) + currentApiSnapshotPath := apiScope.snapshotRelativeCurrentApiTxtPath(stem) ctx.SnapshotBuilder().CopyToSnapshot(properties.CurrentApiFile, currentApiSnapshotPath) scopeSet.AddProperty("current_api", currentApiSnapshotPath) } if properties.RemovedApiFile != nil { - removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(ctx.Name()) + removedApiSnapshotPath := apiScope.snapshotRelativeRemovedApiTxtPath(stem) ctx.SnapshotBuilder().CopyToSnapshot(properties.RemovedApiFile, removedApiSnapshotPath) scopeSet.AddProperty("removed_api", removedApiSnapshotPath) } if properties.AnnotationsZip != nil { - annotationsSnapshotPath := filepath.Join(scopeDir, ctx.Name()+"_annotations.zip") + annotationsSnapshotPath := filepath.Join(scopeDir, stem+"_annotations.zip") ctx.SnapshotBuilder().CopyToSnapshot(properties.AnnotationsZip, annotationsSnapshotPath) scopeSet.AddProperty("annotations", annotationsSnapshotPath) } diff --git a/java/sdk_library_external.go b/java/sdk_library_external.go index 0acaa13b2..4f8398194 100644 --- a/java/sdk_library_external.go +++ b/java/sdk_library_external.go @@ -49,9 +49,10 @@ func (g partitionGroup) String() string { // Get partition group of java module that can be used at inter-partition dependency check. // We currently have three groups -// (system, system_ext) => system partition group -// (vendor, odm) => vendor partition group -// (product) => product partition group +// +// (system, system_ext) => system partition group +// (vendor, odm) => vendor partition group +// (product) => product partition group func (j *Module) partitionGroup(ctx android.EarlyModuleContext) partitionGroup { // system and system_ext partition can be treated as the same in terms of inter-partition dependency. if j.Platform() || j.SystemExtSpecific() { diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go index 805bc226f..096bca8a1 100644 --- a/java/sdk_library_test.go +++ b/java/sdk_library_test.go @@ -18,6 +18,7 @@ import ( "fmt" "path/filepath" "regexp" + "strings" "testing" "android/soong/android" @@ -699,6 +700,80 @@ func TestJavaSdkLibrary_SystemServer(t *testing.T) { `) } +func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("foo-public", "foo-system", "foo-module-lib", "foo-system-server"), + ).RunTestWithBp(t, ` + java_sdk_library { + name: "foo-public", + srcs: ["a.java"], + api_packages: ["foo"], + public: { + enabled: true, + }, + } + + java_sdk_library { + name: "foo-system", + srcs: ["a.java"], + api_packages: ["foo"], + system: { + enabled: true, + }, + } + + java_sdk_library { + name: "foo-module-lib", + srcs: ["a.java"], + api_packages: ["foo"], + system: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + } + + java_sdk_library { + name: "foo-system-server", + srcs: ["a.java"], + api_packages: ["foo"], + system_server: { + enabled: true, + }, + } + + java_library { + name: "bar", + srcs: ["a.java"], + libs: ["foo-public", "foo-system", "foo-module-lib", "foo-system-server"], + sdk_version: "system_server_current", + } + `) + + stubsPath := func(name string, scope *apiScope) string { + name = scope.stubsLibraryModuleName(name) + return fmt.Sprintf("out/soong/.intermediates/%[1]s/android_common/turbine-combined/%[1]s.jar", name) + } + + // The bar library should depend on the highest (where system server is highest and public is + // lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the + // foo-<x> module is <x>. + barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac") + stubLibraries := []string{ + stubsPath("foo-public", apiScopePublic), + stubsPath("foo-system", apiScopeSystem), + stubsPath("foo-module-lib", apiScopeModuleLib), + stubsPath("foo-system-server", apiScopeSystemServer), + } + expectedPattern := fmt.Sprintf(`^-classpath .*:\Q%s\E$`, strings.Join(stubLibraries, ":")) + if expected, actual := expectedPattern, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) { + t.Errorf("expected pattern %q to match %#q", expected, actual) + } +} + func TestJavaSdkLibrary_MissingScope(t *testing.T) { prepareForJavaTest. ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)). @@ -875,11 +950,12 @@ func TestJavaSdkLibraryImport_WithSource(t *testing.T) { }) } -func TestJavaSdkLibraryImport_Preferred(t *testing.T) { +func testJavaSdkLibraryImport_Preferred(t *testing.T, prefer string, preparer android.FixturePreparer) { result := android.GroupFixturePreparers( prepareForJavaTest, PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("sdklib"), + preparer, ).RunTestWithBp(t, ` java_sdk_library { name: "sdklib", @@ -893,11 +969,37 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { java_sdk_library_import { name: "sdklib", - prefer: true, + `+prefer+` public: { jars: ["a.jar"], + stub_srcs: ["a.java"], + current_api: "current.txt", + removed_api: "removed.txt", + annotations: "annotations.zip", }, } + + java_library { + name: "combined", + static_libs: [ + "sdklib.stubs", + ], + java_resources: [ + ":sdklib.stubs.source", + ":sdklib{.public.api.txt}", + ":sdklib{.public.removed-api.txt}", + ":sdklib{.public.annotations.zip}", + ], + sdk_version: "none", + system_modules: "none", + } + + java_library { + name: "public", + srcs: ["a.java"], + libs: ["sdklib"], + sdk_version: "current", + } `) CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{ @@ -913,9 +1015,48 @@ func TestJavaSdkLibraryImport_Preferred(t *testing.T) { CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{ `dex2oatd`, `prebuilt_sdklib.stubs`, + `prebuilt_sdklib.stubs.source`, `sdklib.impl`, `sdklib.xml`, }) + + // Make sure that dependencies on child modules use the prebuilt when preferred. + CheckModuleDependencies(t, result.TestContext, "combined", "android_common", []string{ + // Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib. + `prebuilt_sdklib`, + `prebuilt_sdklib`, + `prebuilt_sdklib`, + `prebuilt_sdklib.stubs`, + `prebuilt_sdklib.stubs.source`, + }) + + // Make sure that dependencies on sdklib that resolve to one of the child libraries use the + // prebuilt library. + public := result.ModuleForTests("public", "android_common") + rule := public.Output("javac/public.jar") + inputs := rule.Implicits.Strings() + expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar" + if !android.InList(expected, inputs) { + t.Errorf("expected %q to contain %q", inputs, expected) + } +} + +func TestJavaSdkLibraryImport_Preferred(t *testing.T) { + t.Run("prefer", func(t *testing.T) { + testJavaSdkLibraryImport_Preferred(t, "prefer: true,", android.NullFixturePreparer) + }) + + t.Run("use_source_config_var", func(t *testing.T) { + testJavaSdkLibraryImport_Preferred(t, + "use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"},", + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.VendorVars = map[string]map[string]string{ + "acme": { + "use_source": "false", + }, + } + })) + }) } func TestJavaSdkLibraryEnforce(t *testing.T) { diff --git a/java/testing.go b/java/testing.go index 511cc5ddb..49430ee05 100644 --- a/java/testing.go +++ b/java/testing.go @@ -59,11 +59,9 @@ var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers( }.AddToFixture(), ) -// Test fixture preparer that will define all default java modules except the -// fake_tool_binary for dex2oatd. -var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers( - // Make sure that all the module types used in the defaults are registered. - PrepareForTestWithJavaBuildComponents, +var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers( + // The java default module definitions. + android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), // Additional files needed when test disallows non-existent source. android.MockFS{ // Needed for framework-res @@ -77,8 +75,14 @@ var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixtu "build/make/core/proguard.flags": nil, "build/make/core/proguard_basic_keeps.flags": nil, }.AddToFixture(), - // The java default module definitions. - android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), +) + +// Test fixture preparer that will define all default java modules except the +// fake_tool_binary for dex2oatd. +var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers( + // Make sure that all the module types used in the defaults are registered. + PrepareForTestWithJavaBuildComponents, + prepareForTestWithFrameworkDeps, // Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module. dexpreopt.PrepareForTestWithDexpreoptCompatLibs, ) @@ -141,6 +145,30 @@ var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string "30": {}, }) +var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers( + android.FixtureMergeEnv(map[string]string{ + "EMMA_INSTRUMENT_FRAMEWORK": "true", + }), + PrepareForTestWithJacocoInstrumentation, +) + +// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be +// depended on as part of the build process for instrumented Java modules. +var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers( + android.FixtureMergeEnv(map[string]string{ + "EMMA_INSTRUMENT": "true", + }), + android.FixtureAddFile("jacocoagent/Test.java", nil), + android.FixtureAddFile("jacocoagent/Android.bp", []byte(` + java_library { + name: "jacocoagent", + host_supported: true, + srcs: ["Test.java"], + sdk_version: "current", + } + `)), +) + // FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the // specified releases and modules. // @@ -365,6 +393,7 @@ func gatherRequiredDepsForTest() string { aidl: { export_include_dirs: ["framework/aidl"], }, + compile_dex: true, } android_app { diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go index 8f4fea4b1..8dc014928 100644 --- a/mk2rbc/mk2rbc.go +++ b/mk2rbc/mk2rbc.go @@ -14,13 +14,13 @@ // Convert makefile containing device configuration to Starlark file // The conversion can handle the following constructs in a makefile: -// * comments -// * simple variable assignments -// * $(call init-product,<file>) -// * $(call inherit-product-if-exists -// * if directives -// All other constructs are carried over to the output starlark file as comments. +// - comments +// - simple variable assignments +// - $(call init-product,<file>) +// - $(call inherit-product-if-exists +// - if directives // +// All other constructs are carried over to the output starlark file as comments. package mk2rbc import ( diff --git a/mk2rbc/soong_variables.go b/mk2rbc/soong_variables.go index de4692528..a52ec4f2a 100644 --- a/mk2rbc/soong_variables.go +++ b/mk2rbc/soong_variables.go @@ -32,8 +32,8 @@ type context struct { // Scans the makefile Soong uses to generate soong.variables file, // collecting variable names and types from the lines that look like this: -// $(call add_json_XXX, <...>, $(VAR)) // +// $(call add_json_XXX, <...>, $(VAR)) func FindSoongVariables(mkFile string, includeFileScope mkparser.Scope, registrar variableRegistrar) error { ctx := context{includeFileScope, registrar} return ctx.doFind(mkFile) diff --git a/python/python.go b/python/python.go index b100cc318..548510842 100644 --- a/python/python.go +++ b/python/python.go @@ -387,9 +387,9 @@ func (p *Module) anySrcHasExt(ctx android.BottomUpMutatorContext, ext string) bo } // DepsMutator mutates dependencies for this module: -// * handles proto dependencies, -// * if required, specifies launcher and adds launcher dependencies, -// * applies python version mutations to Python dependencies +// - handles proto dependencies, +// - if required, specifies launcher and adds launcher dependencies, +// - applies python version mutations to Python dependencies func (p *Module) DepsMutator(ctx android.BottomUpMutatorContext) { android.ProtoDeps(ctx, &p.protoProperties) diff --git a/rust/config/Android.bp b/rust/config/Android.bp index 7757c79fc..e07d39b06 100644 --- a/rust/config/Android.bp +++ b/rust/config/Android.bp @@ -14,6 +14,7 @@ bootstrap_go_package { "arm64_device.go", "global.go", "lints.go", + "riscv64_device.go", "toolchain.go", "allowed_list.go", "darwin_host.go", diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go new file mode 100644 index 000000000..d014dbf8b --- /dev/null +++ b/rust/config/riscv64_device.go @@ -0,0 +1,91 @@ +// Copyright 2022 The Android Open Source Project +// +// 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 config + +import ( + "strings" + + "android/soong/android" +) + +var ( + Riscv64RustFlags = []string{} + Riscv64ArchFeatureRustFlags = map[string][]string{"": {}} + Riscv64LinkFlags = []string{} + + Riscv64ArchVariantRustFlags = map[string][]string{"": {}} +) + +func init() { + registerToolchainFactory(android.Android, android.Riscv64, Riscv64ToolchainFactory) + + pctx.StaticVariable("Riscv64ToolchainRustFlags", strings.Join(Riscv64RustFlags, " ")) + pctx.StaticVariable("Riscv64ToolchainLinkFlags", strings.Join(Riscv64LinkFlags, " ")) + + for variant, rustFlags := range Riscv64ArchVariantRustFlags { + pctx.StaticVariable("Riscv64"+variant+"VariantRustFlags", + strings.Join(rustFlags, " ")) + } + +} + +type toolchainRiscv64 struct { + toolchain64Bit + toolchainRustFlags string +} + +func (t *toolchainRiscv64) RustTriple() string { + return "riscv64-linux-android" +} + +func (t *toolchainRiscv64) ToolchainLinkFlags() string { + // Prepend the lld flags from cc_config so we stay in sync with cc + return "${config.DeviceGlobalLinkFlags} ${cc_config.Riscv64Lldflags} ${config.Riscv64ToolchainLinkFlags}" +} + +func (t *toolchainRiscv64) ToolchainRustFlags() string { + return t.toolchainRustFlags +} + +func (t *toolchainRiscv64) RustFlags() string { + return "${config.Riscv64ToolchainRustFlags}" +} + +func (t *toolchainRiscv64) Supported() bool { + return true +} + +func (toolchainRiscv64) LibclangRuntimeLibraryArch() string { + return "riscv64" +} + +func Riscv64ToolchainFactory(arch android.Arch) Toolchain { + archVariant := arch.ArchVariant + + toolchainRustFlags := []string{ + "${config.Riscv64ToolchainRustFlags}", + "${config.Riscv64" + archVariant + "VariantRustFlags}", + } + + toolchainRustFlags = append(toolchainRustFlags, deviceGlobalRustFlags...) + + for _, feature := range arch.ArchFeatures { + toolchainRustFlags = append(toolchainRustFlags, Riscv64ArchFeatureRustFlags[feature]...) + } + + return &toolchainRiscv64{ + toolchainRustFlags: strings.Join(toolchainRustFlags, " "), + } +} diff --git a/scripts/build_broken_logs.go b/scripts/build_broken_logs.go index 82ba7491e..bb4b9fdd9 100644 --- a/scripts/build_broken_logs.go +++ b/scripts/build_broken_logs.go @@ -19,12 +19,12 @@ // To use, download the logs.zip from one or more branches, and extract them // into subdirectories of the current directory. So for example, I have: // -// ./aosp-master/aosp_arm/std_full.log -// ./aosp-master/aosp_arm64/std_full.log -// ./aosp-master/... -// ./internal-master/aosp_arm/std_full.log -// ./internal-master/aosp_arm64/std_full.log -// ./internal-master/... +// ./aosp-master/aosp_arm/std_full.log +// ./aosp-master/aosp_arm64/std_full.log +// ./aosp-master/... +// ./internal-master/aosp_arm/std_full.log +// ./internal-master/aosp_arm64/std_full.log +// ./internal-master/... // // Then I use `go run path/to/build_broken_logs.go *` package main diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go index c93055a51..1b64130ce 100644 --- a/sdk/bootclasspath_fragment_sdk_test.go +++ b/sdk/bootclasspath_fragment_sdk_test.go @@ -17,6 +17,7 @@ package sdk import ( "fmt" "path/filepath" + "strings" "testing" "android/soong/android" @@ -80,7 +81,7 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { // Add a platform_bootclasspath that depends on the fragment. fixtureAddPlatformBootclasspathForBootclasspathFragment("com.android.art", "mybootclasspathfragment"), - java.FixtureConfigureBootJars("com.android.art:mybootlib"), + java.PrepareForBootImageConfigTest, android.FixtureWithRootAndroidBp(` sdk { name: "mysdk", @@ -99,7 +100,7 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { bootclasspath_fragment { name: "mybootclasspathfragment", image_name: "art", - contents: ["mybootlib"], + contents: ["core1", "core2"], apex_available: ["com.android.art"], hidden_api: { split_packages: ["*"], @@ -113,19 +114,32 @@ func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) { } java_library { - name: "mybootlib", + name: "core1", srcs: ["Test.java"], system_modules: "none", sdk_version: "none", compile_dex: true, apex_available: ["com.android.art"], } - `), + + java_library { + name: "core2", + srcs: ["Test.java"], + system_modules: "none", + sdk_version: "none", + compile_dex: true, + apex_available: ["com.android.art"], + } +`), ).RunTest(t) // A preparer to update the test fixture used when processing an unpackage snapshot. preparerForSnapshot := fixtureAddPrebuiltApexForBootclasspathFragment("com.android.art", "mybootclasspathfragment") + // Check that source on its own configures the bootImageConfig correctly. + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + CheckSnapshot(t, result, "mysdk", "", checkAndroidBpContents(` // This is auto-generated. DO NOT EDIT. @@ -136,7 +150,10 @@ prebuilt_bootclasspath_fragment { visibility: ["//visibility:public"], apex_available: ["com.android.art"], image_name: "art", - contents: ["mybootlib"], + contents: [ + "core1", + "core2", + ], hidden_api: { annotation_flags: "hiddenapi/annotation-flags.csv", metadata: "hiddenapi/metadata.csv", @@ -148,11 +165,19 @@ prebuilt_bootclasspath_fragment { } java_import { - name: "mybootlib", + name: "core1", prefer: false, visibility: ["//visibility:public"], apex_available: ["com.android.art"], - jars: ["java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar"], + jars: ["java_boot_libs/snapshot/jars/are/invalid/core1.jar"], +} + +java_import { + name: "core2", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["com.android.art"], + jars: ["java_boot_libs/snapshot/jars/are/invalid/core2.jar"], } `), checkAllCopyRules(` @@ -162,31 +187,54 @@ java_import { .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv .intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv -.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar +.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core1.jar +.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/core2.jar `), snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot), // Check the behavior of the snapshot without the source. snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) { - // Make sure that the boot jars package check rule includes the dex jar retrieved from the prebuilt apex. - checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/mybootlib.jar") + // Make sure that the boot jars package check rule includes the dex jars retrieved from the prebuilt apex. + checkBootJarsPackageCheckRule(t, result, + "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar", + "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar", + "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar") + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/mybootclasspathfragment/android_common_com.android.art/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") }), snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot), + + // Check the behavior of the snapshot when the source is preferred. + snapshotTestChecker(checkSnapshotWithSourcePreferred, func(t *testing.T, result *android.TestResult) { + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + }), + snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), + + // Check the behavior of the snapshot when it is preferred. + snapshotTestChecker(checkSnapshotPreferredWithSource, func(t *testing.T, result *android.TestResult) { + java.CheckMutatedArtBootImageConfig(t, result, "out/soong/.intermediates/snapshot/prebuilt_mybootclasspathfragment/android_common_com.android.art/meta_lic") + java.CheckMutatedFrameworkBootImageConfig(t, result, "out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/meta_lic") + }), ) - // Make sure that the boot jars package check rule includes the dex jar created from the source. - checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/mybootlib/android_common_apex10000/aligned/mybootlib.jar") + // Make sure that the boot jars package check rule includes the dex jars created from the source. + checkBootJarsPackageCheckRule(t, result, + "out/soong/.intermediates/core1/android_common_apex10000/aligned/core1.jar", + "out/soong/.intermediates/core2/android_common_apex10000/aligned/core2.jar", + "out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar") } // checkBootJarsPackageCheckRule checks that the supplied module is an input to the boot jars // package check rule. -func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModule string) { +func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModules ...string) { + t.Helper() platformBcp := result.ModuleForTests("platform-bootclasspath", "android_common") bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check") command := bootJarsCheckRule.RuleParams.Command - expectedCommandArgs := " out/soong/host/linux-x86/bin/dexdump build/soong/scripts/check_boot_jars/package_allowed_list.txt " + expectedModule + " &&" + expectedCommandArgs := " build/soong/scripts/check_boot_jars/package_allowed_list.txt " + strings.Join(expectedModules, " ") + " &&" android.AssertStringDoesContain(t, "boot jars package check", command, expectedCommandArgs) } @@ -895,3 +943,222 @@ my-unsupported-packages.txt -> hiddenapi/my-unsupported-packages.txt snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot), ) } + +func testSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T, targetBuildRelease string, + expectedSdkSnapshot string, + expectedCopyRules string, + expectedStubFlagsInputs []string, + suffix string) { + + result := android.GroupFixturePreparers( + prepareForSdkTestWithJava, + java.PrepareForTestWithJavaDefaultModules, + java.PrepareForTestWithJavaSdkLibraryFiles, + java.FixtureWithLastReleaseApis("mysdklibrary", "mynewsdklibrary"), + java.FixtureConfigureApexBootJars("myapex:mysdklibrary", "myapex:mynewsdklibrary"), + prepareForSdkTestWithApex, + + // Add a platform_bootclasspath that depends on the fragment. + fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"), + + android.FixtureMergeEnv(map[string]string{ + "SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease, + }), + + android.FixtureWithRootAndroidBp(` + sdk { + name: "mysdk", + apexes: ["myapex"], + } + + apex { + name: "myapex", + key: "myapex.key", + min_sdk_version: "S", + bootclasspath_fragments: ["mybootclasspathfragment"], + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + apex_available: ["myapex"], + contents: [ + "mysdklibrary", + "mynewsdklibrary", + ], + + hidden_api: { + split_packages: [], + }, + } + + java_sdk_library { + name: "mysdklibrary", + apex_available: ["myapex"], + srcs: ["Test.java"], + shared_library: false, + public: {enabled: true}, + min_sdk_version: "S", + } + + java_sdk_library { + name: "mynewsdklibrary", + apex_available: ["myapex"], + srcs: ["Test.java"], + compile_dex: true, + public: {enabled: true}, + min_sdk_version: "Tiramisu", + permitted_packages: ["mynewsdklibrary"], + } + `), + ).RunTest(t) + + bcpf := result.ModuleForTests("mybootclasspathfragment", "android_common") + rule := bcpf.Output("out/soong/.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi" + suffix + "/stub-flags.csv") + android.AssertPathsRelativeToTopEquals(t, "stub flags inputs", expectedStubFlagsInputs, rule.Implicits) + + CheckSnapshot(t, result, "mysdk", "", + checkAndroidBpContents(expectedSdkSnapshot), + checkAllCopyRules(expectedCopyRules), + ) +} + +func TestSnapshotWithBootClasspathFragment_MinSdkVersion(t *testing.T) { + t.Run("target S build", func(t *testing.T) { + expectedSnapshot := ` +// This is auto-generated. DO NOT EDIT. + +prebuilt_bootclasspath_fragment { + name: "mybootclasspathfragment", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + contents: ["mysdklibrary"], + 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_sdk_library_import { + name: "mysdklibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + shared_library: false, + public: { + jars: ["sdk_library/public/mysdklibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"], + current_api: "sdk_library/public/mysdklibrary.txt", + removed_api: "sdk_library/public/mysdklibrary-removed.txt", + sdk_version: "current", + }, +} +` + expectedCopyRules := ` +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/annotation-flags.csv -> hiddenapi/annotation-flags.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/metadata.csv -> hiddenapi/metadata.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/index.csv -> hiddenapi/index.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/stub-flags.csv -> hiddenapi/stub-flags.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/all-flags.csv -> hiddenapi/all-flags.csv +.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt +` + + // On S the stub flags should only be generated from mysdklibrary as mynewsdklibrary is not part + // of the snapshot. + expectedStubFlagsInputs := []string{ + "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar", + "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar", + } + + testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "S", + expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "-for-sdk-snapshot") + }) + + t.Run("target-Tiramisu-build", func(t *testing.T) { + expectedSnapshot := ` +// This is auto-generated. DO NOT EDIT. + +prebuilt_bootclasspath_fragment { + name: "mybootclasspathfragment", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + contents: [ + "mysdklibrary", + "mynewsdklibrary", + ], + hidden_api: { + annotation_flags: "hiddenapi/annotation-flags.csv", + metadata: "hiddenapi/metadata.csv", + index: "hiddenapi/index.csv", + signature_patterns: "hiddenapi/signature-patterns.csv", + filtered_stub_flags: "hiddenapi/filtered-stub-flags.csv", + filtered_flags: "hiddenapi/filtered-flags.csv", + }, +} + +java_sdk_library_import { + name: "mysdklibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + shared_library: false, + public: { + jars: ["sdk_library/public/mysdklibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"], + current_api: "sdk_library/public/mysdklibrary.txt", + removed_api: "sdk_library/public/mysdklibrary-removed.txt", + sdk_version: "current", + }, +} + +java_sdk_library_import { + name: "mynewsdklibrary", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["myapex"], + shared_library: true, + compile_dex: true, + permitted_packages: ["mynewsdklibrary"], + public: { + jars: ["sdk_library/public/mynewsdklibrary-stubs.jar"], + stub_srcs: ["sdk_library/public/mynewsdklibrary_stub_sources"], + current_api: "sdk_library/public/mynewsdklibrary.txt", + removed_api: "sdk_library/public/mynewsdklibrary-removed.txt", + sdk_version: "current", + }, +} +` + expectedCopyRules := ` +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv -> hiddenapi/annotation-flags.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/metadata.csv -> hiddenapi/metadata.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/index.csv -> hiddenapi/index.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv +.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv +.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt +.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt +.intermediates/mynewsdklibrary.stubs/android_common/javac/mynewsdklibrary.stubs.jar -> sdk_library/public/mynewsdklibrary-stubs.jar +.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt +.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt +` + + // On tiramisu the stub flags should be generated from both mynewsdklibrary and mysdklibrary as + // they are both part of the snapshot. + expectedStubFlagsInputs := []string{ + "out/soong/.intermediates/mynewsdklibrary.stubs/android_common/dex/mynewsdklibrary.stubs.jar", + "out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar", + "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar", + "out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar", + } + + testSnapshotWithBootClasspathFragment_MinSdkVersion(t, "Tiramisu", + expectedSnapshot, expectedCopyRules, expectedStubFlagsInputs, "") + }) +} diff --git a/sdk/build_release.go b/sdk/build_release.go index 149a34eb0..6bb05a36d 100644 --- a/sdk/build_release.go +++ b/sdk/build_release.go @@ -100,6 +100,7 @@ var ( // Add the dessert build releases from oldest to newest. buildReleaseS = initBuildRelease("S") buildReleaseT = initBuildRelease("Tiramisu") + buildReleaseU = initBuildRelease("UpsideDownCake") // Add the current build release which is always treated as being more recent than any other // build release, including those added in tests. @@ -397,7 +398,9 @@ func newPropertyPrunerForStructType(structType reflect.Type, selector fieldSelec // structure which are not supported by the specified target build release. // // A property is pruned if its field has a tag of the form: -// `supported_build_releases:"<build-release-set>"` +// +// `supported_build_releases:"<build-release-set>"` +// // and the resulting build release set does not contain the target build release. Properties that // have no such tag are assumed to be supported by all releases. func newPropertyPrunerByBuildRelease(propertiesStruct interface{}, targetBuildRelease *buildRelease) *propertyPruner { diff --git a/sdk/build_release_test.go b/sdk/build_release_test.go index 13730cbca..5bf57b553 100644 --- a/sdk/build_release_test.go +++ b/sdk/build_release_test.go @@ -42,7 +42,7 @@ func TestNameToRelease(t *testing.T) { android.AssertDeepEquals(t, "release", (*buildRelease)(nil), release) // Uses a wildcard in the error message to allow for additional build releases to be added to // the supported set without breaking this test. - android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,F1,F2,current\]`, []error{err}) + android.FailIfNoMatchingErrors(t, `unknown release "A", expected one of \[S,Tiramisu,UpsideDownCake,F1,F2,current\]`, []error{err}) }) } @@ -60,7 +60,7 @@ func TestParseBuildReleaseSet(t *testing.T) { t.Run("closed range", func(t *testing.T) { set, err := parseBuildReleaseSet("S-F1") android.AssertDeepEquals(t, "errors", nil, err) - android.AssertStringEquals(t, "set", "[S,Tiramisu,F1]", set.String()) + android.AssertStringEquals(t, "set", "[S,Tiramisu,UpsideDownCake,F1]", set.String()) }) invalidAReleaseMessage := `unknown release "A", expected one of ` + allBuildReleaseSet.String() t.Run("invalid release", func(t *testing.T) { diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index 7ab5285c6..51903ce39 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -889,6 +889,56 @@ java_sdk_library_import { ) } +func TestSnapshotWithJavaSdkLibrary_DistStem(t *testing.T) { + result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, ` + sdk { + name: "mysdk", + java_sdk_libs: ["myjavalib-foo"], + } + + java_sdk_library { + name: "myjavalib-foo", + apex_available: ["//apex_available:anyapex"], + srcs: ["Test.java"], + sdk_version: "current", + shared_library: false, + public: { + enabled: true, + }, + dist_stem: "myjavalib", + } + `) + + CheckSnapshot(t, result, "mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_sdk_library_import { + name: "myjavalib-foo", + prefer: false, + visibility: ["//visibility:public"], + apex_available: ["//apex_available:anyapex"], + shared_library: false, + public: { + jars: ["sdk_library/public/myjavalib-stubs.jar"], + stub_srcs: ["sdk_library/public/myjavalib_stub_sources"], + current_api: "sdk_library/public/myjavalib.txt", + removed_api: "sdk_library/public/myjavalib-removed.txt", + sdk_version: "current", + }, +} +`), + checkAllCopyRules(` +.intermediates/myjavalib-foo.stubs/android_common/javac/myjavalib-foo.stubs.jar -> sdk_library/public/myjavalib-stubs.jar +.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_api.txt -> sdk_library/public/myjavalib.txt +.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt +`), + checkMergeZips( + ".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip", + ), + ) +} + func TestSnapshotWithJavaSdkLibrary_UseSrcJar(t *testing.T) { result := android.GroupFixturePreparers( prepareForSdkTestWithJavaSdkLibrary, @@ -1004,7 +1054,7 @@ func TestSnapshotWithJavaSdkLibrary_AnnotationsZip_PreT(t *testing.T) { java_sdk_library { name: "myjavalib", srcs: ["Test.java"], - sdk_version: "current", + sdk_version: "S", shared_library: false, annotations_enabled: true, public: { diff --git a/sdk/member_trait.go b/sdk/member_trait.go index 4229ca82b..0843306a8 100644 --- a/sdk/member_trait.go +++ b/sdk/member_trait.go @@ -68,7 +68,6 @@ func getDynamicSdkMemberTraits(key android.OnceKey, registeredTraits []android.S // A list of sdkMemberTraitListProperty instances is created, one per member trait that provides: // * a reference to the member trait. // * a getter for the corresponding field in the properties struct. -// func createDynamicSdkMemberTraits(sdkMemberTraits []android.SdkMemberTrait) *dynamicSdkMemberTraits { var listProperties []*sdkMemberTraitListProperty diff --git a/sdk/member_type.go b/sdk/member_type.go index 10669fe23..98f59820b 100644 --- a/sdk/member_type.go +++ b/sdk/member_type.go @@ -80,7 +80,6 @@ func getDynamicSdkMemberTypes(key android.OnceKey, registeredTypes []android.Sdk // * a reference to the member type. // * a getter for the corresponding field in the properties struct. // * a dependency tag that identifies the member type of a resolved dependency. -// func createDynamicSdkMemberTypes(sdkMemberTypes []android.SdkMemberType) *dynamicSdkMemberTypes { var listProperties []*sdkMemberTypeListProperty diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 1ec12c346..2f9aee9da 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -218,15 +218,16 @@ type EmbeddedPropertiesStruct struct { } type testPropertiesStruct struct { - name string - private string - Public_Kept string `sdk:"keep"` - S_Common string - S_Different string `android:"arch_variant"` - A_Common []string - A_Different []string `android:"arch_variant"` - F_Common *bool - F_Different *bool `android:"arch_variant"` + name string + private string + Public_Ignore string `sdk:"ignore"` + Public_Keep string `sdk:"keep"` + S_Common string + S_Different string `android:"arch_variant"` + A_Common []string + A_Different []string `android:"arch_variant"` + F_Common *bool + F_Different *bool `android:"arch_variant"` EmbeddedPropertiesStruct } @@ -244,30 +245,32 @@ func TestCommonValueOptimization(t *testing.T) { common := &testPropertiesStruct{name: "common"} structs := []propertiesContainer{ &testPropertiesStruct{ - name: "struct-0", - private: "common", - Public_Kept: "common", - S_Common: "common", - S_Different: "upper", - A_Common: []string{"first", "second"}, - A_Different: []string{"alpha", "beta"}, - F_Common: proptools.BoolPtr(false), - F_Different: proptools.BoolPtr(false), + name: "struct-0", + private: "common", + Public_Ignore: "common", + Public_Keep: "keep", + S_Common: "common", + S_Different: "upper", + A_Common: []string{"first", "second"}, + A_Different: []string{"alpha", "beta"}, + F_Common: proptools.BoolPtr(false), + F_Different: proptools.BoolPtr(false), EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ S_Embedded_Common: "embedded_common", S_Embedded_Different: "embedded_upper", }, }, &testPropertiesStruct{ - name: "struct-1", - private: "common", - Public_Kept: "common", - S_Common: "common", - S_Different: "lower", - A_Common: []string{"first", "second"}, - A_Different: []string{"alpha", "delta"}, - F_Common: proptools.BoolPtr(false), - F_Different: proptools.BoolPtr(true), + name: "struct-1", + private: "common", + Public_Ignore: "common", + Public_Keep: "keep", + S_Common: "common", + S_Different: "lower", + A_Common: []string{"first", "second"}, + A_Different: []string{"alpha", "delta"}, + F_Common: proptools.BoolPtr(false), + F_Different: proptools.BoolPtr(true), EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ S_Embedded_Common: "embedded_common", S_Embedded_Different: "embedded_lower", @@ -282,15 +285,16 @@ func TestCommonValueOptimization(t *testing.T) { android.AssertDeepEquals(t, "common properties not correct", &testPropertiesStruct{ - name: "common", - private: "", - Public_Kept: "", - S_Common: "common", - S_Different: "", - A_Common: []string{"first", "second"}, - A_Different: []string(nil), - F_Common: proptools.BoolPtr(false), - F_Different: nil, + name: "common", + private: "", + Public_Ignore: "", + Public_Keep: "keep", + S_Common: "common", + S_Different: "", + A_Common: []string{"first", "second"}, + A_Different: []string(nil), + F_Common: proptools.BoolPtr(false), + F_Different: nil, EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ S_Embedded_Common: "embedded_common", S_Embedded_Different: "", @@ -300,15 +304,16 @@ func TestCommonValueOptimization(t *testing.T) { android.AssertDeepEquals(t, "updated properties[0] not correct", &testPropertiesStruct{ - name: "struct-0", - private: "common", - Public_Kept: "common", - S_Common: "", - S_Different: "upper", - A_Common: nil, - A_Different: []string{"alpha", "beta"}, - F_Common: nil, - F_Different: proptools.BoolPtr(false), + name: "struct-0", + private: "common", + Public_Ignore: "common", + Public_Keep: "keep", + S_Common: "", + S_Different: "upper", + A_Common: nil, + A_Different: []string{"alpha", "beta"}, + F_Common: nil, + F_Different: proptools.BoolPtr(false), EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ S_Embedded_Common: "", S_Embedded_Different: "embedded_upper", @@ -318,15 +323,16 @@ func TestCommonValueOptimization(t *testing.T) { android.AssertDeepEquals(t, "updated properties[1] not correct", &testPropertiesStruct{ - name: "struct-1", - private: "common", - Public_Kept: "common", - S_Common: "", - S_Different: "lower", - A_Common: nil, - A_Different: []string{"alpha", "delta"}, - F_Common: nil, - F_Different: proptools.BoolPtr(true), + name: "struct-1", + private: "common", + Public_Ignore: "common", + Public_Keep: "keep", + S_Common: "", + S_Different: "lower", + A_Common: nil, + A_Different: []string{"alpha", "delta"}, + F_Common: nil, + F_Different: proptools.BoolPtr(true), EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{ S_Embedded_Common: "", S_Embedded_Different: "embedded_lower", @@ -482,6 +488,7 @@ java_import { name: "mysdklibrary", srcs: ["Test.java"], compile_dex: true, + sdk_version: "S", public: {enabled: true}, permitted_packages: ["mysdklibrary"], } diff --git a/sdk/update.go b/sdk/update.go index 5c9376b5d..92a13fa7f 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -211,11 +211,14 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) { container = parent.(android.SdkAware) } + minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, child) + export := memberTag.ExportMember() s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{ sdkVariant: s, memberType: memberType, variant: child.(android.SdkAware), + minApiLevel: minApiLevel, container: container, export: export, exportedComponentsInfo: exportedComponentsInfo, @@ -332,10 +335,28 @@ const BUILD_NUMBER_FILE = "snapshot-creation-build-number.txt" // <arch>/lib/ // libFoo.so : a stub library +func (s sdk) targetBuildRelease(ctx android.ModuleContext) *buildRelease { + config := ctx.Config() + targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name) + targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv) + if err != nil { + ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err) + targetBuildRelease = buildReleaseCurrent + } + + return targetBuildRelease +} + // buildSnapshot is the main function in this source file. It creates rules to copy // the contents (header files, stub libraries, etc) into the zip file. func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { + targetBuildRelease := s.targetBuildRelease(ctx) + targetApiLevel, err := android.ApiLevelFromUser(ctx, targetBuildRelease.name) + if err != nil { + targetApiLevel = android.FutureApiLevel + } + // Aggregate all the sdkMemberVariantDep instances from all the sdk variants. hasLicenses := false var memberVariantDeps []sdkMemberVariantDep @@ -346,12 +367,18 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { // Filter out any sdkMemberVariantDep that is a component of another. memberVariantDeps = filterOutComponents(ctx, memberVariantDeps) - // Record the names of all the members, both explicitly specified and implicitly - // included. + // Record the names of all the members, both explicitly specified and implicitly included. Also, + // record the names of any members that should be excluded from this snapshot. allMembersByName := make(map[string]struct{}) exportedMembersByName := make(map[string]struct{}) + excludedMembersByName := make(map[string]struct{}) + + addMember := func(name string, export bool, exclude bool) { + if exclude { + excludedMembersByName[name] = struct{}{} + return + } - addMember := func(name string, export bool) { allMembersByName[name] = struct{}{} if export { exportedMembersByName[name] = struct{}{} @@ -362,11 +389,15 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { name := memberVariantDep.variant.Name() export := memberVariantDep.export - addMember(name, export) + // If the minApiLevel of the member is greater than the target API level then exclude it from + // this snapshot. + exclude := memberVariantDep.minApiLevel.GreaterThan(targetApiLevel) + + addMember(name, export, exclude) // Add any components provided by the module. for _, component := range memberVariantDep.exportedComponentsInfo.Components { - addMember(component, export) + addMember(component, export, exclude) } if memberVariantDep.memberType == android.LicenseModuleSdkMemberType { @@ -382,18 +413,9 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { modules: make(map[string]*bpModule), } - config := ctx.Config() - // Always add -current to the end snapshotFileSuffix := "-current" - targetBuildReleaseEnv := config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", buildReleaseCurrent.name) - targetBuildRelease, err := nameToRelease(targetBuildReleaseEnv) - if err != nil { - ctx.ModuleErrorf("invalid SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE: %s", err) - targetBuildRelease = buildReleaseCurrent - } - builder := &snapshotBuilder{ ctx: ctx, sdk: s, @@ -404,6 +426,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) { prebuiltModules: make(map[string]*bpModule), allMembersByName: allMembersByName, exportedMembersByName: exportedMembersByName, + excludedMembersByName: excludedMembersByName, targetBuildRelease: targetBuildRelease, } s.builderForTests = builder @@ -437,6 +460,10 @@ be unnecessary as every module in the sdk already has its own licenses property. } name := member.name + if _, ok := excludedMembersByName[name]; ok { + continue + } + requiredTraits := traits[name] if requiredTraits == nil { requiredTraits = android.EmptySdkMemberTraitSet() @@ -1034,6 +1061,9 @@ type snapshotBuilder struct { // The set of exported members by name. exportedMembersByName map[string]struct{} + // The set of members which have been excluded from this snapshot; by name. + excludedMembersByName map[string]struct{} + // The target build release for which the snapshot is to be generated. targetBuildRelease *buildRelease @@ -1218,6 +1248,9 @@ func (s *snapshotBuilder) snapshotSdkMemberName(name string, required bool) stri func (s *snapshotBuilder) snapshotSdkMemberNames(members []string, required bool) []string { var references []string = nil for _, m := range members { + if _, ok := s.excludedMembersByName[m]; ok { + continue + } references = append(references, s.snapshotSdkMemberName(m, required)) } return references @@ -1260,6 +1293,9 @@ type sdkMemberVariantDep struct { // The names of additional component modules provided by the variant. exportedComponentsInfo android.ExportedComponentsInfo + + // The minimum API level on which this module is supported. + minApiLevel android.ApiLevel } var _ android.SdkMember = (*sdkMember)(nil) @@ -2136,6 +2172,11 @@ type extractorProperty struct { // Retrieves the value on which common value optimization will be performed. getter fieldAccessorFunc + // True if the field should never be cleared. + // + // This is set to true if and only if the field is annotated with `sdk:"keep"`. + keep bool + // The empty value for the field. emptyValue reflect.Value @@ -2181,8 +2222,8 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS continue } - // Ignore fields whose value should be kept. - if proptools.HasTag(field, "sdk", "keep") { + // Ignore fields tagged with sdk:"ignore". + if proptools.HasTag(field, "sdk", "ignore") { continue } @@ -2200,6 +2241,8 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS } } + keep := proptools.HasTag(field, "sdk", "keep") + // Save a copy of the field index for use in the function. fieldIndex := f @@ -2239,6 +2282,7 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS name, filter, fieldGetter, + keep, reflect.Zero(field.Type), proptools.HasTag(field, "android", "arch_variant"), } @@ -2358,11 +2402,13 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac if commonValue != nil { emptyValue := property.emptyValue fieldGetter(commonStructValue).Set(*commonValue) - for i := 0; i < sliceValue.Len(); i++ { - container := sliceValue.Index(i).Interface().(propertiesContainer) - itemValue := reflect.ValueOf(container.optimizableProperties()) - fieldValue := fieldGetter(itemValue) - fieldValue.Set(emptyValue) + if !property.keep { + for i := 0; i < sliceValue.Len(); i++ { + container := sliceValue.Index(i).Interface().(propertiesContainer) + itemValue := reflect.ValueOf(container.optimizableProperties()) + fieldValue := fieldGetter(itemValue) + fieldValue.Set(emptyValue) + } } } diff --git a/shared/env.go b/shared/env.go index 152729ba0..b7d3bafb4 100644 --- a/shared/env.go +++ b/shared/env.go @@ -32,10 +32,11 @@ type envFileData []envFileEntry // // e.g. OUT_DIR = "out" // is converted to: -// { -// "Key": "OUT_DIR", -// "Value": "out", -// }, +// +// { +// "Key": "OUT_DIR", +// "Value": "out", +// }, func EnvFileContents(envDeps map[string]string) ([]byte, error) { contents := make(envFileData, 0, len(envDeps)) for key, value := range envDeps { diff --git a/snapshot/recovery_snapshot.go b/snapshot/recovery_snapshot.go index f1e31ca03..ac002be9c 100644 --- a/snapshot/recovery_snapshot.go +++ b/snapshot/recovery_snapshot.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/snapshot/snapshot.go b/snapshot/snapshot.go index 294f8b611..206ecc947 100644 --- a/snapshot/snapshot.go +++ b/snapshot/snapshot.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go index 4a14f2e03..8e5dfe4a2 100644 --- a/snapshot/snapshot_base.go +++ b/snapshot/snapshot_base.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/snapshot/util.go b/snapshot/util.go index f44705227..806ac90fa 100644 --- a/snapshot/util.go +++ b/snapshot/util.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/snapshot/vendor_snapshot.go b/snapshot/vendor_snapshot.go index 9bd26c201..8f7b8c215 100644 --- a/snapshot/vendor_snapshot.go +++ b/snapshot/vendor_snapshot.go @@ -4,7 +4,7 @@ // 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 +// 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, diff --git a/third_party/zip/reader_test.go b/third_party/zip/reader_test.go index 11c6d6e66..5f97f5c5f 100644 --- a/third_party/zip/reader_test.go +++ b/third_party/zip/reader_test.go @@ -615,7 +615,6 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) { // // It's here in hex for the same reason as rZipBytes above: to avoid // problems with on-disk virus scanners or other zip processors. -// func biggestZipBytes() []byte { s := ` 0000000 50 4b 03 04 14 00 08 00 08 00 00 00 00 00 00 00 diff --git a/ui/signal/signal.go b/ui/signal/signal.go index 4929a7bfe..552545d8b 100644 --- a/ui/signal/signal.go +++ b/ui/signal/signal.go @@ -31,13 +31,12 @@ import ( // same time we do. Most of the time this means we just need to ignore the signal and we'll // just see errors from all of our subprocesses. But in case that fails, when we get a signal: // -// 1. Wait two seconds to exit normally. -// 2. Call cancel() which is normally the cancellation of a Context. This will send a SIGKILL -// to any subprocesses attached to that context. -// 3. Wait two seconds to exit normally. -// 4. Call cleanup() to close the log/trace buffers, then panic. -// 5. If another two seconds passes (if cleanup got stuck, etc), then panic. -// +// 1. Wait two seconds to exit normally. +// 2. Call cancel() which is normally the cancellation of a Context. This will send a SIGKILL +// to any subprocesses attached to that context. +// 3. Wait two seconds to exit normally. +// 4. Call cleanup() to close the log/trace buffers, then panic. +// 5. If another two seconds passes (if cleanup got stuck, etc), then panic. func SetupSignals(log logger.Logger, cancel, cleanup func()) { signals := make(chan os.Signal, 5) signal.Notify(signals, os.Interrupt, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM) |