From f5a6628b27ab67cba0aa5fd153973cc5d704a366 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Fri, 21 Feb 2020 08:16:41 -0800 Subject: Use header jar without jarjar for sharded classpath Sharding uses the header jar of all of the classes of the module with the sources of a subset, but was incorrectly used the jarjar version of the header jar, which may have renamed some of the classes. Fixes: 149969343 Test: m framework-minus-apex Change-Id: I568c939f8030d3ddc1e7fa8796cffcac4d6172e8 --- java/java.go | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 462dba809..c89784a03 100644 --- a/java/java.go +++ b/java/java.go @@ -1323,6 +1323,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.compiledSrcJars = srcJars enable_sharding := false + var headerJarFileWithoutJarjar android.Path if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine { if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 { enable_sharding = true @@ -1332,7 +1333,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // allow for the use of annotation processors that do function correctly // with sharding enabled. See: b/77284273. } - j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars) + headerJarFileWithoutJarjar, j.headerJarFile = + j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars) if ctx.Failed() { return } @@ -1351,7 +1353,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { } if enable_sharding { - flags.classpath = append(flags.classpath, j.headerJarFile) + flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar) shardSize := int(*(j.properties.Javac_shard_size)) var shardSrcs []android.Paths if len(uniqueSrcFiles) > 0 { @@ -1642,7 +1644,8 @@ func CheckKotlincFlags(ctx android.ModuleContext, flags []string) { } func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths, - deps deps, flags javaBuilderFlags, jarName string, extraJars android.Paths) android.Path { + deps deps, flags javaBuilderFlags, jarName string, + extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) { var jars android.Paths if len(srcFiles) > 0 || len(srcJars) > 0 { @@ -1650,7 +1653,7 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars turbineJar := android.PathForModuleOut(ctx, "turbine", jarName) TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags) if ctx.Failed() { - return nil + return nil, nil } jars = append(jars, turbineJar) } @@ -1659,7 +1662,6 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars // Combine any static header libraries into classes-header.jar. If there is only // one input jar this step will be skipped. - var headerJar android.Path jars = append(jars, deps.staticHeaderJars...) // we cannot skip the combine step for now if there is only one jar @@ -1668,18 +1670,19 @@ func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{}, false, nil, []string{"META-INF/TRANSITIVE"}) headerJar = combinedJar + jarjarHeaderJar = combinedJar if j.expandJarjarRules != nil { // Transform classes.jar into classes-jarjar.jar jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName) TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules) - headerJar = jarjarFile + jarjarHeaderJar = jarjarFile if ctx.Failed() { - return nil + return nil, nil } } - return headerJar + return headerJar, jarjarHeaderJar } func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags, -- cgit v1.2.3-59-g8ed1b From 81aaa0c1bd99e38f61611d574712a761e3ef8508 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Tue, 18 Feb 2020 12:50:44 +0000 Subject: Reland "Turn on the instrumentation by default for the java code in APEXes" This reverts commit c021ea0b3543d4ff64b16414c0276b96dc5b2c4b. Exempt-From-Owner-Approval: cherry-pick from aosp Bug: 149353192 Merged-In: I2b1c0736202de26c5ea88c0ab14574bd7207a5fb Test: N/A (this is a clean revert) forward fix will be followed (cherry picked from commit 00cae1cc88773a5238809130841b6a6b7eb63614) Change-Id: I2b1c0736202de26c5ea88c0ab14574bd7207a5fb --- java/java.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index c89784a03..1273eff9c 100644 --- a/java/java.go +++ b/java/java.go @@ -1521,6 +1521,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.headerJarFile = j.implementationJarFile } + // Force enable the instrumentation for java code that is built for APEXes + if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() { + j.properties.Instrument = true + } + if j.shouldInstrument(ctx) { outputFile = j.instrument(ctx, flags, outputFile, jarName) } -- cgit v1.2.3-59-g8ed1b From 2882660422bbbe7ecc5d0ead431b383f6d5e7fcd Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Fri, 21 Feb 2020 16:04:53 +0900 Subject: Expect added members for instrumented modules hiddenapi expects that all members in a class to have corresponding hidden API flags. However, this can't be satisfied when the java module having the class is instrumented; JaCoCo added a few number of synthetic members. In this case, give 'no-force-assign-all' option to the hidden api tool so that it doesn't complain about the synthetic methods. Also, disabling instrumenting jacocoagent itself, because it doesn't make sense. Exempt-From-Owner-Approval: PS3 fixes a typo in a comment. PS2 got ORV. Bug: 149353192 Test: SKIP_ABI_CHECKS=true EMMA_INSTRUMENT=true EMMA_INSTRUMENT_FRAMEWORK=true SKIP_BOOT_JARS_CHECK=true m out/soong/.intermediates/external/apache-xml/apache-xml/android_common_com.android.art.debug/hiddenapi/unaligned/unaligned.jar Merged-In: Ibaf383c439945ab664e885af319548b56e2c8cb6 (cherry picked from commit 93e57a0b862beabdd11b8dac342167ea7f7c7b76) Change-Id: Ibaf383c439945ab664e885af319548b56e2c8cb6 --- java/hiddenapi.go | 12 ++++++++++++ java/java.go | 7 +++++-- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'java/java.go') diff --git a/java/hiddenapi.go b/java/hiddenapi.go index 6020aba6e..8f34714d3 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -159,9 +159,21 @@ func hiddenAPIEncodeDex(ctx android.ModuleContext, output android.WritablePath, tmpOutput = android.PathForModuleOut(ctx, "hiddenapi", "unaligned", "unaligned.jar") tmpDir = android.PathForModuleOut(ctx, "hiddenapi", "unaligned") } + + enforceHiddenApiFlagsToAllMembers := true // If frameworks/base doesn't exist we must be building with the 'master-art' manifest. // Disable assertion that all methods/fields have hidden API flags assigned. if !ctx.Config().FrameworksBaseDirExists(ctx) { + enforceHiddenApiFlagsToAllMembers = false + } + // b/149353192: when a module is instrumented, jacoco adds synthetic members + // $jacocoData and $jacocoInit. Since they don't exist when building the hidden API flags, + // don't complain when we don't find hidden API flags for the synthetic members. + if j, ok := ctx.Module().(*Library); ok && j.shouldInstrument(ctx) { + enforceHiddenApiFlagsToAllMembers = false + } + + if !enforceHiddenApiFlagsToAllMembers { hiddenapiFlags = "--no-force-assign-all" } diff --git a/java/java.go b/java/java.go index 1273eff9c..8d58a9023 100644 --- a/java/java.go +++ b/java/java.go @@ -1521,8 +1521,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.headerJarFile = j.implementationJarFile } - // Force enable the instrumentation for java code that is built for APEXes - if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !j.IsForPlatform() { + // Force enable the instrumentation for java code that is built for APEXes ... + // except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent + // doesn't make sense) + isJacocoAgent := ctx.ModuleName() == "jacocoagent" + if android.DirectlyInAnyApex(ctx, ctx.ModuleName()) && !isJacocoAgent && !j.IsForPlatform() { j.properties.Instrument = true } -- cgit v1.2.3-59-g8ed1b From b8fa86ad6f8186258b89572bef0468fc873eb30d Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Tue, 10 Mar 2020 06:23:13 +0900 Subject: Fix apex_available Checking apex_available was missing some corner cases. For example, the deps of share deps of cc_library modules are missed while those from cc_library_shared are correctly tracked. This was due to.. * calling DepIsInSameApex in WalkDeps: both work fine separately, but when they are used together, it fails to work. It's due to how WalkDeps works. (We might fix this bug too risky since it is used very widely) * incorrect receiver for DepIsInSameApex in apex_deps mutator: receiver is supposed to be parent, but child was used before. Interestingly lots of deps are within the same group of module types(cc to cc, java to java), it has worked. (note that receiver's DepIsInSameApex implementation can be different). This change fixes them by.. * walkPayloadDeps is now relying on ApexVariation, which is calculated correctly by TopDown apex_deps mutator. * use correct receiver for DepIsInSameApex in apex_deps mutator, which requires for java.SdkLibrary to override the method and for java.Library/Import to use passed dep instead of receiver to check its membership of sdk. Exempt-From-Owner-Approval: cherry-pick from aosp/master Bug: 151071238 Test: build/boot Merged-In: I0569ef4bb8e79635e4d97a89f421a8d8b7d26456 (cherry picked from commit 5e9013be2202effb500a0aa14d95f5fef70cc75e) Change-Id: I0569ef4bb8e79635e4d97a89f421a8d8b7d26456 --- apex/apex.go | 39 ++++++++++++++++++++++++++++++++------- apex/apex_test.go | 32 +++++++++++++++----------------- java/java.go | 18 ++++++++++++++---- java/sdk_library.go | 14 ++++++++++++-- sdk/sdk_test.go | 3 ++- 5 files changed, 75 insertions(+), 31 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index ee6f93ae3..268088b24 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -212,8 +212,11 @@ func makeApexAvailableWhitelist() map[string][]string { "bluetooth-protos-lite", "bluetooth.mapsapi", "com.android.vcard", + "dnsresolver_aidl_interface-V2-java", "fmtlib", "guava", + "ipmemorystore-aidl-interfaces-V5-java", + "ipmemorystore-aidl-interfaces-java", "internal_include_headers", "lib-bt-packets", "lib-bt-packets-avrcp", @@ -279,6 +282,12 @@ func makeApexAvailableWhitelist() map[string][]string { "libutils_headers", "libz", "media_plugin_headers", + "net-utils-services-common", + "netd_aidl_interface-unstable-java", + "netd_event_listener_interface-java", + "netlink-client", + "networkstack-aidl-interfaces-unstable-java", + "networkstack-client", "sap-api-java-static", "services.net", } @@ -296,6 +305,7 @@ func makeApexAvailableWhitelist() map[string][]string { "libcrypto", "libnativehelper_header_only", "libssl", + "unsupportedappusage", } // // Module separator @@ -319,6 +329,7 @@ func makeApexAvailableWhitelist() map[string][]string { "cronet_impl_platform_java", "libcronet.80.0.3986.0", "org.chromium.net.cronet", + "org.chromium.net.cronet.xml", "prebuilt_libcronet.80.0.3986.0", } // @@ -559,6 +570,7 @@ func makeApexAvailableWhitelist() map[string][]string { "libFLAC-config", "libFLAC-headers", "libFraunhoferAAC", + "libLibGuiProperties", "libarect", "libasync_safe", "libaudio_system_headers", @@ -574,6 +586,7 @@ func makeApexAvailableWhitelist() map[string][]string { "libbase", "libbase_headers", "libbinder_headers", + "libbinderthreadstateutils", "libbluetooth-types-header", "libbufferhub_headers", "libc++", @@ -779,6 +792,7 @@ func makeApexAvailableWhitelist() map[string][]string { "libdexfile_external_headers", "libdexfile_support", "libdexfile_support_static", + "libdl_static", "libgtest_prod", "libjemalloc5", "liblinker_main", @@ -870,6 +884,7 @@ func makeApexAvailableWhitelist() map[string][]string { m["com.android.wifi"] = []string{ "PlatformProperties", "android.hardware.wifi-V1.0-java", + "android.hardware.wifi-V1.0-java-constants", "android.hardware.wifi-V1.1-java", "android.hardware.wifi-V1.2-java", "android.hardware.wifi-V1.3-java", @@ -890,6 +905,8 @@ func makeApexAvailableWhitelist() map[string][]string { "bouncycastle-unbundled", "dnsresolver_aidl_interface-V2-java", "error_prone_annotations", + "framework-wifi-pre-jarjar", + "framework-wifi-util-lib", "ipmemorystore-aidl-interfaces-V3-java", "ipmemorystore-aidl-interfaces-java", "ksoap2", @@ -1025,7 +1042,10 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { var apexBundles []android.ApexInfo var directDep bool if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex { - apexBundles = []android.ApexInfo{{mctx.ModuleName(), proptools.Bool(a.properties.Legacy_android10_support)}} + apexBundles = []android.ApexInfo{android.ApexInfo{ + ApexName: mctx.ModuleName(), + LegacyAndroid10Support: proptools.Bool(a.properties.Legacy_android10_support), + }} directDep = true } else if am, ok := mctx.Module().(android.ApexModule); ok { apexBundles = am.ApexVariations() @@ -1036,10 +1056,14 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { return } + cur := mctx.Module().(interface { + DepIsInSameApex(android.BaseModuleContext, android.Module) bool + }) + mctx.VisitDirectDeps(func(child android.Module) { depName := mctx.OtherModuleName(child) if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && - (directDep || am.DepIsInSameApex(mctx, child)) { + cur.DepIsInSameApex(mctx, child) { android.UpdateApexDependency(apexBundles, depName, directDep) am.BuildForApexes(apexBundles) } @@ -1958,7 +1982,7 @@ func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext, } // Check for the indirect dependencies if it is considered as part of the APEX - if am.DepIsInSameApex(ctx, am) { + if am.ApexName() != "" { do(ctx, parent, am, false /* externalDep */) return true } @@ -1979,10 +2003,12 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) { apexName := ctx.ModuleName() - if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, to) { + fromName := ctx.OtherModuleName(from) + toName := ctx.OtherModuleName(to) + if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) { return } - ctx.ModuleErrorf("%q requires %q that is not available for the APEX.", from.Name(), to.Name()) + ctx.ModuleErrorf("%q requires %q that is not available for the APEX.", fromName, toName) }) } @@ -2352,13 +2378,12 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.buildApexDependencyInfo(ctx) } -func whitelistedApexAvailable(apex string, module android.Module) bool { +func whitelistedApexAvailable(apex, moduleName string) bool { key := apex key = strings.Replace(key, "test_", "", 1) key = strings.Replace(key, "com.android.art.debug", "com.android.art", 1) key = strings.Replace(key, "com.android.art.release", "com.android.art", 1) - moduleName := module.Name() // Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build // system. Trim the prefix for the check since they are confusing moduleName = strings.TrimPrefix(moduleName, "prebuilt_") diff --git a/apex/apex_test.go b/apex/apex_test.go index 6a9533e37..34736e588 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -2832,6 +2832,7 @@ func TestErrorsIfDepsAreNotEnabled(t *testing.T) { stl: "none", system_shared_libs: [], enabled: false, + apex_available: ["myapex"], } `) testApexError(t, `module "myapex" .* depends on disabled module "myjar"`, ` @@ -2853,6 +2854,7 @@ func TestErrorsIfDepsAreNotEnabled(t *testing.T) { sdk_version: "none", system_modules: "none", enabled: false, + apex_available: ["myapex"], } `) } @@ -3011,7 +3013,7 @@ func TestApexWithTestHelperApp(t *testing.T) { func TestApexPropertiesShouldBeDefaultable(t *testing.T) { // libfoo's apex_available comes from cc_defaults - testApexError(t, `"myapex" .*: "myapex" requires "libfoo" that is not available for the APEX`, ` + testApexError(t, `requires "libfoo" that is not available for the APEX`, ` apex { name: "myapex", key: "myapex.key", @@ -3077,8 +3079,8 @@ func TestApexAvailable(t *testing.T) { apex_available: ["otherapex"], }`) - // libbar is an indirect dep - testApexError(t, "requires \"libbar\" that is not available for the APEX", ` + // libbbaz is an indirect dep + testApexError(t, "requires \"libbaz\" that is not available for the APEX", ` apex { name: "myapex", key: "myapex.key", @@ -3091,31 +3093,26 @@ func TestApexAvailable(t *testing.T) { private_key: "testkey.pem", } - apex { - name: "otherapex", - key: "otherapex.key", - native_shared_libs: ["libfoo"], - } - - apex_key { - name: "otherapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - cc_library { name: "libfoo", stl: "none", shared_libs: ["libbar"], system_shared_libs: [], - apex_available: ["myapex", "otherapex"], + apex_available: ["myapex"], } cc_library { name: "libbar", stl: "none", + shared_libs: ["libbaz"], + system_shared_libs: [], + apex_available: ["myapex"], + } + + cc_library { + name: "libbaz", + stl: "none", system_shared_libs: [], - apex_available: ["otherapex"], }`) testApexError(t, "\"otherapex\" is not a valid module name", ` @@ -3452,6 +3449,7 @@ func TestRejectNonInstallableJavaLibrary(t *testing.T) { sdk_version: "none", system_modules: "none", compile_dex: false, + apex_available: ["myapex"], } `) } diff --git a/java/java.go b/java/java.go index 8d58a9023..23dc0b5c5 100644 --- a/java/java.go +++ b/java/java.go @@ -1790,11 +1790,16 @@ func (j *Module) hasCode(ctx android.ModuleContext) bool { } func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - depTag := ctx.OtherModuleDependencyTag(dep) // Dependencies other than the static linkage are all considered crossing APEX boundary + if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + return true + } // Also, a dependency to an sdk member is also considered as such. This is required because // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - return depTag == staticLibTag || j.IsInAnySdk() + if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { + return true + } + return false } func (j *Module) Stem() string { @@ -2495,11 +2500,16 @@ func (j *Import) SrcJarArgs() ([]string, android.Paths) { } func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - depTag := ctx.OtherModuleDependencyTag(dep) // dependencies other than the static linkage are all considered crossing APEX boundary + if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + return true + } // Also, a dependency to an sdk member is also considered as such. This is required because // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - return depTag == staticLibTag || j.IsInAnySdk() + if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { + return true + } + return false } // Add compile time check for interface implementation diff --git a/java/sdk_library.go b/java/sdk_library.go index a8edf1d55..6921114bf 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -581,6 +581,14 @@ func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiSc mctx.CreateModule(DroidstubsFactory, &props) } +func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool { + depTag := mctx.OtherModuleDependencyTag(dep) + if depTag == xmlPermissionsFileTag { + return true + } + return module.Library.DepIsInSameApex(mctx, dep) +} + // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) { props := struct { @@ -590,9 +598,11 @@ func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) { Device_specific *bool Product_specific *bool System_ext_specific *bool + Apex_available []string }{ - Name: proptools.StringPtr(module.xmlFileName()), - Lib_name: proptools.StringPtr(module.BaseModuleName()), + Name: proptools.StringPtr(module.xmlFileName()), + Lib_name: proptools.StringPtr(module.BaseModuleName()), + Apex_available: module.ApexProperties.Apex_available, } if module.SocSpecific() { diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 934bdae01..53c29713f 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -58,6 +58,7 @@ func TestDepNotInRequiredSdks(t *testing.T) { sdk_version: "none", compile_dex: true, host_supported: true, + apex_available: ["myapex"], } // this lib is no in mysdk @@ -113,7 +114,7 @@ func TestSnapshotVisibility(t *testing.T) { java_defaults { name: "java-defaults", - visibility: ["//other/bar"], + visibility: ["//other/bar"], } java_library { -- cgit v1.2.3-59-g8ed1b From bbd78556daf4a7e015f2e3ddfe9539909e9ebf40 Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Thu, 19 Mar 2020 15:23:38 +0000 Subject: Make system_server stubs consistent with other stubs Include the module_api stubs in system_server one instead of putting both of these jars on the classpath. Also rename it to be in line with the other stubs. Bug: 149293194 Test: m Change-Id: Iead5af4152a49cd59a4fd7afc0312c2f0c872c1e --- java/java.go | 2 +- java/sdk.go | 2 +- java/sdk_test.go | 4 ++-- java/testing.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 23dc0b5c5..c73efa4da 100644 --- a/java/java.go +++ b/java/java.go @@ -841,7 +841,7 @@ func (m *Module) getLinkType(name string) (ret linkType, stubs bool) { return javaModule, true case ver.kind == sdkModule: return javaModule, false - case name == "services-stubs": + case name == "android_system_server_stubs_current": return javaSystemServer, true case ver.kind == sdkSystemServer: return javaSystemServer, false diff --git a/java/sdk.go b/java/sdk.go index 20a077230..4c9ba2b55 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -396,7 +396,7 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep return toModule([]string{"android_module_lib_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) case sdkSystemServer: // TODO(146757305): provide .apk and .aidl that have more APIs for modules - return toModule([]string{"android_module_lib_stubs_current", "services-stubs"}, "framework-res", sdkFrameworkAidlPath(ctx)) + return toModule([]string{"android_system_server_stubs_current"}, "framework-res", sdkFrameworkAidlPath(ctx)) default: panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw)) } diff --git a/java/sdk_test.go b/java/sdk_test.go index ea6733d86..088db9e70 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -222,9 +222,9 @@ func TestClasspath(t *testing.T) { { name: "system_server_current", properties: `sdk_version: "system_server_current",`, - bootclasspath: []string{"android_module_lib_stubs_current", "services-stubs", "core-lambda-stubs"}, + bootclasspath: []string{"android_system_server_stubs_current", "core-lambda-stubs"}, system: "core-current-stubs-system-modules", - java9classpath: []string{"android_module_lib_stubs_current", "services-stubs"}, + java9classpath: []string{"android_system_server_stubs_current"}, aidl: "-p" + buildDir + "/framework.aidl", }, } diff --git a/java/testing.go b/java/testing.go index 5b6a39b2a..28c1a2691 100644 --- a/java/testing.go +++ b/java/testing.go @@ -148,7 +148,7 @@ func GatherRequiredDepsForTest() string { "android_system_stubs_current", "android_test_stubs_current", "android_module_lib_stubs_current", - "services-stubs", + "android_system_server_stubs_current", "core.current.stubs", "core.platform.api.stubs", "kotlin-stdlib", -- cgit v1.2.3-59-g8ed1b From a4a83b0ef9b9769681ad285290fdbbf043eff3d5 Mon Sep 17 00:00:00 2001 From: Ulya Trafimovich Date: Wed, 11 Mar 2020 11:59:34 +0000 Subject: Simplify the construction of class loader contexts for system server jars. This reworks CL https://r.android.com/1180134 as follows: 1) Do not reorder the list of system server jars passed from Make to Soong via the product variable PRODUCT_SYSTEM_SERVER_JARS. This means that for some products the order of jars on the system server classpath may be non-optimal: a jar X that depends on Y may be dexpreopted before Y, so that all references to the classes and methods from Y wil be unresolved. Unfortunately for such products, fixing the order is not a simple matter of rearranging their PRODUCT_SYSTEM_SERVER_JARS, because the conflicts may arise when the product-specific variable gets merged with the common variable. 2) As a consequence of 1), do not add artificial dependencies between system server jars: this is now impossible, as it would create circular dependencies for those products that have non-optimal order of jars. 3) Copy dex files for system server jars to a predefined build location. This is necessary because at the time when Soong generates class loader context for k-th jar, it needs to know the paths to jars 1 .. (k-1), and it might have not processed those jars yet (so Soong can't query the paths from the modules). This approach is similar to the way Soong handles bootclasspath jars. 4) Do not exclude from dexpreopting system server jars that are not Soong modules (those that are Make modules). The previous CL excluded them because Make modules do not have ModuleContext. But it turns out that ModuleContext is not necessary, as all the information is passed via the dexpreopt config. Test: aosp_walleye-userdebug boots and there are no messages in the logcat regarding class loader context mismatch: $ adb logcat | grep 'mismatch' # empty Test: Class loader contexts in the oat files for system server jars match expectations: $ oatdump --oat-file=out/target/product/walleye/system/framework/oat/arm64/com.android.location.provider.odex 2>/dev/null | grep '^classpath' classpath = PCL[] $ oatdump --oat-file=out/target/product/walleye/system/framework/oat/arm64/services.odex 2>/dev/null | grep '^classpath' classpath = PCL[/system/framework/com.android.location.provider.jar*1989208671] $ oatdump --oat-file=out/target/product/walleye/system/framework/oat/arm64/ethernet-service.odex 2>/dev/null | grep '^classpath' classpath = PCL[/system/framework/com.android.location.provider.jar*1989208671:/system/framework/services.jar*4040443083:/system/framework/services.jar!classes2.dex*2210087472] Test: The phone boots and logcat has no scary messages related to class loader contexts: $ lunch aosp_walleye-userdebug && m $ adb reboot bootloader && fastboot flashall -w && adb wait-for-device $ adb root $ adb shell stop $ adb logcat -c $ adb shell setprop dalvik.vm.extra-opts -verbose:oat $ adb shell start $ adb logcat | egrep -io 'system_server: .*load.*/system/framework.*' system_server: Loading /system/framework/oat/arm64/com.android.location.provider.odex with executable: 0 system_server: Successfully loaded /system/framework/oat/arm64/com.android.location.provider.odex with executable: 0 system_server: Loading /system/framework/oat/arm64/services.odex with executable: 0 system_server: Successfully loaded /system/framework/oat/arm64/services.odex with executable: 0 system_server: Loading /system/framework/oat/arm64/ethernet-service.odex with executable: 0 system_server: Successfully loaded /system/framework/oat/arm64/ethernet-service.odex with executable: 0 system_server: Loading /system/framework/oat/arm64/wifi-service.odex with executable: 0 system_server: Successfully loaded /system/framework/oat/arm64/wifi-service.odex with executable: 0 system_server: Loading /system/framework/oat/arm64/com.android.location.provider.odex with executable: 1 system_server: Successfully loaded /system/framework/oat/arm64/com.android.location.provider.odex with executable: 1 system_server: Loading /system/framework/oat/arm64/services.odex with executable: 1 system_server: Successfully loaded /system/framework/oat/arm64/services.odex with executable: 1 system_server: Loading /system/framework/oat/arm64/ethernet-service.odex with executable: 1 system_server: Successfully loaded /system/framework/oat/arm64/ethernet-service.odex with executable: 1 system_server: Loading /system/framework/oat/arm64/wifi-service.odex with executable: 1 system_server: Successfully loaded /system/framework/oat/arm64/wifi-service.odex with executable: 1 system_server: Loading /system/framework/oat/arm64/com.android.location.provider.odex with executable: 1 system_server: Successfully loaded /system/framework/oat/arm64/com.android.location.provider.odex with executable: 1 Bug: 141785760 Bug: 140451054 Bug: 148944771 Bug: 147017252 Change-Id: I33c4087f8bfacd0ecb89877aa150b75360d06710 --- dexpreopt/dexpreopt.go | 81 +++++++++++++++++++----------------------------- java/dexpreopt_config.go | 13 ++------ java/java.go | 47 ---------------------------- 3 files changed, 35 insertions(+), 106 deletions(-) (limited to 'java/java.go') diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 6cb987385..7dd01e235 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -41,21 +41,12 @@ import ( "android/soong/android" - "github.com/google/blueprint" "github.com/google/blueprint/pathtools" ) const SystemPartition = "/system/" const SystemOtherPartition = "/system_other/" -type dependencyTag struct { - blueprint.BaseDependencyTag - name string -} - -var SystemServerDepTag = dependencyTag{name: "system-server-dep"} -var SystemServerForcedDepTag = dependencyTag{name: "system-server-forced-dep"} - // GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a // ModuleConfig. The produced files and their install locations will be available through rule.Installs(). func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConfig, @@ -116,13 +107,6 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo } } - // Don't preopt system server jars that are not Soong modules. - if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) { - if _, ok := ctx.(android.ModuleContext); !ok { - return true - } - } - // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip // Also preopt system server jars since selinux prevents system server from loading anything from // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage @@ -239,6 +223,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g invocationPath := odexPath.ReplaceExtension(ctx, "invocation") + systemServerJars := NonUpdatableSystemServerJars(ctx, global) + // The class loader context using paths in the build var classLoaderContextHost android.Paths @@ -253,8 +239,8 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g var conditionalClassLoaderContextHost29 android.Paths var conditionalClassLoaderContextTarget29 []string - var classLoaderContextHostString, classLoaderContextDeviceString string - var classLoaderDeps android.Paths + // A flag indicating if the '&' class loader context is used. + unknownClassLoaderContext := false if module.EnforceUsesLibraries { usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...) @@ -298,49 +284,38 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g pathForLibrary(module, hidlBase)) conditionalClassLoaderContextTarget29 = append(conditionalClassLoaderContextTarget29, filepath.Join("/system/framework", hidlBase+".jar")) - - classLoaderContextHostString = strings.Join(classLoaderContextHost.Strings(), ":") - } else if android.InList(module.Name, NonUpdatableSystemServerJars(ctx, global)) { - // We expect that all dexpreopted system server jars are Soong modules. - mctx, isModule := ctx.(android.ModuleContext) - if !isModule { - panic("Cannot dexpreopt system server jar that is not a soong module.") + } else if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 { + // System server jars should be dexpreopted together: class loader context of each jar + // should include all preceding jars on the system server classpath. + for _, otherJar := range systemServerJars[:jarIndex] { + classLoaderContextHost = append(classLoaderContextHost, SystemServerDexJarHostPath(ctx, otherJar)) + classLoaderContextTarget = append(classLoaderContextTarget, "/system/framework/"+otherJar+".jar") } - // System server jars should be dexpreopted together: class loader context of each jar - // should include preceding jars (which can be found as dependencies of the current jar - // with a special tag). - var jarsOnHost android.Paths - var jarsOnDevice []string - mctx.VisitDirectDepsWithTag(SystemServerDepTag, func(dep android.Module) { - depName := mctx.OtherModuleName(dep) - if jar, ok := dep.(interface{ DexJar() android.Path }); ok { - jarsOnHost = append(jarsOnHost, jar.DexJar()) - jarsOnDevice = append(jarsOnDevice, "/system/framework/"+depName+".jar") - } else { - mctx.ModuleErrorf("module \"%s\" is not a jar", depName) - } - }) - classLoaderContextHostString = strings.Join(jarsOnHost.Strings(), ":") - classLoaderContextDeviceString = strings.Join(jarsOnDevice, ":") - classLoaderDeps = jarsOnHost + // Copy the system server jar to a predefined location where dex2oat will find it. + dexPathHost := SystemServerDexJarHostPath(ctx, module.Name) + rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String())) + rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost) } else { // Pass special class loader context to skip the classpath and collision check. // This will get removed once LOCAL_USES_LIBRARIES is enforced. // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default // to the &. - classLoaderContextHostString = `\&` + unknownClassLoaderContext = true } rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String())) rule.Command().FlagWithOutput("rm -f ", odexPath) // Set values in the environment of the rule. These may be modified by construct_context.sh. - if classLoaderContextHostString == `\&` { - rule.Command().Text(`class_loader_context_arg=--class-loader-context=\&`) - rule.Command().Text(`stored_class_loader_context_arg=""`) + if unknownClassLoaderContext { + rule.Command(). + Text(`class_loader_context_arg=--class-loader-context=\&`). + Text(`stored_class_loader_context_arg=""`) } else { - rule.Command().Text("class_loader_context_arg=--class-loader-context=PCL[" + classLoaderContextHostString + "]") - rule.Command().Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + classLoaderContextDeviceString + "]") + rule.Command(). + Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(classLoaderContextHost.Strings(), ":") + "]"). + Implicits(classLoaderContextHost). + Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(classLoaderContextTarget, ":") + "]") } if module.EnforceUsesLibraries { @@ -395,7 +370,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", module.PreoptBootClassPathDexFiles, ":"). Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", module.PreoptBootClassPathDexLocations, ":"). Flag("${class_loader_context_arg}"). - Flag("${stored_class_loader_context_arg}").Implicits(classLoaderDeps). + Flag("${stored_class_loader_context_arg}"). FlagWithArg("--boot-image=", strings.Join(module.DexPreoptImageLocations, ":")).Implicits(module.DexPreoptImagesDeps[archIdx].Paths()). FlagWithInput("--dex-file=", module.DexPath). FlagWithArg("--dex-location=", dexLocationArg). @@ -609,6 +584,14 @@ func NonUpdatableSystemServerJars(ctx android.PathContext, global *GlobalConfig) }).([]string) } +// A predefined location for the system server dex jars. This is needed in order to generate +// class loader context for dex2oat, as the path to the jar in the Soong module may be unknown +// at that time (Soong processes the jars in dependency order, which may be different from the +// the system server classpath order). +func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath { + return android.PathForOutput(ctx, ctx.Config().DeviceName(), "system_server_dexjars", jar+".jar") +} + func contains(l []string, s string) bool { for _, e := range l { if e == s { diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go index 28f56d24a..5d74b2135 100644 --- a/java/dexpreopt_config.go +++ b/java/dexpreopt_config.go @@ -30,9 +30,9 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string { return ctx.Config().OnceStringSlice(systemServerClasspathKey, func() []string { global := dexpreopt.GetGlobalConfig(ctx) var systemServerClasspathLocations []string - var dexpreoptJars = *DexpreoptedSystemServerJars(ctx.Config()) - // 1) The jars that are dexpreopted. - for _, m := range dexpreoptJars { + nonUpdatable := dexpreopt.NonUpdatableSystemServerJars(ctx, global) + // 1) Non-updatable jars. + for _, m := range nonUpdatable { systemServerClasspathLocations = append(systemServerClasspathLocations, filepath.Join("/system/framework", m+".jar")) } @@ -41,13 +41,6 @@ func systemServerClasspath(ctx android.MakeVarsContext) []string { systemServerClasspathLocations = append(systemServerClasspathLocations, dexpreopt.GetJarLocationFromApexJarPair(m)) } - // 3) The jars from make (which are not updatable, not preopted). - for _, m := range dexpreopt.NonUpdatableSystemServerJars(ctx, global) { - if !android.InList(m, dexpreoptJars) { - systemServerClasspathLocations = append(systemServerClasspathLocations, - filepath.Join("/system/framework", m+".jar")) - } - } if len(systemServerClasspathLocations) != len(global.SystemServerJars)+len(global.UpdatableSystemServerJars) { panic(fmt.Errorf("Wrong number of system server jars, got %d, expected %d", len(systemServerClasspathLocations), diff --git a/java/java.go b/java/java.go index 23dc0b5c5..27e4d6156 100644 --- a/java/java.go +++ b/java/java.go @@ -23,14 +23,12 @@ import ( "path/filepath" "strconv" "strings" - "sync" "github.com/google/blueprint" "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" "android/soong/android" - "android/soong/dexpreopt" "android/soong/java/config" "android/soong/tradefed" ) @@ -54,8 +52,6 @@ func init() { PropertyName: "java_tests", }, }) - - android.PostDepsMutators(RegisterPostDepsMutators) } func RegisterJavaBuildComponents(ctx android.RegistrationContext) { @@ -84,44 +80,6 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) } -func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("ordered_system_server_jars", systemServerJarsDepsMutator) -} - -var ( - dexpreoptedSystemServerJarsKey = android.NewOnceKey("dexpreoptedSystemServerJars") - dexpreoptedSystemServerJarsLock sync.Mutex -) - -func DexpreoptedSystemServerJars(config android.Config) *[]string { - return config.Once(dexpreoptedSystemServerJarsKey, func() interface{} { - return &[]string{} - }).(*[]string) -} - -// A PostDepsMutator pass that enforces total order on non-updatable system server jars. A total -// order is neededed because such jars must be dexpreopted together (each jar on the list must have -// all preceding jars in its class loader context). The total order must be compatible with the -// partial order imposed by genuine dependencies between system server jars (which is not always -// respected by the PRODUCT_SYSTEM_SERVER_JARS variable). -// -// An earlier mutator pass creates genuine dependencies, and this pass traverses the jars in that -// order (which is partial and non-deterministic). This pass adds additional dependencies between -// jars, making the order total and deterministic. It also constructs a global ordered list. -func systemServerJarsDepsMutator(ctx android.BottomUpMutatorContext) { - jars := dexpreopt.NonUpdatableSystemServerJars(ctx, dexpreopt.GetGlobalConfig(ctx)) - name := ctx.ModuleName() - if android.InList(name, jars) { - dexpreoptedSystemServerJarsLock.Lock() - defer dexpreoptedSystemServerJarsLock.Unlock() - jars := DexpreoptedSystemServerJars(ctx.Config()) - for _, dep := range *jars { - ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerDepTag, dep) - } - *jars = append(*jars, name) - } -} - func (j *Module) checkSdkVersion(ctx android.ModuleContext) { if j.SocSpecific() || j.DeviceSpecific() || (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { @@ -705,11 +663,6 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } else if j.shouldInstrumentStatic(ctx) { ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent") } - - // services depend on com.android.location.provider, but dependency in not registered in a Blueprint file - if ctx.ModuleName() == "services" { - ctx.AddDependency(ctx.Module(), dexpreopt.SystemServerForcedDepTag, "com.android.location.provider") - } } func hasSrcExt(srcs []string, ext string) bool { -- cgit v1.2.3-59-g8ed1b From 688de9af5d4089f58a8f98ad8594595bd7ff3688 Mon Sep 17 00:00:00 2001 From: Songchun Fan Date: Tue, 24 Mar 2020 20:32:24 -0700 Subject: [soong] new field in Android.bp to request APK signing V4 If "v4_signature: true" is set, the v4 signature file, named [outputApkFile].idsig will be generated along side the outputApkFile. Test: m nothing Test: atest PackageManagerShellCommandIncrementalTest BUG: 149354175 Change-Id: Ie84725a15406f96f65042ea9909460e4eb34d57f --- java/app.go | 22 ++++++++++++++++---- java/app_builder.go | 16 ++++++++++---- java/app_test.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ java/java.go | 4 ++++ 4 files changed, 94 insertions(+), 8 deletions(-) (limited to 'java/java.go') diff --git a/java/app.go b/java/app.go index bfa25a23c..7a444ca77 100755 --- a/java/app.go +++ b/java/app.go @@ -510,14 +510,28 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { // Build a final signed app package. packageFile := android.PathForModuleOut(ctx, a.installApkName+".apk") - CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps) + v4SigningRequested := Bool(a.Module.deviceProperties.V4_signature) + var v4SignatureFile android.WritablePath = nil + if v4SigningRequested { + v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+".apk.idsig") + } + CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile) a.outputFile = packageFile + if v4SigningRequested { + a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) + } for _, split := range a.aapt.splits { // Sign the split APKs packageFile := android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk") - CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps) + if v4SigningRequested { + v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig") + } + CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile) a.extraOutputFiles = append(a.extraOutputFiles, packageFile) + if v4SigningRequested { + a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile) + } } // Build an app bundle. @@ -1105,7 +1119,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext } a.certificate = certificates[0] signed := android.PathForModuleOut(ctx, "signed", ctx.ModuleName()+".apk") - SignAppPackage(ctx, signed, dexOutput, certificates) + SignAppPackage(ctx, signed, dexOutput, certificates, nil) a.outputFile = signed } else { alignedApk := android.PathForModuleOut(ctx, "zip-aligned", ctx.ModuleName()+".apk") @@ -1310,7 +1324,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC _, certificates := collectAppDeps(ctx, false) certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") - SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates) + SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil) r.certificate = certificates[0] r.outputFile = signed diff --git a/java/app_builder.go b/java/app_builder.go index 5e7fbe6de..b2780bc90 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -45,7 +45,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk", }) func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath, - packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) { + packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath) { unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk" unsignedApk := android.PathForModuleOut(ctx, unsignedApkName) @@ -66,10 +66,10 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa Implicits: deps, }) - SignAppPackage(ctx, outputFile, unsignedApk, certificates) + SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile) } -func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate) { +func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, unsignedApk android.Path, certificates []Certificate, v4SignatureFile android.WritablePath) { var certificateArgs []string var deps android.Paths @@ -78,14 +78,22 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u deps = append(deps, c.Pem, c.Key) } + outputFiles := android.WritablePaths{signedApk} + var flag string = "" + if v4SignatureFile != nil { + outputFiles = append(outputFiles, v4SignatureFile) + flag = "--enable-v4" + } + ctx.Build(pctx, android.BuildParams{ Rule: Signapk, Description: "signapk", - Output: signedApk, + Outputs: outputFiles, Input: unsignedApk, Implicits: deps, Args: map[string]string{ "certificates": strings.Join(certificateArgs, " "), + "flags": flag, }, }) } diff --git a/java/app_test.go b/java/app_test.go index dfd85711b..10503e727 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1073,6 +1073,66 @@ func TestCertificates(t *testing.T) { } } +func TestRequestV4SigningFlag(t *testing.T) { + testCases := []struct { + name string + bp string + expected string + }{ + { + name: "default", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + } + `, + expected: "", + }, + { + name: "default", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + v4_signature: false, + } + `, + expected: "", + }, + { + name: "module certificate property", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + v4_signature: true, + } + `, + expected: "--enable-v4", + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + config := testAppConfig(nil, test.bp, nil) + ctx := testContext() + + run(t, ctx, config) + foo := ctx.ModuleForTests("foo", "android_common") + + signapk := foo.Output("foo.apk") + signFlags := signapk.Args["flags"] + if test.expected != signFlags { + t.Errorf("Incorrect signing flags, expected: %q, got: %q", test.expected, signFlags) + } + }) + } +} + func TestPackageNameOverride(t *testing.T) { testCases := []struct { name string diff --git a/java/java.go b/java/java.go index 46adedcd1..dc0b27244 100644 --- a/java/java.go +++ b/java/java.go @@ -319,6 +319,10 @@ type CompilerDeviceProperties struct { UncompressDex bool `blueprint:"mutated"` IsSDKLibrary bool `blueprint:"mutated"` + + // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file. + // Defaults to false. + V4_signature *bool } func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { -- cgit v1.2.3-59-g8ed1b From 37ca4a1e0dfab898a8abc61c6f62b2d7fc1119e3 Mon Sep 17 00:00:00 2001 From: Jaewoong Jung Date: Thu, 26 Mar 2020 14:01:48 -0700 Subject: Add code coverage support to android_app JNI libs. This is a cherry-pick change. Test: Built mainline module coverage data Bug: 152117890 Change-Id: I47bf3e5d6e78c4518729bdb52616e248156d3cec Merged-In: I47bf3e5d6e78c4518729bdb52616e248156d3cec --- apex/androidmk.go | 4 ++++ java/androidmk.go | 6 +++++- java/app.go | 42 ++++++++++++++++++++++++++++++++++++++---- java/java.go | 7 ++++--- 4 files changed, 51 insertions(+), 8 deletions(-) (limited to 'java/java.go') diff --git a/apex/androidmk.go b/apex/androidmk.go index 9a29687c2..2303efe58 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/cc" + "android/soong/java" "github.com/google/blueprint/proptools" ) @@ -181,6 +182,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.apk.apk fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.builtFile.Base(), ".apk")) + if app, ok := fi.module.(*java.AndroidApp); ok && len(app.JniCoverageOutputs()) > 0 { + fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", strings.Join(app.JniCoverageOutputs().Strings(), " ")) + } fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_app_prebuilt.mk") } else if fi.class == nativeSharedLib || fi.class == nativeExecutable || fi.class == nativeTest { fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.builtFile.Base()) diff --git a/java/androidmk.go b/java/androidmk.go index a220cce70..ee2437aa0 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -275,7 +275,7 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries { } func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { - if !app.IsForPlatform() { + if !app.IsForPlatform() || app.appProperties.HideFromMake { return []android.AndroidMkEntries{android.AndroidMkEntries{ Disabled: true, }} @@ -288,6 +288,7 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { func(entries *android.AndroidMkEntries) { // App module names can be overridden. entries.SetString("LOCAL_MODULE", app.installApkName) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", app.appProperties.PreventInstall) entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", app.exportPackage) if app.dexJarFile != nil { entries.SetPath("LOCAL_SOONG_DEX_JAR", app.dexJarFile) @@ -347,6 +348,9 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries { for _, jniLib := range app.installJniLibs { entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name) } + if len(app.jniCoverageOutputs) > 0 { + entries.AddStrings("LOCAL_PREBUILT_COVERAGE_ARCHIVE", app.jniCoverageOutputs.Strings()...) + } if len(app.dexpreopter.builtInstalled) > 0 { entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", app.dexpreopter.builtInstalled) } diff --git a/java/app.go b/java/app.go index 7a444ca77..f9992d885 100755 --- a/java/app.go +++ b/java/app.go @@ -105,6 +105,11 @@ type appProperties struct { // If set, find and merge all NOTICE files that this module and its dependencies have and store // it in the APK as an asset. Embed_notices *bool + + // cc.Coverage related properties + PreventInstall bool `blueprint:"mutated"` + HideFromMake bool `blueprint:"mutated"` + IsCoverageVariant bool `blueprint:"mutated"` } // android_app properties that can be overridden by override_android_app @@ -133,7 +138,8 @@ type AndroidApp struct { overridableAppProperties overridableAppProperties - installJniLibs []jniLib + installJniLibs []jniLib + jniCoverageOutputs android.Paths bundleFile android.Path @@ -171,6 +177,10 @@ func (a *AndroidApp) Certificate() Certificate { return a.certificate } +func (a *AndroidApp) JniCoverageOutputs() android.Paths { + return a.jniCoverageOutputs +} + var _ AndroidLibraryDependency = (*AndroidApp)(nil) type Certificate struct { @@ -373,6 +383,11 @@ func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext if a.shouldEmbedJnis(ctx) { jniJarFile = android.PathForModuleOut(ctx, "jnilibs.zip") TransformJniLibsToJar(ctx, jniJarFile, jniLibs, a.useEmbeddedNativeLibs(ctx)) + for _, jni := range jniLibs { + if jni.coverageFile.Valid() { + a.jniCoverageOutputs = append(a.jniCoverageOutputs, jni.coverageFile.Path()) + } + } } else { a.installJniLibs = jniLibs } @@ -572,9 +587,10 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps if lib.Valid() { jniLibs = append(jniLibs, jniLib{ - name: ctx.OtherModuleName(module), - path: path, - target: module.Target(), + name: ctx.OtherModuleName(module), + path: path, + target: module.Target(), + coverageFile: dep.CoverageOutputFile(), }) } else { ctx.ModuleErrorf("dependency %q missing output file", otherName) @@ -628,6 +644,24 @@ func (a *AndroidApp) Privileged() bool { return Bool(a.appProperties.Privileged) } +func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { + return ctx.Device() && (ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled()) +} + +func (a *AndroidApp) PreventInstall() { + a.appProperties.PreventInstall = true +} + +func (a *AndroidApp) HideFromMake() { + a.appProperties.HideFromMake = true +} + +func (a *AndroidApp) MarkAsCoverageVariant(coverage bool) { + a.appProperties.IsCoverageVariant = coverage +} + +var _ cc.Coverage = (*AndroidApp)(nil) + // android_app compiles sources and Android resources into an Android application package `.apk` file. func AndroidAppFactory() android.Module { module := &AndroidApp{} diff --git a/java/java.go b/java/java.go index dc0b27244..55ad8b019 100644 --- a/java/java.go +++ b/java/java.go @@ -538,9 +538,10 @@ func (s sdkDep) hasFrameworkLibs() bool { } type jniLib struct { - name string - path android.Path - target android.Target + name string + path android.Path + target android.Target + coverageFile android.OptionalPath } func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool { -- cgit v1.2.3-59-g8ed1b From 1e65f94a4b2cc7dea1896937c2068b87c899c465 Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Fri, 27 Mar 2020 19:39:48 +0000 Subject: Add a Tag field to dist to dist a tagged output Make java_library support this mode of output, to allow callers to dist the classes.jar file rather than the dexed jar file. Bug: 152618077 Test: followup CL Change-Id: I5ba6949833a0fbb95376142aec5096ff5f084c00 --- java/androidmk.go | 1 + java/androidmk_test.go | 36 ++++++++++++++++++++++++++++++++++++ java/java.go | 23 ++++++++++++++++++++++- 3 files changed, 59 insertions(+), 1 deletion(-) (limited to 'java/java.go') diff --git a/java/androidmk.go b/java/androidmk.go index a220cce70..e18fbb427 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -72,6 +72,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if !hideFromMake { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", + DistFile: android.OptionalPathForPath(library.distFile), OutputFile: android.OptionalPathForPath(library.outputFile), Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk", ExtraEntries: []android.AndroidMkExtraEntriesFunc{ diff --git a/java/androidmk_test.go b/java/androidmk_test.go index acc6bf039..7daa6244f 100644 --- a/java/androidmk_test.go +++ b/java/androidmk_test.go @@ -16,6 +16,7 @@ package java import ( "reflect" + "strings" "testing" "android/soong/android" @@ -133,3 +134,38 @@ func TestHostdexSpecificRequired(t *testing.T) { t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual) } } + +func TestDistWithTag(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo_without_tag", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["hi"], + }, + } + java_library { + name: "foo_with_tag", + srcs: ["a.java"], + compile_dex: true, + dist: { + targets: ["hi"], + tag: ".jar", + }, + } + `) + + without_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_without_tag", "android_common").Module()) + with_tag_entries := android.AndroidMkEntriesForTest(t, config, "", ctx.ModuleForTests("foo_with_tag", "android_common").Module()) + + if len(without_tag_entries) != 2 || len(with_tag_entries) != 2 { + t.Errorf("two mk entries per module expected, got %d and %d", len(without_tag_entries), len(with_tag_entries)) + } + if !with_tag_entries[0].DistFile.Valid() || !strings.Contains(with_tag_entries[0].DistFile.String(), "/javac/foo_with_tag.jar") { + t.Errorf("expected classes.jar DistFile, got %v", with_tag_entries[0].DistFile) + } + if without_tag_entries[0].DistFile.Valid() { + t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile) + } +} diff --git a/java/java.go b/java/java.go index dc0b27244..edf83cfe1 100644 --- a/java/java.go +++ b/java/java.go @@ -419,6 +419,8 @@ type Module struct { // list of the xref extraction files kytheFiles android.Paths + + distFile android.Path } func (j *Module) OutputFiles(tag string) (android.Paths, error) { @@ -1775,9 +1777,18 @@ func (j *Module) IsInstallable() bool { // Java libraries (.jar file) // +type LibraryProperties struct { + Dist struct { + // The tag of the output of this module that should be output. + Tag *string `android:"arch_variant"` + } `android:"arch_variant"` +} + type Library struct { Module + libraryProperties LibraryProperties + InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } @@ -1821,6 +1832,15 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...) } + + // Verify Dist.Tag is set to a supported output + if j.libraryProperties.Dist.Tag != nil { + distFiles, err := j.OutputFiles(*j.libraryProperties.Dist.Tag) + if err != nil { + ctx.PropertyErrorf("dist.tag", "%s", err.Error()) + } + j.distFile = distFiles[0] + } } func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -1945,7 +1965,8 @@ func LibraryFactory() android.Module { &module.Module.properties, &module.Module.deviceProperties, &module.Module.dexpreoptProperties, - &module.Module.protoProperties) + &module.Module.protoProperties, + &module.libraryProperties) android.InitApexModule(module) android.InitSdkAwareModule(module) -- cgit v1.2.3-59-g8ed1b From e5ac15a1b74094e38e65db7b3dee29e422e15b2b Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Wed, 8 Apr 2020 19:09:30 +0100 Subject: Check updatable APKs compile against managed SDKs. As a follow up, this property will be set to APKs participating in mainline program. Bug: 153333044 Test: m Change-Id: I6ea2f3c1d26992259e4e9e6a6d8cecf091d39c43 Merged-In: I6ea2f3c1d26992259e4e9e6a6d8cecf091d39c43 (cherry picked from commit 2db1c3f1c432740f734917e04b2b847066c8d508) Exempt-From-Owner-Approval: clean cherry-pick --- java/app.go | 18 ++++++++-- java/app_test.go | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ java/java.go | 26 ++++++++------ java/sdk.go | 21 ++++++++++++ 4 files changed, 154 insertions(+), 13 deletions(-) (limited to 'java/java.go') diff --git a/java/app.go b/java/app.go index f9992d885..8e11b0388 100755 --- a/java/app.go +++ b/java/app.go @@ -110,6 +110,10 @@ type appProperties struct { PreventInstall bool `blueprint:"mutated"` HideFromMake bool `blueprint:"mutated"` IsCoverageVariant bool `blueprint:"mutated"` + + // Whether this app is considered mainline updatable or not. When set to true, this will enforce + // additional rules for making sure that the APK is truly updatable. Default is false. + Updatable *bool } // android_app properties that can be overridden by override_android_app @@ -242,11 +246,21 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon } func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { - a.checkPlatformAPI(ctx) - a.checkSdkVersion(ctx) + a.checkAppSdkVersions(ctx) a.generateAndroidBuildActions(ctx) } +func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { + if Bool(a.appProperties.Updatable) { + if !a.sdkVersion().stable() { + ctx.PropertyErrorf("sdk_version", "Updatable apps must use stable SDKs, found %v", a.sdkVersion()) + } + } + + a.checkPlatformAPI(ctx) + a.checkSdkVersions(ctx) +} + // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { diff --git a/java/app_test.go b/java/app_test.go index 10503e727..0968c9a33 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -264,6 +264,108 @@ func TestAndroidAppLinkType(t *testing.T) { `) } +func TestUpdatableApps(t *testing.T) { + testCases := []struct { + name string + bp string + expectedError string + }{ + { + name: "Stable public SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "29", + updatable: true, + }`, + }, + { + name: "Stable system SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "system_29", + updatable: true, + }`, + }, + { + name: "Current public SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + updatable: true, + }`, + }, + { + name: "Current system SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "system_current", + updatable: true, + }`, + }, + { + name: "Current module SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "module_current", + updatable: true, + }`, + }, + { + name: "Current core SDK", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "core_current", + updatable: true, + }`, + }, + { + name: "No Platform APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + platform_apis: true, + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDKs", + }, + { + name: "No Core Platform APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "core_platform", + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDKs", + }, + { + name: "No unspecified APIs", + bp: `android_app { + name: "foo", + srcs: ["a.java"], + updatable: true, + }`, + expectedError: "Updatable apps must use stable SDK", + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if test.expectedError == "" { + testJava(t, test.bp) + } else { + testJavaError(t, test.expectedError, test.bp) + } + }) + } +} + func TestResourceDirs(t *testing.T) { testCases := []struct { name string diff --git a/java/java.go b/java/java.go index d67ff874d..79568131d 100644 --- a/java/java.go +++ b/java/java.go @@ -80,7 +80,7 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) } -func (j *Module) checkSdkVersion(ctx android.ModuleContext) { +func (j *Module) checkSdkVersions(ctx android.ModuleContext) { if j.SocSpecific() || j.DeviceSpecific() || (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { if sc, ok := ctx.Module().(sdkContext); ok { @@ -90,6 +90,18 @@ func (j *Module) checkSdkVersion(ctx android.ModuleContext) { } } } + + ctx.VisitDirectDeps(func(module android.Module) { + tag := ctx.OtherModuleDependencyTag(module) + switch module.(type) { + // TODO(satayev): cover other types as well, e.g. imports + case *Library, *AndroidLibrary: + switch tag { + case bootClasspathTag, libTag, staticLibTag, java9LibTag: + checkLinkType(ctx, j, module.(linkTypeContext), tag.(dependencyTag)) + } + } + }) } func (j *Module) checkPlatformAPI(ctx android.ModuleContext) { @@ -892,15 +904,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { // Handled by AndroidApp.collectAppDeps return } - switch module.(type) { - case *Library, *AndroidLibrary: - if to, ok := module.(linkTypeContext); ok { - switch tag { - case bootClasspathTag, libTag, staticLibTag: - checkLinkType(ctx, j, to, tag.(dependencyTag)) - } - } - } + switch dep := module.(type) { case SdkLibraryDependency: switch tag { @@ -1817,7 +1821,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo } func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { - j.checkSdkVersion(ctx) + j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) diff --git a/java/sdk.go b/java/sdk.go index 4c9ba2b55..2b5a21d89 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -147,6 +147,10 @@ type sdkSpec struct { raw string } +func (s sdkSpec) String() string { + return fmt.Sprintf("%s_%s", s.kind, s.version) +} + // valid checks if this sdkSpec is well-formed. Note however that true doesn't mean that the // specified SDK actually exists. func (s sdkSpec) valid() bool { @@ -158,6 +162,23 @@ func (s sdkSpec) specified() bool { return s.valid() && s.kind != sdkPrivate } +// whether the API surface is managed and versioned, i.e. has .txt file that +// get frozen on SDK freeze and changes get reviewed by API council. +func (s sdkSpec) stable() bool { + if !s.specified() { + return false + } + switch s.kind { + case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer: + return true + case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate: + return false + default: + panic(fmt.Errorf("unknown sdkKind=%v", s.kind)) + } + return false +} + // prebuiltSdkAvailableForUnbundledBuilt tells whether this sdkSpec can have a prebuilt SDK // that can be used for unbundled builds. func (s sdkSpec) prebuiltSdkAvailableForUnbundledBuild() bool { -- cgit v1.2.3-59-g8ed1b From 2b9e3d39d9548e7e333bd0d56c42a88239483706 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 28 Feb 2020 14:39:53 +0000 Subject: Simplify java library sdk member code Adds the accessor function for retrieving the impl/header jars to the librarySdkMemberType structure instead of passing it into its buildSnapshot() method. That enabled: * The removal of the [header/impl]LibrarySdkMemberType structs. * The removal of their implementations of BuildSnapshot. * Replacing buildSnapshot() with BuildSnapshot() This will make subsequent refactoring of the SdkMemberType interface a little simpler. Bug: 153306490 Test: m nothing Bug: 150451422 Merged-In: I1f96986bb497cf9d9df9916e40065f66b35a4704 Change-Id: I1f96986bb497cf9d9df9916e40065f66b35a4704 --- java/java.go | 64 ++++++++++++++++++++++-------------------------------------- 1 file changed, 23 insertions(+), 41 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 79568131d..e4b51c00c 100644 --- a/java/java.go +++ b/java/java.go @@ -39,11 +39,17 @@ func init() { // Register sdk member types. android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType) - android.RegisterSdkMemberType(&implLibrarySdkMemberType{ - librarySdkMemberType{ - android.SdkMemberTypeBase{ - PropertyName: "java_libs", - }, + android.RegisterSdkMemberType(&librarySdkMemberType{ + android.SdkMemberTypeBase{ + PropertyName: "java_libs", + }, + func(j *Library) android.Path { + implementationJars := j.ImplementationJars() + if len(implementationJars) != 1 { + panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) + } + + return implementationJars[0] }, }) @@ -1870,6 +1876,10 @@ func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) strin type librarySdkMemberType struct { android.SdkMemberTypeBase + + // Function to retrieve the appropriate output jar (implementation or header) from + // the library. + jarToExportGetter func(j *Library) android.Path } func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) { @@ -1881,11 +1891,7 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { return ok } -func (mt *librarySdkMemberType) buildSnapshot( - sdkModuleContext android.ModuleContext, - builder android.SnapshotBuilder, - member android.SdkMember, - jarToExportGetter func(j *Library) android.Path) { +func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { variants := member.Variants() if len(variants) != 1 { @@ -1897,7 +1903,7 @@ func (mt *librarySdkMemberType) buildSnapshot( variant := variants[0] j := variant.(*Library) - exportedJar := jarToExportGetter(j) + exportedJar := mt.jarToExportGetter(j) snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) @@ -1913,43 +1919,19 @@ func (mt *librarySdkMemberType) buildSnapshot( module.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) } -var javaHeaderLibsSdkMemberType android.SdkMemberType = &headerLibrarySdkMemberType{ - librarySdkMemberType{ - android.SdkMemberTypeBase{ - PropertyName: "java_header_libs", - SupportsSdk: true, - }, +var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{ + android.SdkMemberTypeBase{ + PropertyName: "java_header_libs", + SupportsSdk: true, }, -} - -type headerLibrarySdkMemberType struct { - librarySdkMemberType -} - -func (mt *headerLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { - mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path { + func(j *Library) android.Path { headerJars := j.HeaderJars() if len(headerJars) != 1 { panic(fmt.Errorf("there must be only one header jar from %q", j.Name())) } return headerJars[0] - }) -} - -type implLibrarySdkMemberType struct { - librarySdkMemberType -} - -func (mt *implLibrarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { - mt.librarySdkMemberType.buildSnapshot(sdkModuleContext, builder, member, func(j *Library) android.Path { - implementationJars := j.ImplementationJars() - if len(implementationJars) != 1 { - panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) - } - - return implementationJars[0] - }) + }, } // java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well. -- cgit v1.2.3-59-g8ed1b From d76209b690540d1a5f626ad329db09874375d89a Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 2 Mar 2020 11:33:02 +0000 Subject: Refactor java_library/java_test snapshot processing Adds support for handling the common arch to the sdk module type snapshot generation code and then refactors the java_library and java_test snapshot processing to take advantage of that. Bug: 150451422 Bug: 153306490 Test: m nothing Merged-In: If746f375f1c4288ab6b67c7d216593b70258b043 Change-Id: If746f375f1c4288ab6b67c7d216593b70258b043 --- java/java.go | 113 ++++++++++++++++++++++++++++++++++++---------------------- sdk/update.go | 66 +++++++++++++++++++++------------- 2 files changed, 111 insertions(+), 68 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index e4b51c00c..fbb195510 100644 --- a/java/java.go +++ b/java/java.go @@ -1866,12 +1866,12 @@ const ( ) // path to the jar file of a java library. Relative to / -func sdkSnapshotFilePathForJar(member android.SdkMember) string { - return sdkSnapshotFilePathForMember(member, jarFileSuffix) +func sdkSnapshotFilePathForJar(name string) string { + return sdkSnapshotFilePathForMember(name, jarFileSuffix) } -func sdkSnapshotFilePathForMember(member android.SdkMember, suffix string) string { - return filepath.Join(javaDir, member.Name()+suffix) +func sdkSnapshotFilePathForMember(name string, suffix string) string { + return filepath.Join(javaDir, name+suffix) } type librarySdkMemberType struct { @@ -1891,32 +1891,46 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { return ok } -func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { +func (mt *librarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { + return builder.AddPrebuiltModule(member, "java_import") +} - variants := member.Variants() - if len(variants) != 1 { - sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name()) - for _, variant := range variants { - sdkModuleContext.ModuleErrorf(" %q", variant) - } - } - variant := variants[0] +func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { + return &librarySdkMemberProperties{memberType: mt} +} + +type librarySdkMemberProperties struct { + android.SdkMemberPropertiesBase + + memberType *librarySdkMemberType + + library *Library + jarToExport android.Path +} + +func (p *librarySdkMemberProperties) PopulateFromVariant(variant android.SdkAware) { j := variant.(*Library) - exportedJar := mt.jarToExportGetter(j) - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member) - builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) + p.library = j + p.jarToExport = p.memberType.jarToExportGetter(j) +} + +func (p *librarySdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { + if p.jarToExport != nil { + exportedJar := p.jarToExport + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.library.Name()) + builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) - for _, dir := range j.AidlIncludeDirs() { - // TODO(jiyong): copy parcelable declarations only - aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil) - for _, file := range aidlFiles { - builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file)) + for _, dir := range p.library.AidlIncludeDirs() { + // TODO(jiyong): copy parcelable declarations only + aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil) + for _, file := range aidlFiles { + builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file)) + } } - } - module := builder.AddPrebuiltModule(member, "java_import") - module.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + } } var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{ @@ -2082,31 +2096,44 @@ func (mt *testSdkMemberType) IsInstance(module android.Module) bool { return ok } -func (mt *testSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) { - variants := member.Variants() - if len(variants) != 1 { - sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name()) - for _, variant := range variants { - sdkModuleContext.ModuleErrorf(" %q", variant) - } - } - variant := variants[0] - j := variant.(*Test) +func (mt *testSdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { + return builder.AddPrebuiltModule(member, "java_test_import") +} + +func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { + return &testSdkMemberProperties{} +} + +type testSdkMemberProperties struct { + android.SdkMemberPropertiesBase - implementationJars := j.ImplementationJars() + test *Test + jarToExport android.Path +} + +func (p *testSdkMemberProperties) PopulateFromVariant(variant android.SdkAware) { + test := variant.(*Test) + + implementationJars := test.ImplementationJars() if len(implementationJars) != 1 { - panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) + panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name())) } - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(member) - builder.CopyToSnapshot(implementationJars[0], snapshotRelativeJavaLibPath) + p.test = test + p.jarToExport = implementationJars[0] +} + +func (p *testSdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { + if p.jarToExport != nil { + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.test.Name()) + builder.CopyToSnapshot(p.jarToExport, snapshotRelativeJavaLibPath) - snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(member, testConfigSuffix) - builder.CopyToSnapshot(j.testConfig, snapshotRelativeTestConfigPath) + snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.test.Name(), testConfigSuffix) + builder.CopyToSnapshot(p.test.testConfig, snapshotRelativeTestConfigPath) - module := builder.AddPrebuiltModule(member, "java_test_import") - module.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) - module.AddProperty("test_config", snapshotRelativeTestConfigPath) + propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath) + } } // java_test builds a and links sources into a `.jar` file for the device, and possibly for the host as well, and diff --git a/sdk/update.go b/sdk/update.go index 352cc32e4..84b6c18f4 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -676,50 +676,66 @@ func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, build osInfo := &osTypeSpecificInfo{} osInfo.Properties = memberType.CreateVariantPropertiesStruct() variants := member.Variants() + commonArch := false for _, variant := range variants { var properties android.SdkMemberProperties // Get the info associated with the arch type inside the os info. archType := variant.Target().Arch.ArchType - archInfo := &archTypeSpecificInfo{archType: archType} - properties = memberType.CreateVariantPropertiesStruct() - archInfo.Properties = properties + if archType.Name == "common" { + // The arch type is common so populate the common properties directly. + properties = osInfo.Properties - osInfo.archTypes = append(osInfo.archTypes, archInfo) + commonArch = true + } else { + archInfo := &archTypeSpecificInfo{archType: archType} + properties = memberType.CreateVariantPropertiesStruct() + archInfo.Properties = properties + + osInfo.archTypes = append(osInfo.archTypes, archInfo) + } properties.PopulateFromVariant(variant) } - var archProperties []android.SdkMemberProperties - for _, archInfo := range osInfo.archTypes { - archProperties = append(archProperties, archInfo.Properties) - } + if commonArch { + if len(variants) != 1 { + panic("Expected to only have 1 variant when arch type is common but found " + string(len(variants))) + } + } else { + var archProperties []android.SdkMemberProperties + for _, archInfo := range osInfo.archTypes { + archProperties = append(archProperties, archInfo.Properties) + } - extractCommonProperties(osInfo.Properties, archProperties) + extractCommonProperties(osInfo.Properties, archProperties) - // Choose setting for compile_multilib that is appropriate for the arch variants supplied. - var multilib string - archVariantCount := len(osInfo.archTypes) - if archVariantCount == 2 { - multilib = "both" - } else if archVariantCount == 1 { - if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") { - multilib = "64" - } else { - multilib = "32" + // Choose setting for compile_multilib that is appropriate for the arch variants supplied. + var multilib string + archVariantCount := len(osInfo.archTypes) + if archVariantCount == 2 { + multilib = "both" + } else if archVariantCount == 1 { + if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") { + multilib = "64" + } else { + multilib = "32" + } } - } - osInfo.Properties.Base().Compile_multilib = multilib + osInfo.Properties.Base().Compile_multilib = multilib + } osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, bpModule) - archPropertySet := bpModule.AddPropertySet("arch") - for _, av := range osInfo.archTypes { - archTypePropertySet := archPropertySet.AddPropertySet(av.archType.Name) + if !commonArch { + archPropertySet := bpModule.AddPropertySet("arch") + for _, av := range osInfo.archTypes { + archTypePropertySet := archPropertySet.AddPropertySet(av.archType.Name) - av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet) + av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet) + } } memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule) -- cgit v1.2.3-59-g8ed1b From 9b358d7a587ce04d1e9a23d893fa2cac161ecffb Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Mon, 2 Mar 2020 10:16:35 +0000 Subject: Add support for multiple os types Updates the member snapshot creation code to support multiple os types. It basically sorts the variants by os type, then applies the code to optimize the arch properties and then it optimizes the properties that are common across architectures and extracts any properties that are common across os types. The java and cc member types needed to be modified to make the location of the generated files within the snapshot os type dependent when there is more than one os type. That was done by adding an OsPrefix() method to the SdkMemberPropertiesBase which returns the os prefix to use when there is > 1 os type and otherwise returns an empty string. Added three tests, one for cc shared libraries, one for cc binary and one for java header libraries. Bug: 150451422 Bug: 153306490 Test: m nothing Merged-In: I08f5fbdd7852b06c9a9a2f1cfdc364338a3d5bac Change-Id: I08f5fbdd7852b06c9a9a2f1cfdc364338a3d5bac --- android/arch.go | 10 +- android/sdk.go | 21 +++- cc/binary_sdk_member.go | 2 +- cc/library_sdk_member.go | 2 +- cc/testing.go | 23 +++- java/java.go | 16 +-- sdk/cc_sdk_test.go | 287 ++++++++++++++++++++++++++++++++++++++++++++++- sdk/java_sdk_test.go | 66 +++++++++++ sdk/testing.go | 2 +- sdk/update.go | 223 ++++++++++++++++++++++++++++-------- 10 files changed, 582 insertions(+), 70 deletions(-) (limited to 'java/java.go') diff --git a/android/arch.go b/android/arch.go index 922548ea1..e4404868b 100644 --- a/android/arch.go +++ b/android/arch.go @@ -596,7 +596,7 @@ var BuildOs = func() OsType { }() var ( - osTypeList []OsType + OsTypeList []OsType commonTargetMap = make(map[string]Target) NoOsType OsType @@ -672,7 +672,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType { DefaultDisabled: defDisabled, } - osTypeList = append(osTypeList, os) + OsTypeList = append(OsTypeList, os) if _, found := commonTargetMap[name]; found { panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name)) @@ -684,7 +684,7 @@ func NewOsType(name string, class OsClass, defDisabled bool) OsType { } func osByName(name string) OsType { - for _, os := range osTypeList { + for _, os := range OsTypeList { if os.Name == name { return os } @@ -750,7 +750,7 @@ func osMutator(mctx BottomUpMutatorContext) { var moduleOSList []OsType - for _, os := range osTypeList { + for _, os := range OsTypeList { supportedClass := false for _, osClass := range osClasses { if os.Class == osClass { @@ -1071,7 +1071,7 @@ func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc { "Arm_on_x86", "Arm_on_x86_64", } - for _, os := range osTypeList { + for _, os := range OsTypeList { targets = append(targets, os.Field) for _, archType := range osArchTypeMap[os] { diff --git a/android/sdk.go b/android/sdk.go index f28c39215..969e21adb 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -448,10 +448,29 @@ func RegisterSdkMemberType(memberType SdkMemberType) { // Base structure for all implementations of SdkMemberProperties. // -// Contains common properties that apply across many different member types. +// Contains common properties that apply across many different member types. These +// are not affected by the optimization to extract common values. type SdkMemberPropertiesBase struct { // The setting to use for the compile_multilib property. Compile_multilib string + + // The number of unique os types supported by the member variants. + Os_count int + + // The os type for which these properties refer. + Os OsType +} + +// The os prefix to use for any file paths in the sdk. +// +// Is an empty string if the member only provides variants for a single os type, otherwise +// is the OsType.Name. +func (b *SdkMemberPropertiesBase) OsPrefix() string { + if b.Os_count == 1 { + return "" + } else { + return b.Os.Name + } } func (b *SdkMemberPropertiesBase) Base() *SdkMemberPropertiesBase { diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go index eddf5b805..fc9b89e75 100644 --- a/cc/binary_sdk_member.go +++ b/cc/binary_sdk_member.go @@ -78,7 +78,7 @@ const ( // path to the native binary. Relative to / func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string { - return filepath.Join(lib.archType, + return filepath.Join(lib.OsPrefix(), lib.archType, nativeBinaryDir, lib.outputFile.Base()) } diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index a26269772..656df6969 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -254,7 +254,7 @@ const ( // path to the native library. Relative to / func nativeLibraryPathFor(lib *nativeLibInfoProperties) string { - return filepath.Join(lib.archType, + return filepath.Join(lib.OsPrefix(), lib.archType, nativeStubDir, lib.outputFile.Base()) } diff --git a/cc/testing.go b/cc/testing.go index 9652d216c..f85795b33 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -34,7 +34,7 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory) } -func GatherRequiredDepsForTest(os android.OsType) string { +func GatherRequiredDepsForTest(oses ...android.OsType) string { ret := ` toolchain_library { name: "libatomic", @@ -380,8 +380,9 @@ func GatherRequiredDepsForTest(os android.OsType) string { } ` - if os == android.Fuchsia { - ret += ` + for _, os := range oses { + if os == android.Fuchsia { + ret += ` cc_library { name: "libbioniccompat", stl: "none", @@ -391,6 +392,22 @@ func GatherRequiredDepsForTest(os android.OsType) string { stl: "none", } ` + } + if os == android.Windows { + ret += ` + toolchain_library { + name: "libwinpthread", + host_supported: true, + enabled: false, + target: { + windows: { + enabled: true, + }, + }, + src: "", + } + ` + } } return ret } diff --git a/java/java.go b/java/java.go index fbb195510..e3fa69d26 100644 --- a/java/java.go +++ b/java/java.go @@ -1866,12 +1866,12 @@ const ( ) // path to the jar file of a java library. Relative to / -func sdkSnapshotFilePathForJar(name string) string { - return sdkSnapshotFilePathForMember(name, jarFileSuffix) +func sdkSnapshotFilePathForJar(osPrefix, name string) string { + return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix) } -func sdkSnapshotFilePathForMember(name string, suffix string) string { - return filepath.Join(javaDir, name+suffix) +func sdkSnapshotFilePathForMember(osPrefix, name string, suffix string) string { + return filepath.Join(javaDir, osPrefix, name+suffix) } type librarySdkMemberType struct { @@ -1918,7 +1918,7 @@ func (p *librarySdkMemberProperties) PopulateFromVariant(variant android.SdkAwar func (p *librarySdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { if p.jarToExport != nil { exportedJar := p.jarToExport - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.library.Name()) + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.library.Name()) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) for _, dir := range p.library.AidlIncludeDirs() { @@ -2125,10 +2125,10 @@ func (p *testSdkMemberProperties) PopulateFromVariant(variant android.SdkAware) func (p *testSdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { if p.jarToExport != nil { - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.test.Name()) + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.test.Name()) builder.CopyToSnapshot(p.jarToExport, snapshotRelativeJavaLibPath) - snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.test.Name(), testConfigSuffix) + snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), p.test.Name(), testConfigSuffix) builder.CopyToSnapshot(p.test.testConfig, snapshotRelativeTestConfigPath) propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) @@ -2336,7 +2336,7 @@ func BinaryHostFactory() android.Module { // type ImportProperties struct { - Jars []string `android:"path"` + Jars []string `android:"path,arch_variant"` Sdk_version *string diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index 5366edfb5..11bc90238 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -25,11 +25,13 @@ func testSdkWithCc(t *testing.T, bp string) *testSdkResult { t.Helper() fs := map[string][]byte{ - "Test.cpp": nil, - "include/Test.h": nil, - "arm64/include/Arm64Test.h": nil, - "libfoo.so": nil, - "aidl/foo/bar/Test.aidl": nil, + "Test.cpp": nil, + "include/Test.h": nil, + "include-android/AndroidTest.h": nil, + "include-host/HostTest.h": nil, + "arm64/include/Arm64Test.h": nil, + "libfoo.so": nil, + "aidl/foo/bar/Test.aidl": nil, } return testSdkWithFs(t, bp, fs) } @@ -401,6 +403,108 @@ module_exports_snapshot { ) } +func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) { + // b/145598135 - Generating host snapshots for anything other than linux is not supported. + SkipIfNotLinux(t) + + result := testSdkWithCc(t, ` + module_exports { + name: "myexports", + device_supported: false, + host_supported: true, + native_binaries: ["mynativebinary"], + target: { + windows: { + enabled: true, + }, + }, + } + + cc_binary { + name: "mynativebinary", + device_supported: false, + host_supported: true, + srcs: [ + "Test.cpp", + ], + compile_multilib: "both", + system_shared_libs: [], + stl: "none", + target: { + windows: { + enabled: true, + }, + }, + } + `) + + result.CheckSnapshot("myexports", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_binary { + name: "myexports_mynativebinary@current", + sdk_member_name: "mynativebinary", + device_supported: false, + host_supported: true, + target: { + linux_glibc: { + compile_multilib: "both", + }, + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/bin/mynativebinary"], + }, + linux_glibc_x86: { + srcs: ["linux_glibc/x86/bin/mynativebinary"], + }, + windows: { + compile_multilib: "64", + }, + windows_x86_64: { + srcs: ["windows/x86_64/bin/mynativebinary.exe"], + }, + }, +} + +cc_prebuilt_binary { + name: "mynativebinary", + prefer: false, + device_supported: false, + host_supported: true, + target: { + linux_glibc: { + compile_multilib: "both", + }, + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/bin/mynativebinary"], + }, + linux_glibc_x86: { + srcs: ["linux_glibc/x86/bin/mynativebinary"], + }, + windows: { + compile_multilib: "64", + }, + windows_x86_64: { + srcs: ["windows/x86_64/bin/mynativebinary.exe"], + }, + }, +} + +module_exports_snapshot { + name: "myexports@current", + device_supported: false, + host_supported: true, + native_binaries: ["myexports_mynativebinary@current"], +} +`), + checkAllCopyRules(` +.intermediates/mynativebinary/linux_glibc_x86_64/mynativebinary -> linux_glibc/x86_64/bin/mynativebinary +.intermediates/mynativebinary/linux_glibc_x86/mynativebinary -> linux_glibc/x86/bin/mynativebinary +.intermediates/mynativebinary/windows_x86_64/mynativebinary.exe -> windows/x86_64/bin/mynativebinary.exe +`), + ) +} + func TestSnapshotWithCcSharedLibrary(t *testing.T) { result := testSdkWithCc(t, ` sdk { @@ -588,6 +692,99 @@ include/Test.h -> include/include/Test.h ) } +func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) { + // b/145598135 - Generating host snapshots for anything other than linux is not supported. + SkipIfNotLinux(t) + + result := testSdkWithCc(t, ` + sdk { + name: "mysdk", + device_supported: false, + host_supported: true, + native_shared_libs: ["mynativelib"], + target: { + windows: { + enabled: true, + }, + }, + } + + cc_library_shared { + name: "mynativelib", + device_supported: false, + host_supported: true, + srcs: [ + "Test.cpp", + ], + system_shared_libs: [], + stl: "none", + target: { + windows: { + enabled: true, + }, + }, + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_library_shared { + name: "mysdk_mynativelib@current", + sdk_member_name: "mynativelib", + device_supported: false, + host_supported: true, + target: { + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/lib/mynativelib.so"], + }, + linux_glibc_x86: { + srcs: ["linux_glibc/x86/lib/mynativelib.so"], + }, + windows_x86_64: { + srcs: ["windows/x86_64/lib/mynativelib.dll"], + }, + }, + stl: "none", + system_shared_libs: [], +} + +cc_prebuilt_library_shared { + name: "mynativelib", + prefer: false, + device_supported: false, + host_supported: true, + target: { + linux_glibc_x86_64: { + srcs: ["linux_glibc/x86_64/lib/mynativelib.so"], + }, + linux_glibc_x86: { + srcs: ["linux_glibc/x86/lib/mynativelib.so"], + }, + windows_x86_64: { + srcs: ["windows/x86_64/lib/mynativelib.dll"], + }, + }, + stl: "none", + system_shared_libs: [], +} + +sdk_snapshot { + name: "mysdk@current", + device_supported: false, + host_supported: true, + native_shared_libs: ["mysdk_mynativelib@current"], +} +`), + checkAllCopyRules(` +.intermediates/mynativelib/linux_glibc_x86_64_shared/mynativelib.so -> linux_glibc/x86_64/lib/mynativelib.so +.intermediates/mynativelib/linux_glibc_x86_shared/mynativelib.so -> linux_glibc/x86/lib/mynativelib.so +.intermediates/mynativelib/windows_x86_64_shared/mynativelib.dll -> windows/x86_64/lib/mynativelib.dll +`), + ) +} + func TestSnapshotWithCcStaticLibrary(t *testing.T) { result := testSdkWithCc(t, ` module_exports { @@ -958,3 +1155,83 @@ include/Test.h -> include/include/Test.h `), ) } + +func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) { + // b/145598135 - Generating host snapshots for anything other than linux is not supported. + SkipIfNotLinux(t) + + result := testSdkWithCc(t, ` + sdk { + name: "mysdk", + host_supported: true, + native_header_libs: ["mynativeheaders"], + } + + cc_library_headers { + name: "mynativeheaders", + host_supported: true, + system_shared_libs: [], + stl: "none", + export_system_include_dirs: ["include"], + target: { + android: { + export_include_dirs: ["include-android"], + }, + host: { + export_include_dirs: ["include-host"], + }, + }, + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_library_headers { + name: "mysdk_mynativeheaders@current", + sdk_member_name: "mynativeheaders", + host_supported: true, + export_system_include_dirs: ["include/include"], + target: { + android: { + export_include_dirs: ["include/include-android"], + }, + linux_glibc: { + export_include_dirs: ["include/include-host"], + }, + }, + stl: "none", + system_shared_libs: [], +} + +cc_prebuilt_library_headers { + name: "mynativeheaders", + prefer: false, + host_supported: true, + export_system_include_dirs: ["include/include"], + target: { + android: { + export_include_dirs: ["include/include-android"], + }, + linux_glibc: { + export_include_dirs: ["include/include-host"], + }, + }, + stl: "none", + system_shared_libs: [], +} + +sdk_snapshot { + name: "mysdk@current", + host_supported: true, + native_header_libs: ["mysdk_mynativeheaders@current"], +} +`), + checkAllCopyRules(` +include/Test.h -> include/include/Test.h +include-android/AndroidTest.h -> include/include-android/AndroidTest.h +include-host/HostTest.h -> include/include-host/HostTest.h +`), + ) +} diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index 9046eeca0..45da1f957 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -230,6 +230,72 @@ aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl ) } +func TestDeviceAndHostSnapshotWithJavaHeaderLibrary(t *testing.T) { + // b/145598135 - Generating host snapshots for anything other than linux is not supported. + SkipIfNotLinux(t) + + result := testSdkWithJava(t, ` + sdk { + name: "mysdk", + host_supported: true, + java_header_libs: ["myjavalib"], + } + + java_library { + name: "myjavalib", + host_supported: true, + srcs: ["Test.java"], + system_modules: "none", + sdk_version: "none", + compile_dex: true, + } + `) + + result.CheckSnapshot("mysdk", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +java_import { + name: "mysdk_myjavalib@current", + sdk_member_name: "myjavalib", + host_supported: true, + target: { + android: { + jars: ["java/android/myjavalib.jar"], + }, + linux_glibc: { + jars: ["java/linux_glibc/myjavalib.jar"], + }, + }, +} + +java_import { + name: "myjavalib", + prefer: false, + host_supported: true, + target: { + android: { + jars: ["java/android/myjavalib.jar"], + }, + linux_glibc: { + jars: ["java/linux_glibc/myjavalib.jar"], + }, + }, +} + +sdk_snapshot { + name: "mysdk@current", + host_supported: true, + java_header_libs: ["mysdk_myjavalib@current"], +} +`), + checkAllCopyRules(` +.intermediates/myjavalib/android_common/turbine-combined/myjavalib.jar -> java/android/myjavalib.jar +.intermediates/myjavalib/linux_glibc_common/javac/myjavalib.jar -> java/linux_glibc/myjavalib.jar +`), + ) +} + func TestSnapshotWithJavaImplLibrary(t *testing.T) { result := testSdkWithJava(t, ` module_exports { diff --git a/sdk/testing.go b/sdk/testing.go index 41333cdc8..464c3ca9a 100644 --- a/sdk/testing.go +++ b/sdk/testing.go @@ -40,7 +40,7 @@ func testSdkContext(bp string, fs map[string][]byte) (*android.TestContext, andr name: "myapex.cert", certificate: "myapex", } - ` + cc.GatherRequiredDepsForTest(android.Android) + ` + cc.GatherRequiredDepsForTest(android.Android, android.Windows) mockFS := map[string][]byte{ "build/make/target/product/security": nil, diff --git a/sdk/update.go b/sdk/update.go index 84b6c18f4..282a7a4cd 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -17,6 +17,7 @@ package sdk import ( "fmt" "reflect" + "sort" "strings" "github.com/google/blueprint" @@ -660,6 +661,9 @@ type osTypeSpecificInfo struct { // The list of arch type specific info for this os type. archTypes []*archTypeSpecificInfo + + // True if the member has common arch variants for this os type. + commonArch bool } type archTypeSpecificInfo struct { @@ -672,75 +676,199 @@ func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, build memberType := member.memberType - // Group the properties for each variant by arch type. - osInfo := &osTypeSpecificInfo{} - osInfo.Properties = memberType.CreateVariantPropertiesStruct() + // Group the variants by os type. + variantsByOsType := make(map[android.OsType][]android.SdkAware) variants := member.Variants() - commonArch := false for _, variant := range variants { - var properties android.SdkMemberProperties + osType := variant.Target().Os + variantsByOsType[osType] = append(variantsByOsType[osType], variant) + } - // Get the info associated with the arch type inside the os info. - archType := variant.Target().Arch.ArchType + osCount := len(variantsByOsType) + createVariantPropertiesStruct := func(os android.OsType) android.SdkMemberProperties { + properties := memberType.CreateVariantPropertiesStruct() + base := properties.Base() + base.Os_count = osCount + base.Os = os + return properties + } - if archType.Name == "common" { - // The arch type is common so populate the common properties directly. - properties = osInfo.Properties + osTypeToInfo := make(map[android.OsType]*osTypeSpecificInfo) - commonArch = true - } else { - archInfo := &archTypeSpecificInfo{archType: archType} - properties = memberType.CreateVariantPropertiesStruct() - archInfo.Properties = properties + // The set of properties that are common across all architectures and os types. + commonProperties := createVariantPropertiesStruct(android.CommonOS) - osInfo.archTypes = append(osInfo.archTypes, archInfo) - } + // The list of property structures which are os type specific but common across + // architectures within that os type. + var osSpecificPropertiesList []android.SdkMemberProperties - properties.PopulateFromVariant(variant) - } + for osType, osTypeVariants := range variantsByOsType { + // Group the properties for each variant by arch type within the os. + osInfo := &osTypeSpecificInfo{} + osTypeToInfo[osType] = osInfo - if commonArch { - if len(variants) != 1 { - panic("Expected to only have 1 variant when arch type is common but found " + string(len(variants))) - } - } else { - var archProperties []android.SdkMemberProperties - for _, archInfo := range osInfo.archTypes { - archProperties = append(archProperties, archInfo.Properties) - } + // Create a structure into which properties common across the architectures in + // this os type will be stored. Add it to the list of os type specific yet + // architecture independent properties structs. + osInfo.Properties = createVariantPropertiesStruct(osType) + osSpecificPropertiesList = append(osSpecificPropertiesList, osInfo.Properties) + + commonArch := false + for _, variant := range osTypeVariants { + var properties android.SdkMemberProperties + + // Get the info associated with the arch type inside the os info. + archType := variant.Target().Arch.ArchType - extractCommonProperties(osInfo.Properties, archProperties) + if archType.Name == "common" { + // The arch type is common so populate the common properties directly. + properties = osInfo.Properties - // Choose setting for compile_multilib that is appropriate for the arch variants supplied. - var multilib string - archVariantCount := len(osInfo.archTypes) - if archVariantCount == 2 { - multilib = "both" - } else if archVariantCount == 1 { - if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") { - multilib = "64" + commonArch = true } else { - multilib = "32" + archInfo := &archTypeSpecificInfo{archType: archType} + properties = createVariantPropertiesStruct(osType) + archInfo.Properties = properties + + osInfo.archTypes = append(osInfo.archTypes, archInfo) } + + properties.PopulateFromVariant(variant) } - osInfo.Properties.Base().Compile_multilib = multilib + if commonArch { + if len(osTypeVariants) != 1 { + panic("Expected to only have 1 variant when arch type is common but found " + string(len(variants))) + } + } else { + var archPropertiesList []android.SdkMemberProperties + for _, archInfo := range osInfo.archTypes { + archPropertiesList = append(archPropertiesList, archInfo.Properties) + } + + extractCommonProperties(osInfo.Properties, archPropertiesList) + + // Choose setting for compile_multilib that is appropriate for the arch variants supplied. + var multilib string + archVariantCount := len(osInfo.archTypes) + if archVariantCount == 2 { + multilib = "both" + } else if archVariantCount == 1 { + if strings.HasSuffix(osInfo.archTypes[0].archType.Name, "64") { + multilib = "64" + } else { + multilib = "32" + } + } + + osInfo.commonArch = commonArch + osInfo.Properties.Base().Compile_multilib = multilib + } } - osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, bpModule) + // Extract properties which are common across all architectures and os types. + extractCommonProperties(commonProperties, osSpecificPropertiesList) - if !commonArch { - archPropertySet := bpModule.AddPropertySet("arch") - for _, av := range osInfo.archTypes { - archTypePropertySet := archPropertySet.AddPropertySet(av.archType.Name) + // Add the common properties to the module. + commonProperties.AddToPropertySet(sdkModuleContext, builder, bpModule) - av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet) + // Create a target property set into which target specific properties can be + // added. + targetPropertySet := bpModule.AddPropertySet("target") + + // Iterate over the os types in a fixed order. + for _, osType := range s.getPossibleOsTypes() { + osInfo := osTypeToInfo[osType] + if osInfo == nil { + continue + } + + var osPropertySet android.BpPropertySet + var archOsPrefix string + if len(osTypeToInfo) == 1 { + // There is only one os type present in the variants sp don't bother + // with adding target specific properties. + + // Create a structure that looks like: + // module_type { + // name: "...", + // ... + // + // ... + // + // + // arch: { + // + // } + // + osPropertySet = bpModule + + // Arch specific properties need to be added to an arch specific section + // within arch. + archOsPrefix = "" + } else { + // Create a structure that looks like: + // module_type { + // name: "...", + // ... + // + // ... + // target: { + // + // ... + // + // } + // + osPropertySet = targetPropertySet.AddPropertySet(osType.Name) + + // Arch specific properties need to be added to an os and arch specific + // section prefixed with _. + archOsPrefix = osType.Name + "_" + } + + osInfo.Properties.AddToPropertySet(sdkModuleContext, builder, osPropertySet) + if !osInfo.commonArch { + // Either add the arch specific sections into the target or arch sections + // depending on whether they will also be os specific. + var archPropertySet android.BpPropertySet + if archOsPrefix == "" { + archPropertySet = osPropertySet.AddPropertySet("arch") + } else { + archPropertySet = targetPropertySet + } + + // Add arch (and possibly os) specific sections for each set of + // arch (and possibly os) specific properties. + for _, av := range osInfo.archTypes { + archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + av.archType.Name) + + av.Properties.AddToPropertySet(sdkModuleContext, builder, archTypePropertySet) + } } } memberType.FinalizeModule(sdkModuleContext, builder, member, bpModule) } +// Compute the list of possible os types that this sdk could support. +func (s *sdk) getPossibleOsTypes() []android.OsType { + var osTypes []android.OsType + for _, osType := range android.OsTypeList { + if s.DeviceSupported() { + if osType.Class == android.Device && osType != android.Fuchsia { + osTypes = append(osTypes, osType) + } + } + if s.HostSupported() { + if osType.Class == android.Host || osType.Class == android.HostCross { + osTypes = append(osTypes, osType) + } + } + } + sort.SliceStable(osTypes, func(i, j int) bool { return osTypes[i].Name < osTypes[j].Name }) + return osTypes +} + // Extract common properties from a slice of property structures of the same type. // // All the property structures must be of the same type. @@ -766,6 +894,11 @@ func extractCommonProperties(commonProperties interface{}, inputPropertiesSlice var commonValue *reflect.Value sliceValue := reflect.ValueOf(inputPropertiesSlice) + field := propertiesStructType.Field(f) + if field.Name == "SdkMemberPropertiesBase" { + continue + } + for i := 0; i < sliceValue.Len(); i++ { structValue := sliceValue.Index(i).Elem().Elem() fieldValue := structValue.Field(f) -- cgit v1.2.3-59-g8ed1b From 17ab883cb03878acf0429fa858ec4d5739c7a093 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Thu, 19 Mar 2020 16:11:18 +0000 Subject: Make new module creation API more flexible Previously passing additional information to the implementations of AddPrebuiltModule() or the SdkMemberProperties interface would have required making changes to the API. This change added an SdkMemberContext object into which additional information can easily be added without requiring changes to existing implementations. The BuildSnapshot() method was not modified because it is deprecated and will be removed in a follow up change. It also switches the API from passing variants as android.SdkAware to android.Module. That is for a couple of reasons: 1) SdkAware is designed for managing the relationship between the module and the SDK, not for generating the output snapshot. As such there is nothing in SdkAware that is needed for generating the output snapshot. 2) Accepting android.Module instead makes it easier to use the underlying code for generating the snapshot module as well as the individual member modules. This is in preparation for a number of improvements and bug fixes in both the snapshot creation code and implementations to address found while trying to built the platform against ART prebuilts. Bug: 151937654 Bug: 153306490 Test: m nothing Merged-In: Iac10f1200c0f283aa35402167eec8f9aeb65a38e Change-Id: Iac10f1200c0f283aa35402167eec8f9aeb65a38e --- android/sdk.go | 22 ++++++++++++----- cc/binary_sdk_member.go | 10 ++++---- cc/library_sdk_member.go | 10 ++++---- java/java.go | 21 ++++++++++------ sdk/update.go | 63 +++++++++++++++++++++++++++++------------------- 5 files changed, 77 insertions(+), 49 deletions(-) (limited to 'java/java.go') diff --git a/android/sdk.go b/android/sdk.go index 5c7b329a9..fc324a1dd 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -356,7 +356,7 @@ type SdkMemberType interface { // structure and calls AddToPropertySet(...) on the properties struct to add the member // specific properties in the correct place in the structure. // - AddPrebuiltModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) BpModule + AddPrebuiltModule(ctx SdkMemberContext, member SdkMember) BpModule // Create a structure into which variant specific properties can be added. CreateVariantPropertiesStruct() SdkMemberProperties @@ -385,7 +385,7 @@ func (b *SdkMemberTypeBase) BuildSnapshot(sdkModuleContext ModuleContext, builde panic("override AddPrebuiltModule") } -func (b *SdkMemberTypeBase) AddPrebuiltModule(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember) BpModule { +func (b *SdkMemberTypeBase) AddPrebuiltModule(ctx SdkMemberContext, member SdkMember) BpModule { // Returning nil causes the legacy BuildSnapshot method to be used. return nil } @@ -500,9 +500,19 @@ type SdkMemberProperties interface { // Access the base structure. Base() *SdkMemberPropertiesBase - // Populate the structure with information from the variant. - PopulateFromVariant(variant SdkAware) + // Populate this structure with information from the variant. + PopulateFromVariant(ctx SdkMemberContext, variant Module) - // Add the information from the structure to the property set. - AddToPropertySet(sdkModuleContext ModuleContext, builder SnapshotBuilder, propertySet BpPropertySet) + // Add the information from this structure to the property set. + AddToPropertySet(ctx SdkMemberContext, propertySet BpPropertySet) +} + +// Provides access to information common to a specific member. +type SdkMemberContext interface { + + // The module context of the sdk common os variant which is creating the snapshot. + SdkModuleContext() ModuleContext + + // The builder of the snapshot. + SnapshotBuilder() SnapshotBuilder } diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go index 2778ebd11..9b3235c5d 100644 --- a/cc/binary_sdk_member.go +++ b/cc/binary_sdk_member.go @@ -63,9 +63,8 @@ func (mt *binarySdkMemberType) IsInstance(module android.Module) bool { return false } -func (mt *binarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { - pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary") - return pbm +func (mt *binarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { + return ctx.SnapshotBuilder().AddPrebuiltModule(member, "cc_prebuilt_binary") } func (mt *binarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { @@ -107,7 +106,7 @@ type nativeBinaryInfoProperties struct { SystemSharedLibs []string } -func (p *nativeBinaryInfoProperties) PopulateFromVariant(variant android.SdkAware) { +func (p *nativeBinaryInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { ccModule := variant.(*Module) p.archType = ccModule.Target().Arch.ArchType.String() @@ -122,11 +121,12 @@ func (p *nativeBinaryInfoProperties) PopulateFromVariant(variant android.SdkAwar } } -func (p *nativeBinaryInfoProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { +func (p *nativeBinaryInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { if p.Compile_multilib != "" { propertySet.AddProperty("compile_multilib", p.Compile_multilib) } + builder := ctx.SnapshotBuilder() if p.outputFile != nil { propertySet.AddProperty("srcs", []string{nativeBinaryPathFor(*p)}) diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index aca914652..566bdceff 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -106,8 +106,8 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { return false } -func (mt *librarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { - pbm := builder.AddPrebuiltModule(member, mt.prebuiltModuleType) +func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { + pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, mt.prebuiltModuleType) ccModule := member.Variants()[0].(*Module) @@ -332,7 +332,7 @@ type nativeLibInfoProperties struct { outputFile android.Path } -func (p *nativeLibInfoProperties) PopulateFromVariant(variant android.SdkAware) { +func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { ccModule := variant.(*Module) // If the library has some link types then it produces an output binary file, otherwise it @@ -365,6 +365,6 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(variant android.SdkAware) p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders() } -func (p *nativeLibInfoProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { - addPossiblyArchSpecificProperties(sdkModuleContext, builder, p, propertySet) +func (p *nativeLibInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { + addPossiblyArchSpecificProperties(ctx.SdkModuleContext(), ctx.SnapshotBuilder(), p, propertySet) } diff --git a/java/java.go b/java/java.go index e3fa69d26..416cbe5a4 100644 --- a/java/java.go +++ b/java/java.go @@ -1891,8 +1891,8 @@ func (mt *librarySdkMemberType) IsInstance(module android.Module) bool { return ok } -func (mt *librarySdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { - return builder.AddPrebuiltModule(member, "java_import") +func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { + return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_import") } func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { @@ -1908,15 +1908,18 @@ type librarySdkMemberProperties struct { jarToExport android.Path } -func (p *librarySdkMemberProperties) PopulateFromVariant(variant android.SdkAware) { +func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { j := variant.(*Library) p.library = j p.jarToExport = p.memberType.jarToExportGetter(j) } -func (p *librarySdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { +func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { if p.jarToExport != nil { + sdkModuleContext := ctx.SdkModuleContext() + builder := ctx.SnapshotBuilder() + exportedJar := p.jarToExport snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.library.Name()) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) @@ -2096,8 +2099,8 @@ func (mt *testSdkMemberType) IsInstance(module android.Module) bool { return ok } -func (mt *testSdkMemberType) AddPrebuiltModule(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) android.BpModule { - return builder.AddPrebuiltModule(member, "java_test_import") +func (mt *testSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule { + return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_test_import") } func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { @@ -2111,7 +2114,7 @@ type testSdkMemberProperties struct { jarToExport android.Path } -func (p *testSdkMemberProperties) PopulateFromVariant(variant android.SdkAware) { +func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { test := variant.(*Test) implementationJars := test.ImplementationJars() @@ -2123,8 +2126,10 @@ func (p *testSdkMemberProperties) PopulateFromVariant(variant android.SdkAware) p.jarToExport = implementationJars[0] } -func (p *testSdkMemberProperties) AddToPropertySet(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, propertySet android.BpPropertySet) { +func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { if p.jarToExport != nil { + builder := ctx.SnapshotBuilder() + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.test.Name()) builder.CopyToSnapshot(p.jarToExport, snapshotRelativeJavaLibPath) diff --git a/sdk/update.go b/sdk/update.go index c706d1c15..4c167310c 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -254,12 +254,15 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro members, multilib := s.organizeMembers(ctx, memberRefs) for _, member := range members { memberType := member.memberType - prebuiltModule := memberType.AddPrebuiltModule(ctx, builder, member) + + memberCtx := &memberContext{ctx, builder} + + prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member) if prebuiltModule == nil { // Fall back to legacy method of building a snapshot memberType.BuildSnapshot(ctx, builder, member) } else { - s.createMemberSnapshot(ctx, builder, member, prebuiltModule) + s.createMemberSnapshot(memberCtx, member, prebuiltModule) } } @@ -831,7 +834,7 @@ type variantPropertiesFactoryFunc func() android.SdkMemberProperties // Create a new osTypeSpecificInfo for the specified os type and its properties // structures populated with information from the variants. -func newOsTypeSpecificInfo(osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, osTypeVariants []android.SdkAware) *osTypeSpecificInfo { +func newOsTypeSpecificInfo(ctx android.SdkMemberContext, osType android.OsType, variantPropertiesFactory variantPropertiesFactoryFunc, osTypeVariants []android.Module) *osTypeSpecificInfo { osInfo := &osTypeSpecificInfo{ osType: osType, } @@ -847,7 +850,7 @@ func newOsTypeSpecificInfo(osType android.OsType, variantPropertiesFactory varia osInfo.Properties = osSpecificVariantPropertiesFactory() // Group the variants by arch type. - var variantsByArchName = make(map[string][]android.SdkAware) + var variantsByArchName = make(map[string][]android.Module) var archTypes []android.ArchType for _, variant := range osTypeVariants { archType := variant.Target().Arch.ArchType @@ -866,14 +869,14 @@ func newOsTypeSpecificInfo(osType android.OsType, variantPropertiesFactory varia // A common arch type only has one variant and its properties should be treated // as common to the os type. - osInfo.Properties.PopulateFromVariant(commonVariants[0]) + osInfo.Properties.PopulateFromVariant(ctx, commonVariants[0]) } else { // Create an arch specific info for each supported architecture type. for _, archType := range archTypes { archTypeName := archType.Name archVariants := variantsByArchName[archTypeName] - archInfo := newArchSpecificInfo(archType, osSpecificVariantPropertiesFactory, archVariants) + archInfo := newArchSpecificInfo(ctx, archType, osSpecificVariantPropertiesFactory, archVariants) osInfo.archInfos = append(osInfo.archInfos, archInfo) } @@ -912,10 +915,7 @@ func (osInfo *osTypeSpecificInfo) optimizeProperties(commonValueExtractor *commo // Maps the properties related to the os variants through to an appropriate // module structure that will produce equivalent set of variants when it is // processed in a build. -func (osInfo *osTypeSpecificInfo) addToPropertySet( - builder *snapshotBuilder, - bpModule android.BpModule, - targetPropertySet android.BpPropertySet) { +func (osInfo *osTypeSpecificInfo) addToPropertySet(ctx *memberContext, bpModule android.BpModule, targetPropertySet android.BpPropertySet) { var osPropertySet android.BpPropertySet var archPropertySet android.BpPropertySet @@ -965,7 +965,7 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet( } // Add the os specific but arch independent properties to the module. - osInfo.Properties.AddToPropertySet(builder.ctx, builder, osPropertySet) + osInfo.Properties.AddToPropertySet(ctx, osPropertySet) // Add arch (and possibly os) specific sections for each set of arch (and possibly // os) specific properties. @@ -973,7 +973,7 @@ func (osInfo *osTypeSpecificInfo) addToPropertySet( // The archInfos list will be empty if the os contains variants for the common // architecture. for _, archInfo := range osInfo.archInfos { - archInfo.addToPropertySet(builder, archPropertySet, archOsPrefix) + archInfo.addToPropertySet(ctx, archPropertySet, archOsPrefix) } } @@ -987,7 +987,7 @@ type archTypeSpecificInfo struct { // Create a new archTypeSpecificInfo for the specified arch type and its properties // structures populated with information from the variants. -func newArchSpecificInfo(archType android.ArchType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.SdkAware) *archTypeSpecificInfo { +func newArchSpecificInfo(ctx android.SdkMemberContext, archType android.ArchType, variantPropertiesFactory variantPropertiesFactoryFunc, archVariants []android.Module) *archTypeSpecificInfo { // Create an arch specific info into which the variant properties can be copied. archInfo := &archTypeSpecificInfo{archType: archType} @@ -997,7 +997,7 @@ func newArchSpecificInfo(archType android.ArchType, variantPropertiesFactory var archInfo.Properties = variantPropertiesFactory() if len(archVariants) == 1 { - archInfo.Properties.PopulateFromVariant(archVariants[0]) + archInfo.Properties.PopulateFromVariant(ctx, archVariants[0]) } else { // There is more than one variant for this arch type which must be differentiated // by link type. @@ -1006,7 +1006,7 @@ func newArchSpecificInfo(archType android.ArchType, variantPropertiesFactory var if linkType == "" { panic(fmt.Errorf("expected one arch specific variant as it is not identified by link type but found %d", len(archVariants))) } else { - linkInfo := newLinkSpecificInfo(linkType, variantPropertiesFactory, linkVariant) + linkInfo := newLinkSpecificInfo(ctx, linkType, variantPropertiesFactory, linkVariant) archInfo.linkInfos = append(archInfo.linkInfos, linkInfo) } @@ -1052,14 +1052,14 @@ func (archInfo *archTypeSpecificInfo) optimizeProperties(commonValueExtractor *c } // Add the properties for an arch type to a property set. -func (archInfo *archTypeSpecificInfo) addToPropertySet(builder *snapshotBuilder, archPropertySet android.BpPropertySet, archOsPrefix string) { +func (archInfo *archTypeSpecificInfo) addToPropertySet(ctx *memberContext, archPropertySet android.BpPropertySet, archOsPrefix string) { archTypeName := archInfo.archType.Name archTypePropertySet := archPropertySet.AddPropertySet(archOsPrefix + archTypeName) - archInfo.Properties.AddToPropertySet(builder.ctx, builder, archTypePropertySet) + archInfo.Properties.AddToPropertySet(ctx, archTypePropertySet) for _, linkInfo := range archInfo.linkInfos { linkPropertySet := archTypePropertySet.AddPropertySet(linkInfo.linkType) - linkInfo.Properties.AddToPropertySet(builder.ctx, builder, linkPropertySet) + linkInfo.Properties.AddToPropertySet(ctx, linkPropertySet) } } @@ -1071,7 +1071,7 @@ type linkTypeSpecificInfo struct { // Create a new linkTypeSpecificInfo for the specified link type and its properties // structures populated with information from the variant. -func newLinkSpecificInfo(linkType string, variantPropertiesFactory variantPropertiesFactoryFunc, linkVariant android.SdkAware) *linkTypeSpecificInfo { +func newLinkSpecificInfo(ctx android.SdkMemberContext, linkType string, variantPropertiesFactory variantPropertiesFactoryFunc, linkVariant android.Module) *linkTypeSpecificInfo { linkInfo := &linkTypeSpecificInfo{ baseInfo: baseInfo{ // Create the properties into which the link type specific properties will be @@ -1080,16 +1080,29 @@ func newLinkSpecificInfo(linkType string, variantPropertiesFactory variantProper }, linkType: linkType, } - linkInfo.Properties.PopulateFromVariant(linkVariant) + linkInfo.Properties.PopulateFromVariant(ctx, linkVariant) return linkInfo } -func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, builder *snapshotBuilder, member *sdkMember, bpModule android.BpModule) { +type memberContext struct { + sdkMemberContext android.ModuleContext + builder *snapshotBuilder +} + +func (m *memberContext) SdkModuleContext() android.ModuleContext { + return m.sdkMemberContext +} + +func (m *memberContext) SnapshotBuilder() android.SnapshotBuilder { + return m.builder +} + +func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule android.BpModule) { memberType := member.memberType // Group the variants by os type. - variantsByOsType := make(map[android.OsType][]android.SdkAware) + variantsByOsType := make(map[android.OsType][]android.Module) variants := member.Variants() for _, variant := range variants { osType := variant.Target().Os @@ -1118,7 +1131,7 @@ func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, build var osSpecificPropertiesList []android.SdkMemberProperties for osType, osTypeVariants := range variantsByOsType { - osInfo := newOsTypeSpecificInfo(osType, variantPropertiesFactory, osTypeVariants) + osInfo := newOsTypeSpecificInfo(ctx, osType, variantPropertiesFactory, osTypeVariants) osTypeToInfo[osType] = osInfo // Add the os specific properties to a list of os type specific yet architecture // independent properties structs. @@ -1132,7 +1145,7 @@ func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, build commonValueExtractor.extractCommonProperties(commonProperties, osSpecificPropertiesList) // Add the common properties to the module. - commonProperties.AddToPropertySet(sdkModuleContext, builder, bpModule) + commonProperties.AddToPropertySet(ctx, bpModule) // Create a target property set into which target specific properties can be // added. @@ -1145,7 +1158,7 @@ func (s *sdk) createMemberSnapshot(sdkModuleContext android.ModuleContext, build continue } - osInfo.addToPropertySet(builder, bpModule, targetPropertySet) + osInfo.addToPropertySet(ctx, bpModule, targetPropertySet) } } -- cgit v1.2.3-59-g8ed1b From c9103930a41317898fb495424ac3b2f9c12d36ff Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Tue, 17 Mar 2020 21:04:24 +0000 Subject: Improve consistency of handling java snapshot properties Previously, java snapshot properties (java_library and java_test) relied on the properties not being optimized when there was a single os type and instead being added directly to the common os type properties. However, that means that the behavior is inconsistent for other member types depending on whether there was one os type or not. This change updates the java sdk member handling to support optimization. This involved: 1) Adding AidlIncludeDirs field to librarySdkMemberProperties to specify the aidl include dirs instead of extracting that from the library field. 2) Renaming jarToExport to JarToExport (in both library/testSdkMemberProperties)to allow it to be optimized. 3) Adding MemberType() and Name() methods to SdkMemberPropertiesContext to avoid having to store the former in the properties struct and retrieve the latter from the library/test fields. 4) Removing the now unused library/test fields from the properties structures. 5) Separating the processing of the jar/test config in AddToPropertySet(...) as they may be optimized separately. 6) Ditto for the jar/aidl include dirs. 7) While doing this work I noticed that although the contents of the aidl include dirs are copied into the snapshot the java_import does not make use of them. Raised bug 151933053 and added TODO to track that work. Bug: 142935992 Bug: 153306490 Test: m nothing Merged-In: Iba9799e111ca5672b2133568163d8c49837ba9cd Change-Id: Iba9799e111ca5672b2133568163d8c49837ba9cd --- android/sdk.go | 30 +++++++++++++++++++++++++++--- java/java.go | 57 ++++++++++++++++++++++++++++++++------------------------- sdk/update.go | 12 +++++++++++- 3 files changed, 70 insertions(+), 29 deletions(-) (limited to 'java/java.go') diff --git a/android/sdk.go b/android/sdk.go index fc324a1dd..fb469b0b6 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -465,14 +465,29 @@ func RegisterSdkMemberType(memberType SdkMemberType) { // Contains common properties that apply across many different member types. These // are not affected by the optimization to extract common values. type SdkMemberPropertiesBase struct { - // The setting to use for the compile_multilib property. - Compile_multilib string `sdk:"keep"` - // The number of unique os types supported by the member variants. + // + // If a member has a variant with more than one os type then it will need to differentiate + // 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"` // 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"` + + // The setting to use for the compile_multilib property. + // + // This property is set after optimization so there is no point in trying to optimize it. + Compile_multilib string `sdk:"keep"` } // The os prefix to use for any file paths in the sdk. @@ -515,4 +530,13 @@ type SdkMemberContext interface { // The builder of the snapshot. SnapshotBuilder() SnapshotBuilder + + // The type of the member. + MemberType() SdkMemberType + + // The name of the member. + // + // Provided for use by sdk members to create a member specific location within the snapshot + // into which to copy the prebuilt files. + Name() string } diff --git a/java/java.go b/java/java.go index 416cbe5a4..20e01f2af 100644 --- a/java/java.go +++ b/java/java.go @@ -1896,35 +1896,38 @@ func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, } func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties { - return &librarySdkMemberProperties{memberType: mt} + return &librarySdkMemberProperties{} } type librarySdkMemberProperties struct { android.SdkMemberPropertiesBase - memberType *librarySdkMemberType - - library *Library - jarToExport android.Path + JarToExport android.Path + AidlIncludeDirs android.Paths } func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { j := variant.(*Library) - p.library = j - p.jarToExport = p.memberType.jarToExportGetter(j) + p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(j) + p.AidlIncludeDirs = j.AidlIncludeDirs() } func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { - if p.jarToExport != nil { - sdkModuleContext := ctx.SdkModuleContext() - builder := ctx.SnapshotBuilder() + builder := ctx.SnapshotBuilder() - exportedJar := p.jarToExport - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.library.Name()) + exportedJar := p.JarToExport + if exportedJar != nil { + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name()) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) - for _, dir := range p.library.AidlIncludeDirs() { + propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + } + + aidlIncludeDirs := p.AidlIncludeDirs + if len(aidlIncludeDirs) != 0 { + sdkModuleContext := ctx.SdkModuleContext() + for _, dir := range aidlIncludeDirs { // TODO(jiyong): copy parcelable declarations only aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil) for _, file := range aidlFiles { @@ -1932,7 +1935,7 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte } } - propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + // TODO(b/151933053) - add aidl include dirs property } } @@ -2110,8 +2113,8 @@ func (mt *testSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberPr type testSdkMemberProperties struct { android.SdkMemberPropertiesBase - test *Test - jarToExport android.Path + JarToExport android.Path + TestConfig android.Path } func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) { @@ -2122,21 +2125,25 @@ func (p *testSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberConte panic(fmt.Errorf("there must be only one implementation jar from %q", test.Name())) } - p.test = test - p.jarToExport = implementationJars[0] + p.JarToExport = implementationJars[0] + p.TestConfig = test.testConfig } func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) { - if p.jarToExport != nil { - builder := ctx.SnapshotBuilder() - - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), p.test.Name()) - builder.CopyToSnapshot(p.jarToExport, snapshotRelativeJavaLibPath) + builder := ctx.SnapshotBuilder() - snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), p.test.Name(), testConfigSuffix) - builder.CopyToSnapshot(p.test.testConfig, snapshotRelativeTestConfigPath) + exportedJar := p.JarToExport + if exportedJar != nil { + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name()) + builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) + } + + testConfig := p.TestConfig + if testConfig != nil { + snapshotRelativeTestConfigPath := sdkSnapshotFilePathForMember(p.OsPrefix(), ctx.Name(), testConfigSuffix) + builder.CopyToSnapshot(testConfig, snapshotRelativeTestConfigPath) propertySet.AddProperty("test_config", snapshotRelativeTestConfigPath) } } diff --git a/sdk/update.go b/sdk/update.go index 4c167310c..3ff0c1d1c 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -255,7 +255,7 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) andro for _, member := range members { memberType := member.memberType - memberCtx := &memberContext{ctx, builder} + memberCtx := &memberContext{ctx, builder, memberType, member.name} prebuiltModule := memberType.AddPrebuiltModule(memberCtx, member) if prebuiltModule == nil { @@ -1087,6 +1087,8 @@ func newLinkSpecificInfo(ctx android.SdkMemberContext, linkType string, variantP type memberContext struct { sdkMemberContext android.ModuleContext builder *snapshotBuilder + memberType android.SdkMemberType + name string } func (m *memberContext) SdkModuleContext() android.ModuleContext { @@ -1097,6 +1099,14 @@ func (m *memberContext) SnapshotBuilder() android.SnapshotBuilder { return m.builder } +func (m *memberContext) MemberType() android.SdkMemberType { + return m.memberType +} + +func (m *memberContext) Name() string { + return m.name +} + func (s *sdk) createMemberSnapshot(ctx *memberContext, member *sdkMember, bpModule android.BpModule) { memberType := member.memberType -- cgit v1.2.3-59-g8ed1b From b20ad0a7d4c8aa6d88124bacc45555113fa02f70 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Tue, 31 Mar 2020 15:23:40 +0100 Subject: Stop requiring apex_available on java_library members of sdks Previously, adding java_library to an sdk required that the names of any APEXes that transitively compiled against it were added to its apex_available property. This change removes that requirement. Also corrects the dependency path in the TestApexAvailable_IndirectDep error which previously passed through "shared from static" static dependency tags even though those are explicitly NOT followed when checking apex_available settings. Bug: 152878661 Bug: 153306490 Test: m droid Merged-In: I995ed38956c1bc210b09494812de012fed9f9232 Change-Id: I995ed38956c1bc210b09494812de012fed9f9232 --- apex/apex.go | 20 +++++++++++++++++++- apex/apex_test.go | 12 +++--------- java/java.go | 10 ---------- sdk/java_sdk_test.go | 12 ------------ sdk/sdk.go | 16 ++++++++++++---- 5 files changed, 34 insertions(+), 36 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index a40a7539d..a87187a18 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -868,13 +868,23 @@ func apexDepsMutator(mctx android.TopDownMutatorContext) { mctx.VisitDirectDeps(func(child android.Module) { depName := mctx.OtherModuleName(child) if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && - cur.DepIsInSameApex(mctx, child) { + (cur.DepIsInSameApex(mctx, child) || inAnySdk(child)) { android.UpdateApexDependency(apexBundles, depName, directDep) am.BuildForApexes(apexBundles) } }) } +// If a module in an APEX depends on a module from an SDK then it needs an APEX +// specific variant created for it. Refer to sdk.sdkDepsReplaceMutator. +func inAnySdk(module android.Module) bool { + if sa, ok := module.(android.SdkAware); ok { + return sa.IsInAnySdk() + } + + return false +} + // Create apex variations if a module is included in APEX(s). func apexMutator(mctx android.BottomUpMutatorContext) { if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() { @@ -1849,6 +1859,14 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { apexName := ctx.ModuleName() fromName := ctx.OtherModuleName(from) toName := ctx.OtherModuleName(to) + + // If `to` is not actually in the same APEX as `from` then it does not need apex_available and neither + // do any of its dependencies. + if am, ok := from.(android.DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) { + // As soon as the dependency graph crosses the APEX boundary, don't go further. + return false + } + if to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, toName) { return true } diff --git a/apex/apex_test.go b/apex/apex_test.go index a76f50d73..716e263e1 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3518,16 +3518,10 @@ func TestApexAvailable_IndirectDep(t *testing.T) { testApexError(t, `requires "libbaz" that is not available for the APEX. Dependency path: .*via tag apex\.dependencyTag.*"sharedLib".* .*-> libfoo.*link:shared.* -.*via tag cc\.DependencyTag.*"reuse objects".* -.*-> libfoo.*link:static.* -.*via tag cc\.DependencyTag.*"shared from static".* +.*via tag cc\.DependencyTag.*"shared".* .*-> libbar.*link:shared.* -.*via tag cc\.DependencyTag.*"reuse objects".* -.*-> libbar.*link:static.* -.*via tag cc\.DependencyTag.*"shared from static".* -.*-> libbaz.*link:shared.* -.*via tag cc\.DependencyTag.*"reuse objects".* -.*-> libbaz.*link:static.*`, ` +.*via tag cc\.DependencyTag.*"shared".* +.*-> libbaz.*link:shared.*`, ` apex { name: "myapex", key: "myapex.key", diff --git a/java/java.go b/java/java.go index 20e01f2af..57ed29d14 100644 --- a/java/java.go +++ b/java/java.go @@ -1764,11 +1764,6 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu if staticLibTag == ctx.OtherModuleDependencyTag(dep) { return true } - // Also, a dependency to an sdk member is also considered as such. This is required because - // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { - return true - } return false } @@ -2508,11 +2503,6 @@ func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu if staticLibTag == ctx.OtherModuleDependencyTag(dep) { return true } - // Also, a dependency to an sdk member is also considered as such. This is required because - // sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator. - if sa, ok := dep.(android.SdkAware); ok && sa.IsInAnySdk() { - return true - } return false } diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index cbffb501b..4a2c05387 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -53,30 +53,18 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) { system_modules: "none", sdk_version: "none", host_supported: true, - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], } java_import { name: "sdkmember_mysdk_1", sdk_member_name: "sdkmember", host_supported: true, - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], } java_import { name: "sdkmember_mysdk_2", sdk_member_name: "sdkmember", host_supported: true, - apex_available: [ - "//apex_available:platform", - "//apex_available:anyapex", - ], } java_library { diff --git a/sdk/sdk.go b/sdk/sdk.go index a5709ac61..cb5a6053d 100644 --- a/sdk/sdk.go +++ b/sdk/sdk.go @@ -312,7 +312,7 @@ func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { ctx.BottomUp("SdkMemberInterVersion", memberInterVersionMutator).Parallel() } -// RegisterPostDepshMutators registers post-deps mutators to support modules implementing SdkAware +// RegisterPostDepsMutators registers post-deps mutators to support modules implementing SdkAware // interface and the sdk module type. This function has been made public to be called by tests // outside of the sdk package func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) { @@ -431,7 +431,7 @@ func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) { } } -// Step 6: ensure that the dependencies from outside of the APEX are all from the required SDKs +// Step 6: ensure that the dependencies outside of the APEX are all from the required SDKs func sdkRequirementsMutator(mctx android.TopDownMutatorContext) { if m, ok := mctx.Module().(interface { android.DepIsInSameApex @@ -442,12 +442,20 @@ func sdkRequirementsMutator(mctx android.TopDownMutatorContext) { return } mctx.VisitDirectDeps(func(dep android.Module) { - if mctx.OtherModuleDependencyTag(dep) == android.DefaultsDepTag { + tag := mctx.OtherModuleDependencyTag(dep) + if tag == android.DefaultsDepTag { // dependency to defaults is always okay return } - // If the dep is from outside of the APEX, but is not in any of the + // Ignore the dependency from the unversioned member to any versioned members as an + // apex that depends on the unversioned member will not also be depending on a versioned + // member. + if _, ok := tag.(sdkMemberVersionedDepTag); ok { + return + } + + // If the dep is outside of the APEX, but is not in any of the // required SDKs, we know that the dep is a violation. if sa, ok := dep.(android.SdkAware); ok { if !m.DepIsInSameApex(mctx, dep) && !requiredSdks.Contains(sa.ContainingSdk()) { -- cgit v1.2.3-59-g8ed1b From d99540b254789c47862d0d7cf8e45e44e7b81115 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 22 Apr 2020 11:44:34 -0700 Subject: Repeat kapt processor argument for multiple processors kapt claims to support a comma separated list of annotation processors, but it errors if multiple annotation processors are given. Surrounding the the list with {} does not error, but it also doesn't even warn if the second element in the list is garbage, so it may not be running the second processor. Repeat the processor argument for each annotation processor class instead. Bug: 154736649 Test: TestKapt Test: m checkbuild Change-Id: I4c7c161dbf867d7fba1aaf16fd5e502647e3f682 Merged-In: I4c7c161dbf867d7fba1aaf16fd5e502647e3f682 (cherry picked from commit 5a11686e64d7c6665589458a94f183d0823dc833) --- java/builder.go | 10 +++++----- java/java.go | 5 +++-- java/kotlin.go | 7 +++++-- java/kotlin_test.go | 14 +++++++++++--- 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'java/java.go') diff --git a/java/builder.go b/java/builder.go index f09cd9808..ad9afee81 100644 --- a/java/builder.go +++ b/java/builder.go @@ -195,7 +195,7 @@ type javaBuilderFlags struct { classpath classpath java9Classpath classpath processorPath classpath - processor string + processors []string systemModules *systemModules aidlFlags string aidlDeps android.Paths @@ -269,8 +269,8 @@ func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx deps = append(deps, flags.processorPath...) processor := "-proc:none" - if flags.processor != "" { - processor = "-processor " + flags.processor + if len(flags.processors) > 0 { + processor = "-processor " + strings.Join(flags.processors, ",") } intermediatesDir := "xref" @@ -384,8 +384,8 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab deps = append(deps, flags.processorPath...) processor := "-proc:none" - if flags.processor != "" { - processor = "-processor " + flags.processor + if len(flags.processors) > 0 { + processor = "-processor " + strings.Join(flags.processors, ",") } srcJarDir := "srcjars" diff --git a/java/java.go b/java/java.go index 57ed29d14..1c2e22a51 100644 --- a/java/java.go +++ b/java/java.go @@ -1134,7 +1134,8 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...) flags.processorPath = append(flags.processorPath, deps.processorPath...) - flags.processor = strings.Join(deps.processorClasses, ",") + flags.processors = append(flags.processors, deps.processorClasses...) + flags.processors = android.FirstUniqueStrings(flags.processors) if len(flags.bootClasspath) == 0 && ctx.Host() && !flags.javaVersion.usesJavaModules() && decodeSdkDep(ctx, sdkContext(j)).hasStandardLibs() { @@ -1269,7 +1270,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { srcJars = append(srcJars, kaptSrcJar) // Disable annotation processing in javac, it's already been handled by kapt flags.processorPath = nil - flags.processor = "" + flags.processors = nil } kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) diff --git a/java/kotlin.go b/java/kotlin.go index cb7da20f8..9b160a082 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -136,8 +136,11 @@ func kotlinKapt(ctx android.ModuleContext, outputFile android.WritablePath, kaptProcessorPath := flags.processorPath.FormRepeatedClassPath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=") kaptProcessor := "" - if flags.processor != "" { - kaptProcessor = "-P plugin:org.jetbrains.kotlin.kapt3:processors=" + flags.processor + for i, p := range flags.processors { + if i > 0 { + kaptProcessor += " " + } + kaptProcessor += "-P plugin:org.jetbrains.kotlin.kapt3:processors=" + p } encodedJavacFlags := kaptEncodeFlags([][2]string{ diff --git a/java/kotlin_test.go b/java/kotlin_test.go index 5c6d45f45..60ca1c476 100644 --- a/java/kotlin_test.go +++ b/java/kotlin_test.go @@ -88,7 +88,7 @@ func TestKapt(t *testing.T) { java_library { name: "foo", srcs: ["a.java", "b.kt"], - plugins: ["bar"], + plugins: ["bar", "baz"], } java_plugin { @@ -96,6 +96,12 @@ func TestKapt(t *testing.T) { processor_class: "com.bar", srcs: ["b.java"], } + + java_plugin { + name: "baz", + processor_class: "com.baz", + srcs: ["b.java"], + } `) buildOS := android.BuildOs.String() @@ -105,6 +111,7 @@ func TestKapt(t *testing.T) { javac := ctx.ModuleForTests("foo", "android_common").Rule("javac") bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String() + baz := ctx.ModuleForTests("baz", buildOS+"_common").Rule("javac").Output.String() // Test that the kotlin and java sources are passed to kapt and kotlinc if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" { @@ -136,11 +143,12 @@ func TestKapt(t *testing.T) { } // Test that the processors are passed to kapt - expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar + expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar + + " -P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + baz if kapt.Args["kaptProcessorPath"] != expectedProcessorPath { t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"]) } - expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar" + expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar -P plugin:org.jetbrains.kotlin.kapt3:processors=com.baz" if kapt.Args["kaptProcessor"] != expectedProcessor { t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"]) } -- cgit v1.2.3-59-g8ed1b From 062ed7eaa11123cca7dcd608df5148718b7e4fca Mon Sep 17 00:00:00 2001 From: Jaewoong Jung Date: Sun, 26 Apr 2020 15:10:51 -0700 Subject: Add defaults support to runtime_resource_overlay. Bug: 154956723 Test: app_test.go Change-Id: Ida29035ef45ec188c95a07a8bccaaa77eea486d7 --- java/app_test.go | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ java/java.go | 1 + 2 files changed, 60 insertions(+) (limited to 'java/java.go') diff --git a/java/app_test.go b/java/app_test.go index b1c8b63df..39460dce6 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2540,3 +2540,62 @@ func TestRuntimeResourceOverlay(t *testing.T) { t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides) } } + +func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) { + ctx, config := testJava(t, ` + java_defaults { + name: "rro_defaults", + theme: "default_theme", + product_specific: true, + aaptflags: ["--keep-raw-values"], + } + + runtime_resource_overlay { + name: "foo_with_defaults", + defaults: ["rro_defaults"], + } + + runtime_resource_overlay { + name: "foo_barebones", + } + `) + + // + // RRO module with defaults + // + m := ctx.ModuleForTests("foo_with_defaults", "android_common") + + // Check AAPT2 link flags. + aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ") + expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"} + absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags) + if len(absentFlags) > 0 { + t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags) + } + + // Check device location. + path := android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] + expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"} + if !reflect.DeepEqual(path, expectedPath) { + t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath) + } + + // + // RRO module without defaults + // + m = ctx.ModuleForTests("foo_barebones", "android_common") + + // Check AAPT2 link flags. + aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ") + unexpectedFlags := "--keep-raw-values" + if inList(unexpectedFlags, aapt2Flags) { + t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags) + } + + // Check device location. + path = android.AndroidMkEntriesForTest(t, config, "", m.Module())[0].EntryMap["LOCAL_MODULE_PATH"] + expectedPath = []string{"/tmp/target/product/test_device/system/overlay"} + if !reflect.DeepEqual(path, expectedPath) { + t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath) + } +} diff --git a/java/java.go b/java/java.go index 1c2e22a51..5d7780720 100644 --- a/java/java.go +++ b/java/java.go @@ -2745,6 +2745,7 @@ func DefaultsFactory() android.Module { &sdkLibraryProperties{}, &DexImportProperties{}, &android.ApexProperties{}, + &RuntimeResourceOverlayProperties{}, ) android.InitDefaultsModule(module) -- cgit v1.2.3-59-g8ed1b From 2eedf623ff3fe9f104d4fd07754c3b15b712d0e1 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Wed, 15 Apr 2020 17:29:42 +0100 Subject: Ensure APEX's Java deps use stable SDKs. Test: m Bug: 153333044 Change-Id: Ib1acf3073e96fe23c92d292ec0b1a91e2cd408db Merged-In: Ib1acf3073e96fe23c92d292ec0b1a91e2cd408db Exempt-From-Owner-Approval: cp from aosp (cherry picked from commit 8cf899afcc69643f63350bc9f9f92677bb8feabd) --- apex/apex.go | 20 ++++++++- apex/apex_test.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ java/java.go | 8 ++++ java/sdk.go | 5 ++- 4 files changed, 150 insertions(+), 2 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index 6a0c4c141..719136515 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1871,6 +1871,8 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } + + a.checkJavaStableSdkVersion(ctx) } } @@ -1940,7 +1942,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkApexAvailability(ctx) a.checkUpdatable(ctx) - a.collectDepsInfo(ctx) handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) @@ -2247,6 +2248,23 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.buildApexDependencyInfo(ctx) } +// Enforce that Java deps of the apex are using stable SDKs to compile +func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { + // Visit direct deps only. As long as we guarantee top-level deps are using + // stable SDKs, java's checkLinkType guarantees correct usage for transitive deps + ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) { + tag := ctx.OtherModuleDependencyTag(module) + switch tag { + case javaLibTag, androidAppTag: + if m, ok := module.(interface{ CheckStableSdkVersion() error }); ok { + if err := m.CheckStableSdkVersion(); err != nil { + ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err) + } + } + } + }) +} + func whitelistedApexAvailable(apex, moduleName string) bool { key := apex moduleName = normalizeModuleName(moduleName) diff --git a/apex/apex_test.go b/apex/apex_test.go index 2618db320..f1d80ae85 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -1377,6 +1377,122 @@ func TestInvalidMinSdkVersion(t *testing.T) { `) } +func TestJavaStableSdkVersion(t *testing.T) { + testCases := []struct { + name string + expectedError string + bp string + }{ + { + name: "Non-updatable apex with non-stable dep", + bp: ` + apex { + name: "myapex", + java_libs: ["myjar"], + key: "myapex.key", + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + java_library { + name: "myjar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "core_platform", + apex_available: ["myapex"], + } + `, + }, + { + name: "Updatable apex with stable dep", + bp: ` + apex { + name: "myapex", + java_libs: ["myjar"], + key: "myapex.key", + updatable: true, + min_sdk_version: "29", + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + java_library { + name: "myjar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "current", + apex_available: ["myapex"], + } + `, + }, + { + name: "Updatable apex with non-stable dep", + expectedError: "cannot depend on \"myjar\"", + bp: ` + apex { + name: "myapex", + java_libs: ["myjar"], + key: "myapex.key", + updatable: true, + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + java_library { + name: "myjar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "core_platform", + apex_available: ["myapex"], + } + `, + }, + { + name: "Updatable apex with non-stable transitive dep", + expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against non-public Android API.", + bp: ` + apex { + name: "myapex", + java_libs: ["myjar"], + key: "myapex.key", + updatable: true, + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + java_library { + name: "myjar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "current", + apex_available: ["myapex"], + static_libs: ["transitive-jar"], + } + java_library { + name: "transitive-jar", + srcs: ["foo/bar/MyClass.java"], + sdk_version: "core_platform", + apex_available: ["myapex"], + } + `, + }, + } + + for _, test := range testCases { + t.Run(test.name, func(t *testing.T) { + if test.expectedError == "" { + testApex(t, test.bp) + } else { + testApexError(t, test.expectedError, test.bp) + } + }) + } +} + func TestFilesInSubDir(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -4289,6 +4405,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { java_library { name: "some-updatable-apex-lib", srcs: ["a.java"], + sdk_version: "current", apex_available: [ "some-updatable-apex", ], @@ -4297,12 +4414,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { java_library { name: "some-platform-lib", srcs: ["a.java"], + sdk_version: "current", installable: true, } java_library { name: "some-art-lib", srcs: ["a.java"], + sdk_version: "current", apex_available: [ "com.android.art.something", ], diff --git a/java/java.go b/java/java.go index 5d7780720..6589721f8 100644 --- a/java/java.go +++ b/java/java.go @@ -86,6 +86,14 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) } +func (j *Module) CheckStableSdkVersion() error { + sdkVersion := j.sdkVersion() + if sdkVersion.stable() { + return nil + } + return fmt.Errorf("non stable SDK %v", sdkVersion) +} + func (j *Module) checkSdkVersions(ctx android.ModuleContext) { if j.SocSpecific() || j.DeviceSpecific() || (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { diff --git a/java/sdk.go b/java/sdk.go index be5e51240..4414600fa 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -170,9 +170,12 @@ func (s sdkSpec) stable() bool { return false } switch s.kind { + case sdkNone: + // there is nothing to manage and version in this case; de facto stable API. + return true case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer: return true - case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate: + case sdkCorePlatform, sdkTest, sdkPrivate: return false default: panic(fmt.Errorf("unknown sdkKind=%v", s.kind)) -- cgit v1.2.3-59-g8ed1b From 388d39ba9a13db914a26d70a92e6074216842b43 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Mon, 27 Apr 2020 18:53:18 +0100 Subject: Introduce min_sdk_version to deps info. Bug: 149622332 Test: m Change-Id: Ie6568cb8a82d5cca9a3dc91b5a068abf4b0632dc Merged-In: Ie6568cb8a82d5cca9a3dc91b5a068abf4b0632dc Exempt-From-Owner-Approval: cp from aosp (cherry picked from commit 480e25b74f9e7101ff3083bd4517f15ac0a6a1b9) --- android/apex.go | 20 +++++++++++++++----- apex/apex_test.go | 32 ++++++++++++++++---------------- apex/builder.go | 16 ++++++++++++---- cc/cc.go | 4 ++++ java/java.go | 8 ++++++++ 5 files changed, 55 insertions(+), 25 deletions(-) (limited to 'java/java.go') diff --git a/android/apex.go b/android/apex.go index 07d59b248..ede096540 100644 --- a/android/apex.go +++ b/android/apex.go @@ -405,21 +405,29 @@ type ApexModuleDepInfo struct { From []string // Whether the dependency belongs to the final compiled APEX. IsExternal bool + // min_sdk_version of the ApexModule + MinSdkVersion string } // A map of a dependency name to its ApexModuleDepInfo type DepNameToDepInfoMap map[string]ApexModuleDepInfo type ApexBundleDepsInfo struct { - flatListPath OutputPath - fullListPath OutputPath + minSdkVersion string + flatListPath OutputPath + fullListPath OutputPath } type ApexDepsInfoIntf interface { + MinSdkVersion() string FlatListPath() Path FullListPath() Path } +func (d *ApexBundleDepsInfo) MinSdkVersion() string { + return d.minSdkVersion +} + func (d *ApexBundleDepsInfo) FlatListPath() Path { return d.flatListPath } @@ -433,14 +441,16 @@ var _ ApexDepsInfoIntf = (*ApexBundleDepsInfo)(nil) // Generate two module out files: // 1. FullList with transitive deps and their parents in the dep graph // 2. FlatList with a flat list of transitive deps -func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, depInfos DepNameToDepInfoMap) { +func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion string, depInfos DepNameToDepInfoMap) { + d.minSdkVersion = minSdkVersion + var fullContent strings.Builder var flatContent strings.Builder - fmt.Fprintf(&flatContent, "%s:\\n", ctx.ModuleName()) + fmt.Fprintf(&flatContent, "%s(minSdkVersion:%s):\\n", ctx.ModuleName(), minSdkVersion) for _, key := range FirstUniqueStrings(SortedStringKeys(depInfos)) { info := depInfos[key] - toName := info.To + toName := fmt.Sprintf("%s(minSdkVersion:%s)", info.To, info.MinSdkVersion) if info.IsExternal { toName = toName + " (external)" } diff --git a/apex/apex_test.go b/apex/apex_test.go index c00fd050e..11a8bd291 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -479,18 +479,18 @@ func TestBasicApex(t *testing.T) { ensureListContains(t, noticeInputs, "custom_notice_for_static_lib") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "myjar <- myapex") - ensureListContains(t, fullDepsInfo, "mylib <- myapex") - ensureListContains(t, fullDepsInfo, "mylib2 <- mylib") - ensureListContains(t, fullDepsInfo, "myotherjar <- myjar") - ensureListContains(t, fullDepsInfo, "mysharedjar (external) <- myjar") + ensureListContains(t, fullDepsInfo, "myjar(minSdkVersion:(no version)) <- myapex") + ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex") + ensureListContains(t, fullDepsInfo, "mylib2(minSdkVersion:(no version)) <- mylib") + ensureListContains(t, fullDepsInfo, "myotherjar(minSdkVersion:(no version)) <- myjar") + ensureListContains(t, fullDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external) <- myjar") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " myjar") - ensureListContains(t, flatDepsInfo, " mylib") - ensureListContains(t, flatDepsInfo, " mylib2") - ensureListContains(t, flatDepsInfo, " myotherjar") - ensureListContains(t, flatDepsInfo, " mysharedjar (external)") + ensureListContains(t, flatDepsInfo, " myjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " mylib2(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " myotherjar(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external)") } func TestDefaults(t *testing.T) { @@ -792,14 +792,14 @@ func TestApexWithExplicitStubsDependency(t *testing.T) { ensureNotContains(t, libFooStubsLdFlags, "libbar.so") fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n") - ensureListContains(t, fullDepsInfo, "mylib <- myapex2") - ensureListContains(t, fullDepsInfo, "libbaz <- mylib") - ensureListContains(t, fullDepsInfo, "libfoo (external) <- mylib") + ensureListContains(t, fullDepsInfo, "mylib(minSdkVersion:(no version)) <- myapex2") + ensureListContains(t, fullDepsInfo, "libbaz(minSdkVersion:(no version)) <- mylib") + ensureListContains(t, fullDepsInfo, "libfoo(minSdkVersion:(no version)) (external) <- mylib") flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n") - ensureListContains(t, flatDepsInfo, " mylib") - ensureListContains(t, flatDepsInfo, " libbaz") - ensureListContains(t, flatDepsInfo, " libfoo (external)") + ensureListContains(t, flatDepsInfo, " mylib(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " libbaz(minSdkVersion:(no version))") + ensureListContains(t, flatDepsInfo, " libfoo(minSdkVersion:(no version)) (external)") } func TestApexWithRuntimeLibsDependency(t *testing.T) { diff --git a/apex/builder.go b/apex/builder.go index 2996cc636..f04771c2a 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -694,10 +694,18 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { info.IsExternal = info.IsExternal && externalDep depInfos[to.Name()] = info } else { + toMinSdkVersion := "(no version)" + if m, ok := to.(interface{ MinSdkVersion() string }); ok { + if v := m.MinSdkVersion(); v != "" { + toMinSdkVersion = v + } + } + depInfos[to.Name()] = android.ApexModuleDepInfo{ - To: to.Name(), - From: []string{from.Name()}, - IsExternal: externalDep, + To: to.Name(), + From: []string{from.Name()}, + IsExternal: externalDep, + MinSdkVersion: toMinSdkVersion, } } @@ -705,7 +713,7 @@ func (a *apexBundle) buildApexDependencyInfo(ctx android.ModuleContext) { return !externalDep }) - a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, depInfos) + a.ApexBundleDepsInfo.BuildDepsInfoLists(ctx, proptools.String(a.properties.Min_sdk_version), depInfos) ctx.Build(pctx, android.BuildParams{ Rule: android.Phony, diff --git a/cc/cc.go b/cc/cc.go index ec0f1a08a..01bf5f1ef 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -580,6 +580,10 @@ func (c *Module) SdkVersion() string { return String(c.Properties.Sdk_version) } +func (c *Module) MinSdkVersion() string { + return String(c.Properties.Min_sdk_version) +} + func (c *Module) AlwaysSdk() bool { return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only) } diff --git a/java/java.go b/java/java.go index 6589721f8..549519792 100644 --- a/java/java.go +++ b/java/java.go @@ -604,6 +604,10 @@ func (j *Module) targetSdkVersion() sdkSpec { return j.sdkVersion() } +func (j *Module) MinSdkVersion() string { + return j.minSdkVersion().version.String() +} + func (j *Module) AvailableFor(what string) bool { if what == android.AvailableToPlatform && Bool(j.deviceProperties.Hostdex) { // Exception: for hostdex: true libraries, the platform variant is created @@ -2395,6 +2399,10 @@ func (j *Import) minSdkVersion() sdkSpec { return j.sdkVersion() } +func (j *Import) MinSdkVersion() string { + return j.minSdkVersion().version.String() +} + func (j *Import) Prebuilt() *android.Prebuilt { return &j.prebuilt } -- cgit v1.2.3-59-g8ed1b From 08385bf9ac57ca1f94c5be3fc1379556243a1768 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 6 May 2020 10:23:19 +0100 Subject: Retry: Detect invalid arch specific properties in snapshot Previously, the snapshot code did not know whether a specific property could be arch specific or not and assumed that they all were which meant that it could generate snapshots containing arch specific values for properties that are not arch specific and so would fail when unpacked. This change requires arch specific fields in SdkMemberProperties to be tagged as such using `android:"arch_variant"` (just as in module input property structures). Any property without that must have properties that are common across all variants. Bug: 155628860 Test: m nothing Merged-In: I3df60f0b53ba02ec2c55a80c7da058eac5909d26 Change-Id: I3df60f0b53ba02ec2c55a80c7da058eac5909d26 (cherry picked from commit 864e1b45dbf90e0b79b767be385e5f57f3dbdd25) --- android/sdk.go | 8 +++++++- cc/library_sdk_member.go | 10 +++++----- java/java.go | 2 +- sdk/sdk_test.go | 33 ++++++++++++++++++++++++++++----- sdk/update.go | 32 +++++++++++++++++++++++++++++--- 5 files changed, 70 insertions(+), 15 deletions(-) (limited to 'java/java.go') diff --git a/android/sdk.go b/android/sdk.go index 873e08942..36afc3df2 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -342,9 +342,15 @@ type SdkMemberType interface { // // * The variant property structs are analysed to find exported (capitalized) fields which // 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 + // 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 `android:"arch_variant"` will be allowed to have + // values that differ by arch, fields not tagged as such must have common values across + // all variants. + // // * The sdk module type populates the BpModule structure, creating the arch specific // structure and calls AddToPropertySet(...) on the properties struct to add the member // specific properties in the correct place in the structure. diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index 2c8e31158..730012c5b 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -307,7 +307,7 @@ type nativeLibInfoProperties struct { // The list of possibly common exported include dirs. // // This field is exported as its contents may not be arch specific. - ExportedIncludeDirs android.Paths + ExportedIncludeDirs android.Paths `android:"arch_variant"` // The list of arch specific exported generated include dirs. // @@ -322,23 +322,23 @@ type nativeLibInfoProperties struct { // The list of possibly common exported system include dirs. // // This field is exported as its contents may not be arch specific. - ExportedSystemIncludeDirs android.Paths + ExportedSystemIncludeDirs android.Paths `android:"arch_variant"` // The list of possibly common exported flags. // // This field is exported as its contents may not be arch specific. - ExportedFlags []string + ExportedFlags []string `android:"arch_variant"` // The set of shared libraries // // This field is exported as its contents may not be arch specific. - SharedLibs []string + SharedLibs []string `android:"arch_variant"` // The set of system shared libraries. Note nil and [] are semantically // distinct - see BaseLinkerProperties.System_shared_libs. // // This field is exported as its contents may not be arch specific. - SystemSharedLibs []string + SystemSharedLibs []string `android:"arch_variant"` // The specific stubs version for the lib variant, or empty string if stubs // are not in use. diff --git a/java/java.go b/java/java.go index 549519792..1dba1c078 100644 --- a/java/java.go +++ b/java/java.go @@ -1910,7 +1910,7 @@ func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMembe type librarySdkMemberProperties struct { android.SdkMemberPropertiesBase - JarToExport android.Path + JarToExport android.Path `android:"arch_variant"` AidlIncludeDirs android.Paths } diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go index 095f83607..898ecea68 100644 --- a/sdk/sdk_test.go +++ b/sdk/sdk_test.go @@ -226,8 +226,8 @@ func TestSDkInstall(t *testing.T) { } type EmbeddedPropertiesStruct struct { - S_Embedded_Common string - S_Embedded_Different string + S_Embedded_Common string `android:"arch_variant"` + S_Embedded_Different string `android:"arch_variant"` } type testPropertiesStruct struct { @@ -235,11 +235,11 @@ type testPropertiesStruct struct { private string Public_Kept string `sdk:"keep"` S_Common string - S_Different string + S_Different string `android:"arch_variant"` A_Common []string - A_Different []string + A_Different []string `android:"arch_variant"` F_Common *bool - F_Different *bool + F_Different *bool `android:"arch_variant"` EmbeddedPropertiesStruct } @@ -346,3 +346,26 @@ func TestCommonValueOptimization(t *testing.T) { }, structs[1]) } + +func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) { + common := &testPropertiesStruct{name: "common"} + structs := []propertiesContainer{ + &testPropertiesStruct{ + name: "struct-0", + S_Common: "should-be-but-is-not-common0", + }, + &testPropertiesStruct{ + name: "struct-1", + S_Common: "should-be-but-is-not-common1", + }, + } + + extractor := newCommonValueExtractor(common) + + h := TestHelper{t} + + err := extractor.extractCommonProperties(common, structs) + h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties: + "struct-0" has value "should-be-but-is-not-common0" + "struct-1" has value "should-be-but-is-not-common1"`, err) +} diff --git a/sdk/update.go b/sdk/update.go index 03a5c0379..bcc2c778b 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -1225,6 +1225,9 @@ type extractorProperty struct { // The empty value for the field. emptyValue reflect.Value + + // True if the property can support arch variants false otherwise. + archVariant bool } func (p extractorProperty) String() string { @@ -1303,6 +1306,7 @@ func (e *commonValueExtractor) gatherFields(structType reflect.Type, containingS name, fieldGetter, reflect.Zero(field.Type), + proptools.HasTag(field, "android", "arch_variant"), } e.properties = append(e.properties, property) } @@ -1370,10 +1374,16 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac fieldGetter := property.getter // Check to see if all the structures have the same value for the field. The commonValue - // is nil on entry to the loop and if it is nil on exit then there is no common value, - // otherwise it points to the common value. + // is nil on entry to the loop and if it is nil on exit then there is no common value or + // all the values have been filtered out, otherwise it points to the common value. var commonValue *reflect.Value + // Assume that all the values will be the same. + // + // While similar to this is not quite the same as commonValue == nil. If all the values + // have been filtered out then this will be false but commonValue == nil will be true. + valuesDiffer := false + for i := 0; i < sliceValue.Len(); i++ { container := sliceValue.Index(i).Interface().(propertiesContainer) itemValue := reflect.ValueOf(container.optimizableProperties()) @@ -1387,12 +1397,13 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac // no value in common so break out. if !reflect.DeepEqual(fieldValue.Interface(), commonValue.Interface()) { commonValue = nil + valuesDiffer = true break } } } - // If the fields all have a common value then store it in the common struct field + // If the fields all have common value then store it in the common struct field // and set the input struct's field to the empty value. if commonValue != nil { emptyValue := property.emptyValue @@ -1404,6 +1415,21 @@ func (e *commonValueExtractor) extractCommonProperties(commonProperties interfac fieldValue.Set(emptyValue) } } + + if valuesDiffer && !property.archVariant { + // The values differ but the property does not support arch variants so it + // is an error. + var details strings.Builder + for i := 0; i < sliceValue.Len(); i++ { + container := sliceValue.Index(i).Interface().(propertiesContainer) + itemValue := reflect.ValueOf(container.optimizableProperties()) + fieldValue := fieldGetter(itemValue) + + _, _ = fmt.Fprintf(&details, "\n %q has value %q", container.String(), fieldValue.Interface()) + } + + return fmt.Errorf("field %q is not tagged as \"arch_variant\" but has arch specific properties:%s", property.String(), details.String()) + } } return nil -- cgit v1.2.3-59-g8ed1b From 1a724e666fef89d0797df279546b55d47db35ae8 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 8 May 2020 13:44:43 +0100 Subject: java_sdk_library: Delegate component module to naming scheme Adds a naming scheme abstraction to which the java_sdk_library/import will delegate the task of creating the names of their component modules. The naming scheme can be selected in a module definition but for now the only supported option is "default". Test: m nothing Bug: 155480189 Merged-In: I708657661188ea4a14a4dd8c6bc4b46237bbe5e0 Change-Id: I708657661188ea4a14a4dd8c6bc4b46237bbe5e0 (cherry picked from commit 1b1e8069ec08a9f54cf0f8aa4ed95cab2781b3db) --- java/java.go | 1 + java/sdk_library.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 5 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 1dba1c078..38cde2afe 100644 --- a/java/java.go +++ b/java/java.go @@ -2759,6 +2759,7 @@ func DefaultsFactory() android.Module { &ImportProperties{}, &AARImportProperties{}, &sdkLibraryProperties{}, + &commonToSdkLibraryAndImportProperties{}, &DexImportProperties{}, &android.ApexProperties{}, &RuntimeResourceOverlayProperties{}, diff --git a/java/sdk_library.go b/java/sdk_library.go index dfda61208..68623e958 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -474,6 +474,15 @@ func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep an } type commonToSdkLibraryAndImportProperties struct { + // The naming scheme to use for the components that this module creates. + // + // If not specified then it defaults to "default", which is currently the only + // allowable value. + // + // This is a temporary mechanism to simplify conversion from separate modules for each + // component that follow a different naming pattern to the default one. + // + // TODO(b/155480189) - Remove once naming inconsistencies have been resolved. Naming_scheme *string } @@ -482,27 +491,46 @@ type commonToSdkLibraryAndImport struct { moduleBase *android.ModuleBase scopePaths map[*apiScope]*scopePaths + + namingScheme sdkLibraryComponentNamingScheme + + commonProperties commonToSdkLibraryAndImportProperties } func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase + + moduleBase.AddProperties(&c.commonProperties) +} + +func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { + schemeProperty := proptools.StringDefault(c.commonProperties.Naming_scheme, "default") + switch schemeProperty { + case "default": + c.namingScheme = &defaultNamingScheme{} + default: + ctx.PropertyErrorf("naming_scheme", "expected 'default' but was %q", schemeProperty) + return false + } + + return true } // Name of the java_library module that compiles the stubs source. func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string { - return apiScope.stubsLibraryModuleName(c.moduleBase.BaseModuleName()) + return c.namingScheme.stubsLibraryModuleName(apiScope, c.moduleBase.BaseModuleName()) } // Name of the droidstubs module that generates the stubs source and may also // generate/check the API. func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string { - return apiScope.stubsSourceModuleName(c.moduleBase.BaseModuleName()) + return c.namingScheme.stubsSourceModuleName(apiScope, c.moduleBase.BaseModuleName()) } // Name of the droidstubs module that generates/checks the API. Only used if it // requires different arts to the stubs source generating module. func (c *commonToSdkLibraryAndImport) apiModuleName(apiScope *apiScope) string { - return apiScope.apiModuleName(c.moduleBase.BaseModuleName()) + return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName()) } func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths { @@ -1149,6 +1177,32 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { module.Library.Module.deviceProperties.IsSDKLibrary = true } +// Defines how to name the individual component modules the sdk library creates. +type sdkLibraryComponentNamingScheme interface { + stubsLibraryModuleName(scope *apiScope, baseName string) string + + stubsSourceModuleName(scope *apiScope, baseName string) string + + apiModuleName(scope *apiScope, baseName string) string +} + +type defaultNamingScheme struct { +} + +func (s *defaultNamingScheme) stubsLibraryModuleName(scope *apiScope, baseName string) string { + return scope.stubsLibraryModuleName(baseName) +} + +func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName string) string { + return scope.stubsSourceModuleName(baseName) +} + +func (s *defaultNamingScheme) apiModuleName(scope *apiScope, baseName string) string { + return scope.apiModuleName(baseName) +} + +var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil) + // java_sdk_library is a special Java library that provides optional platform APIs to apps. // In practice, it can be viewed as a combination of several modules: 1) stubs library that clients // are linked against to, 2) droiddoc module that internally generates API stubs source files, @@ -1175,7 +1229,11 @@ func SdkLibraryFactory() android.Module { android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility) android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility) - module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { module.CreateInternalModules(ctx) }) + module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + if module.initCommonAfterDefaultsApplied(ctx) { + module.CreateInternalModules(ctx) + } + }) return module } @@ -1279,7 +1337,11 @@ func sdkLibraryImportFactory() android.Module { android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) - module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { module.createInternalModules(mctx) }) + module.SetDefaultableHook(func(mctx android.DefaultableHookContext) { + if module.initCommonAfterDefaultsApplied(mctx) { + module.createInternalModules(mctx) + } + }) return module } -- cgit v1.2.3-59-g8ed1b From db22475ecb59f5228083ad9ba7f4d1ba2606083b Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 14 May 2020 18:05:32 -0700 Subject: Use system modules for prebuilt SDKs >=30 Prebuilt SDKs >=30 now contain core-for-system-modules.jar, convert them to system modules and use them when compiling against the SDK to allow using javac -source 1.9 -target 1.9. Bug: 117069453 Test: TestClasspath Change-Id: Iebadad5980b952ed91c3ffd56cff1ce1827d3247 --- java/java.go | 17 ++++------- java/prebuilt_apis.go | 35 +++++++++++++++++++++-- java/sdk.go | 26 +++++++++++++++-- java/sdk_test.go | 67 ++++++++++++++++++++++++++++++++++--------- java/testing.go | 78 +++++++++++++++++++++++++++++++-------------------- 5 files changed, 161 insertions(+), 62 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 549519792..517924847 100644 --- a/java/java.go +++ b/java/java.go @@ -629,13 +629,15 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } } else if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) - ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) if j.deviceProperties.EffectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultBootclasspathLibraries...) ctx.AddVariationDependencies(nil, proguardRaiseTag, config.DefaultLibraries...) } } + if sdkDep.systemModules != "" { + ctx.AddVariationDependencies(nil, systemModulesTag, sdkDep.systemModules) + } if ctx.ModuleName() == "android_stubs_current" || ctx.ModuleName() == "android_system_stubs_current" || @@ -1038,19 +1040,10 @@ func addPlugins(deps *deps, pluginJars android.Paths, pluginClasses ...string) { } func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext sdkContext) javaVersion { - sdk, err := sdkContext.sdkVersion().effectiveVersion(ctx) - if err != nil { - ctx.PropertyErrorf("sdk_version", "%s", err) - } if javaVersion != "" { return normalizeJavaVersion(ctx, javaVersion) - } else if ctx.Device() && sdk <= 23 { - return JAVA_VERSION_7 - } else if ctx.Device() && sdk <= 29 { - return JAVA_VERSION_8 - } else if ctx.Device() && ctx.Config().UnbundledBuildUsePrebuiltSdks() { - // TODO(b/142896162): once we have prebuilt system modules we can use 1.9 for unbundled builds - return JAVA_VERSION_8 + } else if ctx.Device() { + return sdkContext.sdkVersion().defaultJavaLanguageVersion(ctx) } else { return JAVA_VERSION_9 } diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index 03bc76bf2..999c72f3c 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -15,11 +15,12 @@ package java import ( - "android/soong/android" "sort" "strings" "github.com/google/blueprint/proptools" + + "android/soong/android" ) func init() { @@ -69,6 +70,10 @@ func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, return } +func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope string, apiver string) string { + return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module +} + func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) { props := struct { Name *string @@ -76,7 +81,7 @@ func createImport(mctx android.LoadHookContext, module string, scope string, api Sdk_version *string Installable *bool }{} - props.Name = proptools.StringPtr(mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module) + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver)) props.Jars = append(props.Jars, path) // TODO(hansson): change to scope after migration is done. props.Sdk_version = proptools.StringPtr("current") @@ -124,6 +129,27 @@ func prebuiltSdkStubs(mctx android.LoadHookContext) { } } +func createSystemModules(mctx android.LoadHookContext, apiver string) { + props := struct { + Name *string + Libs []string + }{} + props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver)) + props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver)) + + mctx.CreateModule(SystemModulesFactory, &props) +} + +func prebuiltSdkSystemModules(mctx android.LoadHookContext) { + for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs { + jar := android.ExistentPathForSource(mctx, + mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar") + if jar.Valid() { + createSystemModules(mctx, apiver) + } + } +} + func prebuiltApiFiles(mctx android.LoadHookContext) { mydir := mctx.ModuleDir() + "/" // //api/.txt @@ -178,6 +204,7 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { if _, ok := mctx.Module().(*prebuiltApis); ok { prebuiltApiFiles(mctx) prebuiltSdkStubs(mctx) + prebuiltSdkSystemModules(mctx) } } @@ -191,7 +218,9 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { // Similarly, it generates a java_import for all API .jar files found under the // directory where the Android.bp is located. Specifically, an API file located // at .///api/.jar generates a java_import module named -// .... +// ___, and for SDK versions >= 30 +// a java_system_modules module named +// _public__system_modules func PrebuiltApisFactory() android.Module { module := &prebuiltApis{} module.AddProperties(&module.properties) diff --git a/java/sdk.go b/java/sdk.go index 4414600fa..f96ecded4 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -253,6 +253,20 @@ func (s sdkSpec) effectiveVersionString(ctx android.EarlyModuleContext) (string, return ver.String(), err } +func (s sdkSpec) defaultJavaLanguageVersion(ctx android.EarlyModuleContext) javaVersion { + sdk, err := s.effectiveVersion(ctx) + if err != nil { + ctx.PropertyErrorf("sdk_version", "%s", err) + } + if sdk <= 23 { + return JAVA_VERSION_7 + } else if sdk <= 29 { + return JAVA_VERSION_8 + } else { + return JAVA_VERSION_9 + } +} + func sdkSpecFrom(str string) sdkSpec { switch str { // special cases first @@ -346,10 +360,16 @@ func decodeSdkDep(ctx android.EarlyModuleContext, sdkContext sdkContext) sdkDep return sdkDep{} } + var systemModules string + if sdkVersion.defaultJavaLanguageVersion(ctx).usesJavaModules() { + systemModules = "sdk_public_" + sdkVersion.version.String() + "_system_modules" + } + return sdkDep{ - useFiles: true, - jars: android.Paths{jarPath.Path(), lambdaStubsPath}, - aidl: android.OptionalPathForPath(aidlPath.Path()), + useFiles: true, + jars: android.Paths{jarPath.Path(), lambdaStubsPath}, + aidl: android.OptionalPathForPath(aidlPath.Path()), + systemModules: systemModules, } } diff --git a/java/sdk_test.go b/java/sdk_test.go index 8eb5ffbad..52d2df552 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -81,6 +81,16 @@ func TestClasspath(t *testing.T) { java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/29/public/framework.aidl", }, + { + + name: "sdk v30", + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, { name: "current", @@ -108,6 +118,16 @@ func TestClasspath(t *testing.T) { java8classpath: []string{"prebuilts/sdk/29/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/29/public/framework.aidl", }, + { + + name: "system_30", + properties: `sdk_version: "system_30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, { name: "test_current", @@ -174,14 +194,26 @@ func TestClasspath(t *testing.T) { java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/29/public/framework.aidl", }, + { + + name: "unbundled sdk v30", + unbundled: true, + properties: `sdk_version: "30",`, + bootclasspath: []string{`""`}, + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", + }, { name: "unbundled current", unbundled: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, + system: "sdk_public_current_system_modules", java8classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, aidl: "-pprebuilts/sdk/current/public/framework.aidl", }, @@ -189,27 +221,30 @@ func TestClasspath(t *testing.T) { name: "pdk default", pdk: true, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk current", pdk: true, properties: `sdk_version: "current",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "pdk 29", pdk: true, properties: `sdk_version: "29",`, bootclasspath: []string{`""`}, - forces8: true, - java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, - aidl: "-pprebuilts/sdk/29/public/framework.aidl", + system: "sdk_public_30_system_modules", + java8classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + java9classpath: []string{"prebuilts/sdk/30/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"}, + aidl: "-pprebuilts/sdk/30/public/framework.aidl", }, { name: "module_current", @@ -292,12 +327,16 @@ func TestClasspath(t *testing.T) { if testcase.system == "none" { system = "--system=none" } else if testcase.system != "" { - system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + dir := "" + if strings.HasPrefix(testcase.system, "sdk_public_") { + dir = "prebuilts/sdk" + } + system = "--system=" + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system") // The module-relative parts of these paths are hardcoded in system_modules.go: systemDeps = []string{ - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "modules"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), - filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system", "release"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "modules"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "lib", "jrt-fs.jar"), + filepath.Join(buildDir, ".intermediates", dir, testcase.system, "android_common", "system", "release"), } } diff --git a/java/testing.go b/java/testing.go index dd3565313..5deabc3dd 100644 --- a/java/testing.go +++ b/java/testing.go @@ -53,36 +53,54 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string "assets_a/a": nil, "assets_b/b": nil, - "prebuilts/sdk/14/public/android.jar": nil, - "prebuilts/sdk/14/public/framework.aidl": nil, - "prebuilts/sdk/14/system/android.jar": nil, - "prebuilts/sdk/17/public/android.jar": nil, - "prebuilts/sdk/17/public/framework.aidl": nil, - "prebuilts/sdk/17/system/android.jar": nil, - "prebuilts/sdk/29/public/android.jar": nil, - "prebuilts/sdk/29/public/framework.aidl": nil, - "prebuilts/sdk/29/system/android.jar": nil, - "prebuilts/sdk/29/system/foo.jar": nil, - "prebuilts/sdk/current/core/android.jar": nil, - "prebuilts/sdk/current/public/android.jar": nil, - "prebuilts/sdk/current/public/framework.aidl": nil, - "prebuilts/sdk/current/public/core.jar": nil, - "prebuilts/sdk/current/system/android.jar": nil, - "prebuilts/sdk/current/test/android.jar": nil, - "prebuilts/sdk/28/public/api/foo.txt": nil, - "prebuilts/sdk/28/system/api/foo.txt": nil, - "prebuilts/sdk/28/test/api/foo.txt": nil, - "prebuilts/sdk/28/public/api/foo-removed.txt": nil, - "prebuilts/sdk/28/system/api/foo-removed.txt": nil, - "prebuilts/sdk/28/test/api/foo-removed.txt": nil, - "prebuilts/sdk/28/public/api/bar.txt": nil, - "prebuilts/sdk/28/system/api/bar.txt": nil, - "prebuilts/sdk/28/test/api/bar.txt": nil, - "prebuilts/sdk/28/public/api/bar-removed.txt": nil, - "prebuilts/sdk/28/system/api/bar-removed.txt": nil, - "prebuilts/sdk/28/test/api/bar-removed.txt": nil, - "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, - "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "current"],}`), + "prebuilts/sdk/14/public/android.jar": nil, + "prebuilts/sdk/14/public/framework.aidl": nil, + "prebuilts/sdk/14/system/android.jar": nil, + "prebuilts/sdk/17/public/android.jar": nil, + "prebuilts/sdk/17/public/framework.aidl": nil, + "prebuilts/sdk/17/system/android.jar": nil, + "prebuilts/sdk/29/public/android.jar": nil, + "prebuilts/sdk/29/public/framework.aidl": nil, + "prebuilts/sdk/29/system/android.jar": nil, + "prebuilts/sdk/29/system/foo.jar": nil, + "prebuilts/sdk/30/public/android.jar": nil, + "prebuilts/sdk/30/public/framework.aidl": nil, + "prebuilts/sdk/30/system/android.jar": nil, + "prebuilts/sdk/30/system/foo.jar": nil, + "prebuilts/sdk/30/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/core/android.jar": nil, + "prebuilts/sdk/current/public/android.jar": nil, + "prebuilts/sdk/current/public/framework.aidl": nil, + "prebuilts/sdk/current/public/core.jar": nil, + "prebuilts/sdk/current/public/core-for-system-modules.jar": nil, + "prebuilts/sdk/current/system/android.jar": nil, + "prebuilts/sdk/current/test/android.jar": nil, + "prebuilts/sdk/28/public/api/foo.txt": nil, + "prebuilts/sdk/28/system/api/foo.txt": nil, + "prebuilts/sdk/28/test/api/foo.txt": nil, + "prebuilts/sdk/28/public/api/foo-removed.txt": nil, + "prebuilts/sdk/28/system/api/foo-removed.txt": nil, + "prebuilts/sdk/28/test/api/foo-removed.txt": nil, + "prebuilts/sdk/28/public/api/bar.txt": nil, + "prebuilts/sdk/28/system/api/bar.txt": nil, + "prebuilts/sdk/28/test/api/bar.txt": nil, + "prebuilts/sdk/28/public/api/bar-removed.txt": nil, + "prebuilts/sdk/28/system/api/bar-removed.txt": nil, + "prebuilts/sdk/28/test/api/bar-removed.txt": nil, + "prebuilts/sdk/30/public/api/foo.txt": nil, + "prebuilts/sdk/30/system/api/foo.txt": nil, + "prebuilts/sdk/30/test/api/foo.txt": nil, + "prebuilts/sdk/30/public/api/foo-removed.txt": nil, + "prebuilts/sdk/30/system/api/foo-removed.txt": nil, + "prebuilts/sdk/30/test/api/foo-removed.txt": nil, + "prebuilts/sdk/30/public/api/bar.txt": nil, + "prebuilts/sdk/30/system/api/bar.txt": nil, + "prebuilts/sdk/30/test/api/bar.txt": nil, + "prebuilts/sdk/30/public/api/bar-removed.txt": nil, + "prebuilts/sdk/30/system/api/bar-removed.txt": nil, + "prebuilts/sdk/30/test/api/bar-removed.txt": nil, + "prebuilts/sdk/tools/core-lambda-stubs.jar": nil, + "prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["14", "28", "30", "current"],}`), "prebuilts/apk/app.apk": nil, "prebuilts/apk/app_arm.apk": nil, -- cgit v1.2.3-59-g8ed1b From eb03296b57a414b5c327ae6b4057f279f6903439 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 13 May 2020 11:05:02 -0700 Subject: Don't use SDK variant for vendor JNI libraries Vendor JNI libraries already have stable APIs enforced by the VNDK, they shouldn't use SDK variants. Bug: 156225490 Test: TestJNISDK Change-Id: I21ba67e8e9fb05016caf5888129adc1a939545c2 Merged-In: I21ba67e8e9fb05016caf5888129adc1a939545c2 (cherry picked from commit c2d24050c5e3a09b7bc5236d15f24afa2405911f) --- android/module.go | 7 +++++++ java/app.go | 47 ++++++++++++++++++++++++++++++++--------------- java/app_test.go | 43 +++++++++++++++++++++++++++++++++---------- java/java.go | 3 +-- 4 files changed, 73 insertions(+), 27 deletions(-) (limited to 'java/java.go') diff --git a/android/module.go b/android/module.go index f16407272..baf348aaf 100644 --- a/android/module.go +++ b/android/module.go @@ -886,6 +886,13 @@ func (m *ModuleBase) SystemExtSpecific() bool { return Bool(m.commonProperties.System_ext_specific) } +// RequiresStableAPIs returns true if the module will be installed to a partition that may +// be updated separately from the system image. +func (m *ModuleBase) RequiresStableAPIs(ctx BaseModuleContext) bool { + return m.SocSpecific() || m.DeviceSpecific() || + (m.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) +} + func (m *ModuleBase) PartitionTag(config DeviceConfig) string { partition := "system" if m.SocSpecific() { diff --git a/java/app.go b/java/app.go index 156deb8f9..f9ce4bf0e 100755 --- a/java/app.go +++ b/java/app.go @@ -252,7 +252,10 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) { // If the app builds against an Android SDK use the SDK variant of JNI dependencies // unless jni_uses_platform_apis is set. - if (usesSDK && !Bool(a.appProperties.Jni_uses_platform_apis)) || + // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already + // have stable APIs through the VNDK. + if (usesSDK && !a.RequiresStableAPIs(ctx) && + !Bool(a.appProperties.Jni_uses_platform_apis)) || Bool(a.appProperties.Jni_uses_sdk_apis) { variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) } @@ -583,7 +586,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { dexJarFile := a.dexBuildActions(ctx) - jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) + jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) jniJarFile := a.jniBuildActions(jniLibs, ctx) if ctx.Failed() { @@ -639,12 +642,25 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.buildAppDependencyInfo(ctx) } -func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool, +type appDepsInterface interface { + sdkVersion() sdkSpec + minSdkVersion() sdkSpec + RequiresStableAPIs(ctx android.BaseModuleContext) bool +} + +func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, + shouldCollectRecursiveNativeDeps bool, checkNativeSdkVersion bool) ([]jniLib, []Certificate) { + var jniLibs []jniLib var certificates []Certificate seenModulePaths := make(map[string]bool) + if checkNativeSdkVersion { + checkNativeSdkVersion = app.sdkVersion().specified() && + app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx) + } + ctx.WalkDeps(func(module android.Module, parent android.Module) bool { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -662,16 +678,9 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps } seenModulePaths[path.String()] = true - if checkNativeSdkVersion { - if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok { - if app.sdkVersion().specified() && - app.sdkVersion().kind != sdkCorePlatform && - dep.SdkVersion() == "" { - ctx.PropertyErrorf("jni_libs", - "JNI dependency %q uses platform APIs, but this module does not", - otherName) - } - } + if checkNativeSdkVersion && dep.SdkVersion() == "" { + ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not", + otherName) } if lib.Valid() { @@ -1257,7 +1266,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set") } - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, a, false, false) // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_PACKAGE_SPLITS @@ -1374,6 +1383,14 @@ func (a *AndroidAppImport) Privileged() bool { return Bool(a.properties.Privileged) } +func (a *AndroidAppImport) sdkVersion() sdkSpec { + return sdkSpecFrom("") +} + +func (a *AndroidAppImport) minSdkVersion() sdkSpec { + return sdkSpecFrom("") +} + func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { props := reflect.TypeOf((*AndroidAppImportProperties)(nil)) @@ -1548,7 +1565,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC r.aapt.buildActions(ctx, r, aaptLinkFlags...) // Sign the built package - _, certificates := collectAppDeps(ctx, false, false) + _, certificates := collectAppDeps(ctx, r, false, false) certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, nil) diff --git a/java/app_test.go b/java/app_test.go index be9815099..7d47a5c2f 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -1144,25 +1144,44 @@ func TestJNISDK(t *testing.T) { platform_apis: true, jni_uses_sdk_apis: true, } + + cc_library { + name: "libvendorjni", + system_shared_libs: [], + stl: "none", + vendor: true, + } + + android_test { + name: "app_vendor", + jni_libs: ["libvendorjni"], + sdk_version: "current", + vendor: true, + } `) testCases := []struct { - name string - sdkJNI bool + name string + sdkJNI bool + vendorJNI bool }{ - {"app_platform", false}, - {"app_sdk", true}, - {"app_force_platform", false}, - {"app_force_sdk", true}, + {name: "app_platform"}, + {name: "app_sdk", sdkJNI: true}, + {name: "app_force_platform"}, + {name: "app_force_sdk", sdkJNI: true}, + {name: "app_vendor", vendorJNI: true}, } + platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). + Output("libjni.so").Output.String() + sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). + Output("libjni.so").Output.String() + vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared"). + Output("libvendorjni.so").Output.String() + for _, test := range testCases { t.Run(test.name, func(t *testing.T) { app := ctx.ModuleForTests(test.name, "android_common") - platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared"). - Output("libjni.so").Output.String() - sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared"). - Output("libjni.so").Output.String() jniLibZip := app.MaybeOutput("jnilibs.zip") if len(jniLibZip.Implicits) != 1 { @@ -1174,6 +1193,10 @@ func TestJNISDK(t *testing.T) { if gotJNI != sdkJNI { t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI) } + } else if test.vendorJNI { + if gotJNI != vendorJNI { + t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI) + } } else { if gotJNI != platformJNI { t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI) diff --git a/java/java.go b/java/java.go index 38cde2afe..066e09afb 100644 --- a/java/java.go +++ b/java/java.go @@ -95,8 +95,7 @@ func (j *Module) CheckStableSdkVersion() error { } func (j *Module) checkSdkVersions(ctx android.ModuleContext) { - if j.SocSpecific() || j.DeviceSpecific() || - (j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) { + if j.RequiresStableAPIs(ctx) { if sc, ok := ctx.Module().(sdkContext); ok { if !sc.sdkVersion().specified() { ctx.PropertyErrorf("sdk_version", -- cgit v1.2.3-59-g8ed1b From ba60625021fc6bf429c00b37dfd79b6082861ab7 Mon Sep 17 00:00:00 2001 From: easoncylee Date: Thu, 30 Apr 2020 14:57:06 +0800 Subject: Add test_mainline_modules to the auto-gen test config(AndroidJUnitTest only). To support parameterized mainline modules in Test Mapping, we plan to add a new parameter called test_mainline_modules in build system to auto-generate the test config based on the parameter. For detailed information: go/test-mapping-mainline-gcl (search for auto-generated pattern) Bug: 155238134 Test: add "test_mainline_modules: [some.apk]" to TetheringTests, and build the modules, confirm the parameterized option is added in the test config. Change-Id: I41ba8749ce46da62db402a8b8a555d4874e1cfc0 Merged-In: I41ba8749ce46da62db402a8b8a555d4874e1cfc0 --- java/app.go | 7 ++++++- java/java.go | 4 ++++ tradefed/autogen.go | 18 +++++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) (limited to 'java/java.go') diff --git a/java/app.go b/java/app.go index 756203c56..611a7d809 100755 --- a/java/app.go +++ b/java/app.go @@ -980,6 +980,7 @@ func (a *AndroidTest) InstallInTestcases() bool { } func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { + var configs []tradefed.Config if a.appTestProperties.Instrumentation_target_package != nil { a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+*a.appTestProperties.Instrumentation_target_package) @@ -992,8 +993,12 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { } a.generateAndroidBuildActions(ctx) + for _, module := range a.testProperties.Test_mainline_modules { + configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) + } + testConfig := tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, - a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config) + a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config, configs) a.testConfig = a.FixTestConfig(ctx, testConfig) a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) } diff --git a/java/java.go b/java/java.go index a5d69e304..6141a40b0 100644 --- a/java/java.go +++ b/java/java.go @@ -2029,6 +2029,10 @@ type testProperties struct { // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true // explicitly. Auto_gen_config *bool + + // Add parameterized mainline modules to auto generated test config. The options will be + // handled by TradeFed to do downloading and installing the specified modules on the device. + Test_mainline_modules []string } type testHelperLibraryProperties struct { diff --git a/tradefed/autogen.go b/tradefed/autogen.go index 596284beb..be44cac5d 100644 --- a/tradefed/autogen.go +++ b/tradefed/autogen.go @@ -219,31 +219,39 @@ func AutoGenRustTestConfig(ctx android.ModuleContext, name string, testConfigPro } var autogenInstrumentationTest = pctx.StaticRule("autogenInstrumentationTest", blueprint.RuleParams{ - Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template", + Command: "${AutoGenTestConfigScript} $out $in ${EmptyTestConfig} $template ${extraConfigs}", CommandDeps: []string{ "${AutoGenTestConfigScript}", "${EmptyTestConfig}", "$template", }, -}, "name", "template") +}, "name", "template", "extraConfigs") func AutoGenInstrumentationTestConfig(ctx android.ModuleContext, testConfigProp *string, - testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool) android.Path { + testConfigTemplateProp *string, manifest android.Path, testSuites []string, autoGenConfig *bool, configs []Config) android.Path { path, autogenPath := testConfigPath(ctx, testConfigProp, testSuites, autoGenConfig, testConfigTemplateProp) + var configStrings []string if autogenPath != nil { template := "${InstrumentationTestConfigTemplate}" moduleTemplate := getTestConfigTemplate(ctx, testConfigTemplateProp) if moduleTemplate.Valid() { template = moduleTemplate.String() } + for _, config := range configs { + configStrings = append(configStrings, config.Config()) + } + extraConfigs := strings.Join(configStrings, fmt.Sprintf("\\n%s", test_xml_indent)) + extraConfigs = fmt.Sprintf("--extra-configs '%s'", extraConfigs) + ctx.Build(pctx, android.BuildParams{ Rule: autogenInstrumentationTest, Description: "test config", Input: manifest, Output: autogenPath, Args: map[string]string{ - "name": ctx.ModuleName(), - "template": template, + "name": ctx.ModuleName(), + "template": template, + "extraConfigs": extraConfigs, }, }) return autogenPath -- cgit v1.2.3-59-g8ed1b From c8f2f186d1603f992bedbaa1f878bb03dc7c512b Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Sun, 17 May 2020 08:34:50 +0100 Subject: Extract common behavior between Module and Import Although the duplication being eliminated here is minimal follow up changes will add more functionality that is common to Module and Import. Test: m nothing Bug: 156723295 Merged-In: I1733405526764272beba63470a9bc8a958d41024 Change-Id: I1733405526764272beba63470a9bc8a958d41024 (cherry picked from commit 0d3c2e136b24272a51feed84eec947b7f42cf057) --- java/java.go | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index a5d69e304..da9bd3dfe 100644 --- a/java/java.go +++ b/java/java.go @@ -354,6 +354,22 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { return BoolDefault(me.Optimize.Enabled, me.Optimize.EnabledByDefault) } +// Functionality common to Module and Import +type embeddableInModuleAndImport struct { +} + +// Module/Import's DepIsInSameApex(...) delegates to this method. +// +// This cannot implement DepIsInSameApex(...) directly as that leads to ambiguity with +// the one provided by ApexModuleBase. +func (e *embeddableInModuleAndImport) depIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { + // dependencies other than the static linkage are all considered crossing APEX boundary + if staticLibTag == ctx.OtherModuleDependencyTag(dep) { + return true + } + return false +} + // Module contains the properties and members used by all java module types type Module struct { android.ModuleBase @@ -361,6 +377,9 @@ type Module struct { android.ApexModuleBase android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties CompilerProperties protoProperties android.ProtoProperties deviceProperties CompilerDeviceProperties @@ -1765,11 +1784,7 @@ func (j *Module) hasCode(ctx android.ModuleContext) bool { } func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // Dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } func (j *Module) Stem() string { @@ -2377,6 +2392,9 @@ type Import struct { prebuilt android.Prebuilt android.SdkBase + // Functionality common to Module and Import. + embeddableInModuleAndImport + properties ImportProperties combinedClasspathFile android.Path @@ -2508,11 +2526,7 @@ func (j *Import) SrcJarArgs() ([]string, android.Paths) { } func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - // dependencies other than the static linkage are all considered crossing APEX boundary - if staticLibTag == ctx.OtherModuleDependencyTag(dep) { - return true - } - return false + return j.depIsInSameApex(ctx, dep) } // Add compile time check for interface implementation -- cgit v1.2.3-59-g8ed1b From 442a47552193e2893dbbc1b67a9a1bbd08903314 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 15 May 2020 10:20:31 +0100 Subject: Improve tracking of exported sdk libraries The build tracks the java_sdk_library/_import modules that are referenced by libraries so that it can ensure that any Android app that includes code that depends on one of those modules has the appropriate entry in their manifest. Unfortunately, there were a couple of issues with that: 1) It only tracks direct references to the java_sdk_library module itself, e.g. android.test.mock. Direct references to the stubs module, e.g. android.test.mock.stubs were not tracked. Making it possible for Android apps to reference libraries which would not be available at runtime. 2) The logic for determining whether something was a java_sdk_library was repeated in a number of places making it difficult to allow java_sdk_library/_import instances to determine whether they should be treated as an Android shared library. 3) It tracks (and could use) even those java_sdk_library instances which do not represent a shared library, e.g. the ones that set api_only: true. While this change will simplifty fixing that the actual issue will be fixed in a follow up change. Changes: * Added EmbeddableSdkLibraryComponent and embedded it into java_sdk_library/_import, java_library and java_import. It provides the common code to minimize duplication. It contains an SdkLibraryToImplicitlyTrack field that if set will cause any references to the containing module to add the SdkLibraryParent to the list of implicit sdk libraries being tracked. * Changed code that assumed that anything that implemented SdkLibraryDependency required tracking to use the OptionalImplicitSdkLibrary() method to get the optional name of the sdk library to track. That will allow a follow up change to return nil from that method to exclude an sdk library from being tracked. * Moved SdkLibraryDependency from java.go to sdk_library.go as that is a better place for it to be. * Changed the stubs java_library/java_import creation code to initialize the SdkLibraryToImplicitlyTrack field with the name of the creating module. * Initialized the SdkLibraryToImplicitlyTrack field in the java_sdk_library/_import so that direct references to them will be tracked too. * Added tests to verify that direct access to the .stubs child of both java_sdk_library and java_sdk_library_import are tracked properly. Test: atest CtsProviderTestCases - which relies on android.test.mock being implicitly tracked to verify that I had not broken anything. Used aapt2 dump badging to read the manifest. m nothing - to run the new tests which failed before fixing the code. Bug: 156723295 Merged-In: Ia99def91e9b74d2ed0a777de04b476c00ea0393d Change-Id: Ia99def91e9b74d2ed0a777de04b476c00ea0393d (cherry picked from commit 859fe961b015259368e9994969b569eb34f54ddc) --- java/aar.go | 7 ++-- java/app_test.go | 24 ++++++++++++++ java/java.go | 33 +++++++++++++++---- java/java_test.go | 22 ++++++++++--- java/sdk_library.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 166 insertions(+), 14 deletions(-) (limited to 'java/java.go') diff --git a/java/aar.go b/java/aar.go index 0e103f248..c8daf835b 100644 --- a/java/aar.go +++ b/java/aar.go @@ -379,8 +379,11 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati sharedLibs = append(sharedLibs, exportPackage) } - if _, ok := module.(SdkLibraryDependency); ok { - sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module)) + // If the module is (or possibly could be) a component of a java_sdk_library + // (including the java_sdk_library) itself then append any implicit sdk library + // names to the list of sdk libraries to be added to the manifest. + if component, ok := module.(SdkLibraryComponentDependency); ok { + sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) } case frameworkResTag: diff --git a/java/app_test.go b/java/app_test.go index c731a1713..12b935ed3 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2382,6 +2382,20 @@ func TestUsesLibraries(t *testing.T) { sdk_version: "current", } + java_sdk_library { + name: "qux", + srcs: ["a.java"], + api_packages: ["qux"], + sdk_version: "current", + } + + java_sdk_library { + name: "quuz", + srcs: ["a.java"], + api_packages: ["quuz"], + sdk_version: "current", + } + java_sdk_library { name: "bar", srcs: ["a.java"], @@ -2392,6 +2406,7 @@ func TestUsesLibraries(t *testing.T) { android_app { name: "app", srcs: ["a.java"], + libs: ["qux", "quuz.stubs"], uses_libs: ["foo"], sdk_version: "current", optional_uses_libs: [ @@ -2422,6 +2437,15 @@ func TestUsesLibraries(t *testing.T) { app := ctx.ModuleForTests("app", "android_common") prebuilt := ctx.ModuleForTests("prebuilt", "android_common") + // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. + manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + // Test that all libraries are verified cmd := app.Rule("verify_uses_libraries").RuleParams.Command if w := "--uses-library foo"; !strings.Contains(cmd, w) { diff --git a/java/java.go b/java/java.go index da9bd3dfe..00b11f77a 100644 --- a/java/java.go +++ b/java/java.go @@ -355,7 +355,17 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { } // Functionality common to Module and Import +// +// It is embedded in Module so its functionality can be used by methods in Module +// but it is currently only initialized by Import and Library. type embeddableInModuleAndImport struct { + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent +} + +func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) { + e.initSdkLibraryComponent(moduleBase) } // Module/Import's DepIsInSameApex(...) delegates to this method. @@ -496,11 +506,6 @@ type Dependency interface { JacocoReportClassesFile() android.Path } -type SdkLibraryDependency interface { - SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths - SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths -} - type xref interface { XrefJavaFiles() android.Paths } @@ -930,6 +935,12 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } } + // If this is a component library (stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -949,7 +960,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported - j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) + j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -1990,6 +2001,8 @@ func LibraryFactory() android.Module { &module.Module.protoProperties, &module.libraryProperties) + module.initModuleAndImport(&module.ModuleBase) + android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -2451,6 +2464,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.combinedClasspathFile = outputFile + // If this is a component library (impl, stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2567,6 +2586,8 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) + module.initModuleAndImport(&module.ModuleBase) + android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) diff --git a/java/java_test.go b/java/java_test.go index 4f3a803ff..4c085cf0f 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "reflect" + "sort" "strconv" "strings" "testing" @@ -1153,13 +1154,25 @@ func TestJavaSdkLibrary(t *testing.T) { java_library { name: "baz", srcs: ["c.java"], - libs: ["foo", "bar"], + libs: ["foo", "bar.stubs"], sdk_version: "system_current", } + java_sdk_library_import { + name: "quuz", + public: { + jars: ["c.jar"], + }, + } + java_sdk_library_import { + name: "fred", + public: { + jars: ["b.jar"], + }, + } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz"], + libs: ["baz", "fred", "quuz.stubs"], sdk_version: "system_current", } java_library { @@ -1224,8 +1237,9 @@ func TestJavaSdkLibrary(t *testing.T) { qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { sdkLibs := quxLib.ExportedSdkLibs() - if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { - t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) + sort.Strings(sdkLibs) + if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { + t.Errorf("qux should export %q but exports %q", w, sdkLibs) } } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 5efb4d045..0334f80d3 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -543,12 +543,18 @@ type commonToSdkLibraryAndImport struct { namingScheme sdkLibraryComponentNamingScheme commonProperties commonToSdkLibraryAndImportProperties + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent } func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase moduleBase.AddProperties(&c.commonProperties) + + // Initialize this as an sdk library component. + c.initSdkLibraryComponent(moduleBase) } func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { @@ -563,6 +569,9 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return false } + // Use the name specified in the module definition as the owner. + c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + return true } @@ -728,6 +737,84 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android. return paths.stubsHeaderPath } +func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { + componentProps := &struct { + SdkLibraryToImplicitlyTrack *string + }{ + // Mark the stubs library as being components of this java_sdk_library so that + // any app that includes code which depends (directly or indirectly) on the stubs + // library will have the appropriate invocation inserted into its + // manifest if necessary. + SdkLibraryToImplicitlyTrack: proptools.StringPtr(c.moduleBase.BaseModuleName()), + } + + return componentProps +} + +// Properties related to the use of a module as an component of a java_sdk_library. +type SdkLibraryComponentProperties struct { + + // The name of the java_sdk_library/_import to add to a entry + // in the AndroidManifest.xml of any Android app that includes code that references + // this module. If not set then no java_sdk_library/_import is tracked. + SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` +} + +// Structure to be embedded in a module struct that needs to support the +// SdkLibraryComponentDependency interface. +type EmbeddableSdkLibraryComponent struct { + sdkLibraryComponentProperties SdkLibraryComponentProperties +} + +func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) { + moduleBase.AddProperties(&e.sdkLibraryComponentProperties) +} + +// to satisfy SdkLibraryComponentDependency +func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string { + if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil { + return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack} + } + return nil +} + +// Implemented by modules that are (or possibly could be) a component of a java_sdk_library +// (including the java_sdk_library) itself. +type SdkLibraryComponentDependency interface { + // The optional name of the sdk library that should be implicitly added to the + // AndroidManifest of an app that contains code which references the sdk library. + // + // Returns an array containing 0 or 1 items rather than a *string to make it easier + // to append this to the list of exported sdk libraries. + OptionalImplicitSdkLibrary() []string +} + +// Make sure that all the module types that are components of java_sdk_library/_import +// and which can be referenced (directly or indirectly) from an android app implement +// the SdkLibraryComponentDependency interface. +var _ SdkLibraryComponentDependency = (*Library)(nil) +var _ SdkLibraryComponentDependency = (*Import)(nil) +var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) +var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil) + +// Provides access to sdk_version related header and implentation jars. +type SdkLibraryDependency interface { + SdkLibraryComponentDependency + + // Get the header jars appropriate for the supplied sdk_version. + // + // These are turbine generated jars so they only change if the externals of the + // class changes but it does not contain and implementation or JavaDoc. + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths + + // Get the implementation jars appropriate for the supplied sdk version. + // + // These are either the implementation jar for the whole sdk library or the implementation + // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise + // they are identical to the corresponding header jars. + SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths +} + type SdkLibrary struct { Library @@ -978,7 +1065,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Dist.Tag = proptools.StringPtr(".jar") } - mctx.CreateModule(LibraryFactory, &props) + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } // Creates a droidstubs module that creates stubs source files from the given full source @@ -1321,6 +1408,8 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { &module.protoProperties, ) + module.initSdkLibraryComponent(&module.ModuleBase) + module.properties.Installable = proptools.BoolPtr(true) module.deviceProperties.IsSDKLibrary = true } @@ -1569,7 +1658,8 @@ func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl // The imports are preferred if the java_sdk_library_import is preferred. props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) - mctx.CreateModule(ImportFactory, &props) + + mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { -- cgit v1.2.3-59-g8ed1b From 98c71228f1f81cba80f17a73df6e7ace57e83a30 Mon Sep 17 00:00:00 2001 From: David Srbecky Date: Wed, 20 May 2020 22:20:28 +0100 Subject: Allow the user to explicitly set the java Uncompress_dex property. ART tests need to explicitly control the compression. Bug: 157239179 Test: "atest ArtGtestsTarget" with http://go/aog/1302773 Change-Id: I4490aa0a61fa71f830feb6a46dffd8d20fccfc66 --- android/neverallow.go | 10 ++++++++++ android/neverallow_test.go | 28 ++++++++++++++++++++++++++-- java/app.go | 9 +++++---- java/app_test.go | 26 ++++++++++++++++++++++++++ java/dex.go | 5 +++-- java/java.go | 20 ++++++++++++++------ 6 files changed, 84 insertions(+), 14 deletions(-) (limited to 'java/java.go') diff --git a/android/neverallow.go b/android/neverallow.go index f9fc03caa..9e075b719 100644 --- a/android/neverallow.go +++ b/android/neverallow.go @@ -55,6 +55,7 @@ func init() { AddNeverAllowRules(createMediaRules()...) AddNeverAllowRules(createJavaDeviceForHostRules()...) AddNeverAllowRules(createCcSdkVariantRules()...) + AddNeverAllowRules(createUncompressDexRules()...) } // Add a NeverAllow rule to the set of rules to apply. @@ -210,6 +211,15 @@ func createCcSdkVariantRules() []Rule { } } +func createUncompressDexRules() []Rule { + return []Rule{ + NeverAllow(). + NotIn("art"). + WithMatcher("uncompress_dex", isSetMatcherInstance). + Because("uncompress_dex is only allowed for certain jars for test in art."), + } +} + func neverallowMutator(ctx BottomUpMutatorContext) { m, ok := ctx.Module().(Module) if !ok { diff --git a/android/neverallow_test.go b/android/neverallow_test.go index 2fc42e31f..85c8c5908 100644 --- a/android/neverallow_test.go +++ b/android/neverallow_test.go @@ -303,6 +303,29 @@ var neverallowTests = []struct { `module "outside_whitelist": violates neverallow`, }, }, + { + name: "uncompress_dex inside art", + fs: map[string][]byte{ + "art/Android.bp": []byte(` + java_library { + name: "inside_art_libraries", + uncompress_dex: true, + }`), + }, + }, + { + name: "uncompress_dex outside art", + fs: map[string][]byte{ + "other/Android.bp": []byte(` + java_library { + name: "outside_art_libraries", + uncompress_dex: true, + }`), + }, + expectedErrors: []string{ + "module \"outside_art_libraries\": violates neverallow", + }, + }, } func TestNeverallow(t *testing.T) { @@ -396,8 +419,9 @@ func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) { } type mockJavaLibraryProperties struct { - Libs []string - Sdk_version *string + Libs []string + Sdk_version *string + Uncompress_dex *bool } type mockJavaLibraryModule struct { diff --git a/java/app.go b/java/app.go index 86cf7471d..5c694b984 100755 --- a/java/app.go +++ b/java/app.go @@ -540,16 +540,17 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path { installDir = filepath.Join("app", a.installApkName) } a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk") - a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx) - + if a.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx)) + } + a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries() a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx) a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx) a.dexpreopter.manifestFile = a.mergedManifestFile - a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex - if ctx.ModuleName() != "framework-res" { a.Module.compile(ctx, a.aaptSrcJar) } diff --git a/java/app_test.go b/java/app_test.go index c731a1713..ec9d51b4a 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2682,6 +2682,32 @@ func TestUncompressDex(t *testing.T) { uncompressedPlatform: true, uncompressedUnbundled: true, }, + { + name: "normal_uncompress_dex_true", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: true, + } + `, + uncompressedPlatform: true, + uncompressedUnbundled: true, + }, + { + name: "normal_uncompress_dex_false", + bp: ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + uncompress_dex: false, + } + `, + uncompressedPlatform: false, + uncompressedUnbundled: false, + }, } test := func(t *testing.T, bp string, want bool, unbundled bool) { diff --git a/java/dex.go b/java/dex.go index 6afdb6dc4..62f17c6d8 100644 --- a/java/dex.go +++ b/java/dex.go @@ -18,6 +18,7 @@ import ( "strings" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" "android/soong/android" ) @@ -177,7 +178,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, outDir := android.PathForModuleOut(ctx, "dex") zipFlags := "--ignore_missing_files" - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { zipFlags += " -L 0" } @@ -214,7 +215,7 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, }, }) } - if j.deviceProperties.UncompressDex { + if proptools.Bool(j.deviceProperties.Uncompress_dex) { alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName) TransformZipAlign(ctx, alignedJavalibJar, javalibJar) javalibJar = alignedJavalibJar diff --git a/java/java.go b/java/java.go index da9bd3dfe..26b785c9e 100644 --- a/java/java.go +++ b/java/java.go @@ -342,8 +342,13 @@ type CompilerDeviceProperties struct { // set the name of the output Stem *string - UncompressDex bool `blueprint:"mutated"` - IsSDKLibrary bool `blueprint:"mutated"` + // Keep the data uncompressed. We always need uncompressed dex for execution, + // so this might actually save space by avoiding storing the same data twice. + // This defaults to reasonable value based on module and should not be set. + // It exists only to support ART tests. + Uncompress_dex *bool + + IsSDKLibrary bool `blueprint:"mutated"` // If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file. // Defaults to false. @@ -1560,7 +1565,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Hidden API CSV generation and dex encoding dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, - j.deviceProperties.UncompressDex) + proptools.Bool(j.deviceProperties.Uncompress_dex)) // merge dex jar with resources if necessary if j.resourceJar != nil { @@ -1568,7 +1573,7 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName) TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{}, false, nil, nil) - if j.deviceProperties.UncompressDex { + if *j.deviceProperties.Uncompress_dex { combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName) TransformZipAlign(ctx, combinedAlignedJar, combinedJar) dexOutputFile = combinedAlignedJar @@ -1845,8 +1850,11 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.checkSdkVersions(ctx) j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar") j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter) - j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex + if j.deviceProperties.Uncompress_dex == nil { + // If the value was not force-set by the user, use reasonable default based on the module. + j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter)) + } + j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex j.compile(ctx, nil) exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() -- cgit v1.2.3-59-g8ed1b From ed0314270d226d5a8769439a607f79b8c974f793 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 25 May 2020 01:55:59 +0000 Subject: Revert "Improve tracking of exported sdk libraries" Revert submission 11569833 Reason for revert: Broke presubmit: b/157231582 Reverted Changes: Ia99def91e:Improve tracking of exported sdk libraries If91b4d106:java_sdk_library: Do not expose stubs implementati... Id6d76e56c:java_sdk_library: Access outputs using tags Change-Id: I3a07d412e795df512c430e4d2ed221f4d17e904a --- java/aar.go | 7 ++-- java/app_test.go | 24 -------------- java/java.go | 33 ++++--------------- java/java_test.go | 22 +++---------- java/sdk_library.go | 94 ++--------------------------------------------------- 5 files changed, 14 insertions(+), 166 deletions(-) (limited to 'java/java.go') diff --git a/java/aar.go b/java/aar.go index c8daf835b..0e103f248 100644 --- a/java/aar.go +++ b/java/aar.go @@ -379,11 +379,8 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati sharedLibs = append(sharedLibs, exportPackage) } - // If the module is (or possibly could be) a component of a java_sdk_library - // (including the java_sdk_library) itself then append any implicit sdk library - // names to the list of sdk libraries to be added to the manifest. - if component, ok := module.(SdkLibraryComponentDependency); ok { - sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) + if _, ok := module.(SdkLibraryDependency); ok { + sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module)) } case frameworkResTag: diff --git a/java/app_test.go b/java/app_test.go index 12b935ed3..c731a1713 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2382,20 +2382,6 @@ func TestUsesLibraries(t *testing.T) { sdk_version: "current", } - java_sdk_library { - name: "qux", - srcs: ["a.java"], - api_packages: ["qux"], - sdk_version: "current", - } - - java_sdk_library { - name: "quuz", - srcs: ["a.java"], - api_packages: ["quuz"], - sdk_version: "current", - } - java_sdk_library { name: "bar", srcs: ["a.java"], @@ -2406,7 +2392,6 @@ func TestUsesLibraries(t *testing.T) { android_app { name: "app", srcs: ["a.java"], - libs: ["qux", "quuz.stubs"], uses_libs: ["foo"], sdk_version: "current", optional_uses_libs: [ @@ -2437,15 +2422,6 @@ func TestUsesLibraries(t *testing.T) { app := ctx.ModuleForTests("app", "android_common") prebuilt := ctx.ModuleForTests("prebuilt", "android_common") - // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. - manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] - if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { - t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) - } - if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { - t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) - } - // Test that all libraries are verified cmd := app.Rule("verify_uses_libraries").RuleParams.Command if w := "--uses-library foo"; !strings.Contains(cmd, w) { diff --git a/java/java.go b/java/java.go index 00b11f77a..da9bd3dfe 100644 --- a/java/java.go +++ b/java/java.go @@ -355,17 +355,7 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { } // Functionality common to Module and Import -// -// It is embedded in Module so its functionality can be used by methods in Module -// but it is currently only initialized by Import and Library. type embeddableInModuleAndImport struct { - - // Functionality related to this being used as a component of a java_sdk_library. - EmbeddableSdkLibraryComponent -} - -func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) { - e.initSdkLibraryComponent(moduleBase) } // Module/Import's DepIsInSameApex(...) delegates to this method. @@ -506,6 +496,11 @@ type Dependency interface { JacocoReportClassesFile() android.Path } +type SdkLibraryDependency interface { + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths + SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths +} + type xref interface { XrefJavaFiles() android.Paths } @@ -935,12 +930,6 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } } - // If this is a component library (stubs, etc.) for a java_sdk_library then - // add the name of that java_sdk_library to the exported sdk libs to make sure - // that, if necessary, a element for that java_sdk_library is - // added to the Android manifest. - j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) - ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -960,7 +949,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported - j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...) + j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -2001,8 +1990,6 @@ func LibraryFactory() android.Module { &module.Module.protoProperties, &module.libraryProperties) - module.initModuleAndImport(&module.ModuleBase) - android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -2464,12 +2451,6 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.combinedClasspathFile = outputFile - // If this is a component library (impl, stubs, etc.) for a java_sdk_library then - // add the name of that java_sdk_library to the exported sdk libs to make sure - // that, if necessary, a element for that java_sdk_library is - // added to the Android manifest. - j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) - ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2586,8 +2567,6 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) - module.initModuleAndImport(&module.ModuleBase) - android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) diff --git a/java/java_test.go b/java/java_test.go index 4c085cf0f..4f3a803ff 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,7 +19,6 @@ import ( "os" "path/filepath" "reflect" - "sort" "strconv" "strings" "testing" @@ -1154,25 +1153,13 @@ func TestJavaSdkLibrary(t *testing.T) { java_library { name: "baz", srcs: ["c.java"], - libs: ["foo", "bar.stubs"], + libs: ["foo", "bar"], sdk_version: "system_current", } - java_sdk_library_import { - name: "quuz", - public: { - jars: ["c.jar"], - }, - } - java_sdk_library_import { - name: "fred", - public: { - jars: ["b.jar"], - }, - } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz", "fred", "quuz.stubs"], + libs: ["baz"], sdk_version: "system_current", } java_library { @@ -1237,9 +1224,8 @@ func TestJavaSdkLibrary(t *testing.T) { qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { sdkLibs := quxLib.ExportedSdkLibs() - sort.Strings(sdkLibs) - if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { - t.Errorf("qux should export %q but exports %q", w, sdkLibs) + if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { + t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) } } } diff --git a/java/sdk_library.go b/java/sdk_library.go index 0334f80d3..5efb4d045 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -543,18 +543,12 @@ type commonToSdkLibraryAndImport struct { namingScheme sdkLibraryComponentNamingScheme commonProperties commonToSdkLibraryAndImportProperties - - // Functionality related to this being used as a component of a java_sdk_library. - EmbeddableSdkLibraryComponent } func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase moduleBase.AddProperties(&c.commonProperties) - - // Initialize this as an sdk library component. - c.initSdkLibraryComponent(moduleBase) } func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { @@ -569,9 +563,6 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return false } - // Use the name specified in the module definition as the owner. - c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) - return true } @@ -737,84 +728,6 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android. return paths.stubsHeaderPath } -func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { - componentProps := &struct { - SdkLibraryToImplicitlyTrack *string - }{ - // Mark the stubs library as being components of this java_sdk_library so that - // any app that includes code which depends (directly or indirectly) on the stubs - // library will have the appropriate invocation inserted into its - // manifest if necessary. - SdkLibraryToImplicitlyTrack: proptools.StringPtr(c.moduleBase.BaseModuleName()), - } - - return componentProps -} - -// Properties related to the use of a module as an component of a java_sdk_library. -type SdkLibraryComponentProperties struct { - - // The name of the java_sdk_library/_import to add to a entry - // in the AndroidManifest.xml of any Android app that includes code that references - // this module. If not set then no java_sdk_library/_import is tracked. - SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` -} - -// Structure to be embedded in a module struct that needs to support the -// SdkLibraryComponentDependency interface. -type EmbeddableSdkLibraryComponent struct { - sdkLibraryComponentProperties SdkLibraryComponentProperties -} - -func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) { - moduleBase.AddProperties(&e.sdkLibraryComponentProperties) -} - -// to satisfy SdkLibraryComponentDependency -func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string { - if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil { - return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack} - } - return nil -} - -// Implemented by modules that are (or possibly could be) a component of a java_sdk_library -// (including the java_sdk_library) itself. -type SdkLibraryComponentDependency interface { - // The optional name of the sdk library that should be implicitly added to the - // AndroidManifest of an app that contains code which references the sdk library. - // - // Returns an array containing 0 or 1 items rather than a *string to make it easier - // to append this to the list of exported sdk libraries. - OptionalImplicitSdkLibrary() []string -} - -// Make sure that all the module types that are components of java_sdk_library/_import -// and which can be referenced (directly or indirectly) from an android app implement -// the SdkLibraryComponentDependency interface. -var _ SdkLibraryComponentDependency = (*Library)(nil) -var _ SdkLibraryComponentDependency = (*Import)(nil) -var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) -var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil) - -// Provides access to sdk_version related header and implentation jars. -type SdkLibraryDependency interface { - SdkLibraryComponentDependency - - // Get the header jars appropriate for the supplied sdk_version. - // - // These are turbine generated jars so they only change if the externals of the - // class changes but it does not contain and implementation or JavaDoc. - SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths - - // Get the implementation jars appropriate for the supplied sdk version. - // - // These are either the implementation jar for the whole sdk library or the implementation - // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise - // they are identical to the corresponding header jars. - SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths -} - type SdkLibrary struct { Library @@ -1065,7 +978,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Dist.Tag = proptools.StringPtr(".jar") } - mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) + mctx.CreateModule(LibraryFactory, &props) } // Creates a droidstubs module that creates stubs source files from the given full source @@ -1408,8 +1321,6 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { &module.protoProperties, ) - module.initSdkLibraryComponent(&module.ModuleBase) - module.properties.Installable = proptools.BoolPtr(true) module.deviceProperties.IsSDKLibrary = true } @@ -1658,8 +1569,7 @@ func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl // The imports are preferred if the java_sdk_library_import is preferred. props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) - - mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) + mctx.CreateModule(ImportFactory, &props) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { -- cgit v1.2.3-59-g8ed1b From 64e61997569dde18f70abac001942ee677bccab0 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 15 May 2020 10:20:31 +0100 Subject: Retry: "Improve tracking of exported sdk libraries" The build tracks the java_sdk_library/_import modules that are referenced by libraries so that it can ensure that any Android app that includes code that depends on one of those modules has the appropriate entry in their manifest. Unfortunately, there were a couple of issues with that: 1) It only tracks direct references to the java_sdk_library module itself, e.g. android.test.mock. Direct references to the stubs module, e.g. android.test.mock.stubs were not tracked. Making it possible for Android apps to reference libraries which would not be available at runtime. 2) The logic for determining whether something was a java_sdk_library was repeated in a number of places making it difficult to allow java_sdk_library/_import instances to determine whether they should be treated as an Android shared library. 3) It tracks (and could use) even those java_sdk_library instances which do not represent a shared library, e.g. the ones that set api_only: true. While this change will simplifty fixing that the actual issue will be fixed in a follow up change. Changes: * Added EmbeddableSdkLibraryComponent and embedded it into java_sdk_library/_import, java_library and java_import. It provides the common code to minimize duplication. It contains an SdkLibraryToImplicitlyTrack field that if set will cause any references to the containing module to add the SdkLibraryParent to the list of implicit sdk libraries being tracked. * Changed code that assumed that anything that implemented SdkLibraryDependency required tracking to use the OptionalImplicitSdkLibrary() method to get the optional name of the sdk library to track. That will allow a follow up change to return nil from that method to exclude an sdk library from being tracked. * Moved SdkLibraryDependency from java.go to sdk_library.go as that is a better place for it to be. * Changed the stubs java_library/java_import creation code to initialize the SdkLibraryToImplicitlyTrack field with the name of the creating module. * Initialized the SdkLibraryToImplicitlyTrack field in the java_sdk_library/_import so that direct references to them will be tracked too. * Added tests to verify that direct access to the .stubs child of both java_sdk_library and java_sdk_library_import are tracked properly. Test: atest CtsProviderTestCases - which relies on android.test.mock being implicitly tracked to verify that I had not broken anything. Used aapt2 dump badging to read the manifest. m nothing - to run the new tests which failed before fixing the code. Bug: 156723295 (cherry picked from commit 859fe961b015259368e9994969b569eb34f54ddc) Change-Id: I760a9ac72856e3a07a497ce40db70c7e70106837 --- java/aar.go | 7 ++-- java/app_test.go | 24 ++++++++++++++ java/java.go | 33 +++++++++++++++---- java/java_test.go | 22 ++++++++++--- java/sdk_library.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 166 insertions(+), 14 deletions(-) (limited to 'java/java.go') diff --git a/java/aar.go b/java/aar.go index 0e103f248..c8daf835b 100644 --- a/java/aar.go +++ b/java/aar.go @@ -379,8 +379,11 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati sharedLibs = append(sharedLibs, exportPackage) } - if _, ok := module.(SdkLibraryDependency); ok { - sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module)) + // If the module is (or possibly could be) a component of a java_sdk_library + // (including the java_sdk_library) itself then append any implicit sdk library + // names to the list of sdk libraries to be added to the manifest. + if component, ok := module.(SdkLibraryComponentDependency); ok { + sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...) } case frameworkResTag: diff --git a/java/app_test.go b/java/app_test.go index c731a1713..12b935ed3 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -2382,6 +2382,20 @@ func TestUsesLibraries(t *testing.T) { sdk_version: "current", } + java_sdk_library { + name: "qux", + srcs: ["a.java"], + api_packages: ["qux"], + sdk_version: "current", + } + + java_sdk_library { + name: "quuz", + srcs: ["a.java"], + api_packages: ["quuz"], + sdk_version: "current", + } + java_sdk_library { name: "bar", srcs: ["a.java"], @@ -2392,6 +2406,7 @@ func TestUsesLibraries(t *testing.T) { android_app { name: "app", srcs: ["a.java"], + libs: ["qux", "quuz.stubs"], uses_libs: ["foo"], sdk_version: "current", optional_uses_libs: [ @@ -2422,6 +2437,15 @@ func TestUsesLibraries(t *testing.T) { app := ctx.ModuleForTests("app", "android_common") prebuilt := ctx.ModuleForTests("prebuilt", "android_common") + // Test that implicit dependencies on java_sdk_library instances are passed to the manifest. + manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"] + if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) { + t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs) + } + // Test that all libraries are verified cmd := app.Rule("verify_uses_libraries").RuleParams.Command if w := "--uses-library foo"; !strings.Contains(cmd, w) { diff --git a/java/java.go b/java/java.go index da9bd3dfe..00b11f77a 100644 --- a/java/java.go +++ b/java/java.go @@ -355,7 +355,17 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { } // Functionality common to Module and Import +// +// It is embedded in Module so its functionality can be used by methods in Module +// but it is currently only initialized by Import and Library. type embeddableInModuleAndImport struct { + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent +} + +func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) { + e.initSdkLibraryComponent(moduleBase) } // Module/Import's DepIsInSameApex(...) delegates to this method. @@ -496,11 +506,6 @@ type Dependency interface { JacocoReportClassesFile() android.Path } -type SdkLibraryDependency interface { - SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths - SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths -} - type xref interface { XrefJavaFiles() android.Paths } @@ -930,6 +935,12 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } } + // If this is a component library (stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -949,7 +960,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...) // names of sdk libs that are directly depended are exported - j.exportedSdkLibs = append(j.exportedSdkLibs, otherName) + j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -1990,6 +2001,8 @@ func LibraryFactory() android.Module { &module.Module.protoProperties, &module.libraryProperties) + module.initModuleAndImport(&module.ModuleBase) + android.InitApexModule(module) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -2451,6 +2464,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.combinedClasspathFile = outputFile + // If this is a component library (impl, stubs, etc.) for a java_sdk_library then + // add the name of that java_sdk_library to the exported sdk libs to make sure + // that, if necessary, a element for that java_sdk_library is + // added to the Android manifest. + j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...) + ctx.VisitDirectDeps(func(module android.Module) { otherName := ctx.OtherModuleName(module) tag := ctx.OtherModuleDependencyTag(module) @@ -2567,6 +2586,8 @@ func ImportFactory() android.Module { module.AddProperties(&module.properties) + module.initModuleAndImport(&module.ModuleBase) + android.InitPrebuiltModule(module, &module.properties.Jars) android.InitApexModule(module) android.InitSdkAwareModule(module) diff --git a/java/java_test.go b/java/java_test.go index 4f3a803ff..4c085cf0f 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "reflect" + "sort" "strconv" "strings" "testing" @@ -1153,13 +1154,25 @@ func TestJavaSdkLibrary(t *testing.T) { java_library { name: "baz", srcs: ["c.java"], - libs: ["foo", "bar"], + libs: ["foo", "bar.stubs"], sdk_version: "system_current", } + java_sdk_library_import { + name: "quuz", + public: { + jars: ["c.jar"], + }, + } + java_sdk_library_import { + name: "fred", + public: { + jars: ["b.jar"], + }, + } java_library { name: "qux", srcs: ["c.java"], - libs: ["baz"], + libs: ["baz", "fred", "quuz.stubs"], sdk_version: "system_current", } java_library { @@ -1224,8 +1237,9 @@ func TestJavaSdkLibrary(t *testing.T) { qux := ctx.ModuleForTests("qux", "android_common") if quxLib, ok := qux.Module().(*Library); ok { sdkLibs := quxLib.ExportedSdkLibs() - if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) { - t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs) + sort.Strings(sdkLibs) + if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) { + t.Errorf("qux should export %q but exports %q", w, sdkLibs) } } } diff --git a/java/sdk_library.go b/java/sdk_library.go index b215a76f7..de30635b4 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -543,12 +543,18 @@ type commonToSdkLibraryAndImport struct { namingScheme sdkLibraryComponentNamingScheme commonProperties commonToSdkLibraryAndImportProperties + + // Functionality related to this being used as a component of a java_sdk_library. + EmbeddableSdkLibraryComponent } func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) { c.moduleBase = moduleBase moduleBase.AddProperties(&c.commonProperties) + + // Initialize this as an sdk library component. + c.initSdkLibraryComponent(moduleBase) } func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool { @@ -563,6 +569,9 @@ func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android return false } + // Use the name specified in the module definition as the owner. + c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName()) + return true } @@ -728,6 +737,84 @@ func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android. return paths.stubsHeaderPath } +func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} { + componentProps := &struct { + SdkLibraryToImplicitlyTrack *string + }{ + // Mark the stubs library as being components of this java_sdk_library so that + // any app that includes code which depends (directly or indirectly) on the stubs + // library will have the appropriate invocation inserted into its + // manifest if necessary. + SdkLibraryToImplicitlyTrack: proptools.StringPtr(c.moduleBase.BaseModuleName()), + } + + return componentProps +} + +// Properties related to the use of a module as an component of a java_sdk_library. +type SdkLibraryComponentProperties struct { + + // The name of the java_sdk_library/_import to add to a entry + // in the AndroidManifest.xml of any Android app that includes code that references + // this module. If not set then no java_sdk_library/_import is tracked. + SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"` +} + +// Structure to be embedded in a module struct that needs to support the +// SdkLibraryComponentDependency interface. +type EmbeddableSdkLibraryComponent struct { + sdkLibraryComponentProperties SdkLibraryComponentProperties +} + +func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) { + moduleBase.AddProperties(&e.sdkLibraryComponentProperties) +} + +// to satisfy SdkLibraryComponentDependency +func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string { + if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil { + return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack} + } + return nil +} + +// Implemented by modules that are (or possibly could be) a component of a java_sdk_library +// (including the java_sdk_library) itself. +type SdkLibraryComponentDependency interface { + // The optional name of the sdk library that should be implicitly added to the + // AndroidManifest of an app that contains code which references the sdk library. + // + // Returns an array containing 0 or 1 items rather than a *string to make it easier + // to append this to the list of exported sdk libraries. + OptionalImplicitSdkLibrary() []string +} + +// Make sure that all the module types that are components of java_sdk_library/_import +// and which can be referenced (directly or indirectly) from an android app implement +// the SdkLibraryComponentDependency interface. +var _ SdkLibraryComponentDependency = (*Library)(nil) +var _ SdkLibraryComponentDependency = (*Import)(nil) +var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil) +var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil) + +// Provides access to sdk_version related header and implentation jars. +type SdkLibraryDependency interface { + SdkLibraryComponentDependency + + // Get the header jars appropriate for the supplied sdk_version. + // + // These are turbine generated jars so they only change if the externals of the + // class changes but it does not contain and implementation or JavaDoc. + SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths + + // Get the implementation jars appropriate for the supplied sdk version. + // + // These are either the implementation jar for the whole sdk library or the implementation + // jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise + // they are identical to the corresponding header jars. + SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths +} + type SdkLibrary struct { Library @@ -981,7 +1068,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext props.Dist.Tag = proptools.StringPtr(".jar") } - mctx.CreateModule(LibraryFactory, &props) + mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } // Creates a droidstubs module that creates stubs source files from the given full source @@ -1326,6 +1413,8 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { &module.protoProperties, ) + module.initSdkLibraryComponent(&module.ModuleBase) + module.properties.Installable = proptools.BoolPtr(true) module.deviceProperties.IsSDKLibrary = true } @@ -1574,7 +1663,8 @@ func (module *sdkLibraryImport) createJavaImportForStubs(mctx android.Defaultabl // The imports are preferred if the java_sdk_library_import is preferred. props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer()) - mctx.CreateModule(ImportFactory, &props) + + mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary()) } func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) { -- cgit v1.2.3-59-g8ed1b From ac103461a47e86665ec78df6e5d9792d7464a57b Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Tue, 19 May 2020 12:06:48 +0100 Subject: Improve the structure of the link check method Match by name first, then by kind. Bug: 157010342 Test: m Change-Id: Ic337a073c3bd14ac03b1d899aeb612247a708495 --- java/java.go | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index da9bd3dfe..726d4869b 100644 --- a/java/java.go +++ b/java/java.go @@ -827,41 +827,42 @@ type linkTypeContext interface { } func (m *Module) getLinkType(name string) (ret linkType, stubs bool) { - ver := m.sdkVersion() - switch { - case name == "core.current.stubs" || name == "core.platform.api.stubs" || - name == "stub-annotations" || name == "private-stub-annotations-jar" || - name == "core-lambda-stubs" || name == "core-generated-annotation-stubs": + switch name { + case "core.current.stubs", "core.platform.api.stubs", "stub-annotations", + "private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs": return javaCore, true - case ver.kind == sdkCore: - return javaCore, false - case name == "android_system_stubs_current": + case "android_stubs_current": + return javaSdk, true + case "android_system_stubs_current": return javaSystem, true - case ver.kind == sdkSystem: - return javaSystem, false - case name == "android_test_stubs_current": + case "android_module_lib_stubs_current": + return javaModule, true + case "android_system_server_stubs_current": + return javaSystemServer, true + case "android_test_stubs_current": return javaSystem, true - case ver.kind == sdkTest: - return javaPlatform, false - case name == "android_stubs_current": - return javaSdk, true - case ver.kind == sdkPublic: + } + + ver := m.sdkVersion() + switch ver.kind { + case sdkCore: + return javaCore, false + case sdkSystem: + return javaSystem, false + case sdkPublic: return javaSdk, false - case name == "android_module_lib_stubs_current": - return javaModule, true - case ver.kind == sdkModule: + case sdkModule: return javaModule, false - case name == "android_system_server_stubs_current": - return javaSystemServer, true - case ver.kind == sdkSystemServer: + case sdkSystemServer: return javaSystemServer, false - case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform: + case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest: return javaPlatform, false - case !ver.valid(): + } + + if !ver.valid() { panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw)) - default: - return javaSdk, false } + return javaSdk, false } func checkLinkType(ctx android.ModuleContext, from *Module, to linkTypeContext, tag dependencyTag) { -- cgit v1.2.3-59-g8ed1b From 0bd88d0b4e782df6aa99475307a4cfab6d617d14 Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Mon, 25 May 2020 12:20:51 +0100 Subject: Correct link type for module stubs Module stubs compile against module_current, so any module depending on them had to compile against module_current (or broader) too. Treat them as the API surface the stubs are for. Bug: 157010342 Test: m Change-Id: I49b9082dc1b5afe6c22e94126e574dd8061f0f39 --- java/java.go | 4 ++++ java/sdk_library.go | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 726d4869b..0c5ef5db8 100644 --- a/java/java.go +++ b/java/java.go @@ -843,6 +843,10 @@ func (m *Module) getLinkType(name string) (ret linkType, stubs bool) { return javaSystem, true } + if stub, linkType := moduleStubLinkType(name); stub { + return linkType, true + } + ver := m.sdkVersion() switch ver.kind { case sdkCore: diff --git a/java/sdk_library.go b/java/sdk_library.go index 61bb106d8..94f38f558 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1224,6 +1224,24 @@ func (s *frameworkModulesNamingScheme) apiModuleName(scope *apiScope, baseName s var _ sdkLibraryComponentNamingScheme = (*frameworkModulesNamingScheme)(nil) +func moduleStubLinkType(name string) (stub bool, ret linkType) { + // This suffix-based approach is fragile and could potentially mis-trigger. + // TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly. + if strings.HasSuffix(name, ".stubs.public") || strings.HasSuffix(name, "-stubs-publicapi") { + return true, javaSdk + } + if strings.HasSuffix(name, ".stubs.system") || strings.HasSuffix(name, "-stubs-systemapi") { + return true, javaSystem + } + if strings.HasSuffix(name, ".stubs.module_lib") || strings.HasSuffix(name, "-stubs-module_libs_api") { + return true, javaModule + } + if strings.HasSuffix(name, ".stubs.test") { + return true, javaSystem + } + return false, javaPlatform +} + // java_sdk_library is a special Java library that provides optional platform APIs to apps. // In practice, it can be viewed as a combination of several modules: 1) stubs library that clients // are linked against to, 2) droiddoc module that internally generates API stubs source files, -- cgit v1.2.3-59-g8ed1b From ed50ca8dd8806e957a42751ebac83ebe57805ab8 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Thu, 28 May 2020 23:46:55 +0900 Subject: apex respects stem of java_library modules apex now respects stem of java_library modules. As a follow-up we need to suppor the same for other types of modules. Exempt-From-Owner-Approval: cherry-pick from AOSP Bug: 157638999 Test: m Merged-In: Iaf5023020b5440f1ffd4f5414b5a7864655fc22a (cherry picked from commit a62aa2399031a01620775a06dbae53af0cff5a25) Change-Id: Iaf5023020b5440f1ffd4f5414b5a7864655fc22a --- apex/apex.go | 19 +++++++++++++++++-- apex/apex_test.go | 3 ++- java/java.go | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index 6ae6cd959..ba1c1d27e 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1179,6 +1179,7 @@ func (class apexFileClass) NameInMake() string { // apexFile represents a file in an APEX bundle type apexFile struct { builtFile android.Path + stem string moduleName string installDir string class apexFileClass @@ -1218,9 +1219,17 @@ func (af *apexFile) Ok() bool { return af.builtFile != nil && af.builtFile.String() != "" } +func (af *apexFile) apexRelativePath(path string) string { + return filepath.Join(af.installDir, path) +} + // Path() returns path of this apex file relative to the APEX root func (af *apexFile) Path() string { - return filepath.Join(af.installDir, af.builtFile.Base()) + stem := af.builtFile.Base() + if af.stem != "" { + stem = af.stem + } + return af.apexRelativePath(stem) } // SymlinkPaths() returns paths of the symlinks (if any) relative to the APEX root @@ -1660,11 +1669,17 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) ap return af } -func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib java.Dependency, module android.Module) apexFile { +type javaDependency interface { + java.Dependency + Stem() string +} + +func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile { dirInApex := "javalib" fileToCopy := lib.DexJar() af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = lib.JacocoReportClassesFile() + af.stem = lib.Stem() + ".jar" return af } diff --git a/apex/apex_test.go b/apex/apex_test.go index a2d7a9713..89f8c8993 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -386,6 +386,7 @@ func TestBasicApex(t *testing.T) { java_library { name: "myjar", srcs: ["foo/bar/MyClass.java"], + stem: "myjar_stem", sdk_version: "none", system_modules: "none", static_libs: ["myotherjar"], @@ -440,7 +441,7 @@ func TestBasicApex(t *testing.T) { // Ensure that both direct and indirect deps are copied into apex ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") - ensureContains(t, copyCmds, "image.apex/javalib/myjar.jar") + ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar") // .. but not for java libs ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar") ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar") diff --git a/java/java.go b/java/java.go index 81f98c0d5..c30dc4e50 100644 --- a/java/java.go +++ b/java/java.go @@ -1880,7 +1880,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { extraInstallDeps = j.InstallMixin(ctx, j.outputFile) } j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), - ctx.ModuleName()+".jar", j.outputFile, extraInstallDeps...) + j.Stem()+".jar", j.outputFile, extraInstallDeps...) } // Verify Dist.Tag is set to a supported output @@ -2721,7 +2721,7 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.maybeStrippedDexJarFile = dexOutputFile ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), - ctx.ModuleName()+".jar", dexOutputFile) + j.Stem()+".jar", dexOutputFile) } func (j *DexImport) DexJar() android.Path { -- cgit v1.2.3-59-g8ed1b From a105cf99d0efb05f186cf07b1e34cb3f79694664 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Fri, 29 May 2020 11:24:51 +0100 Subject: Collect permitted packages from java_sdk_library instances Switching an updatable boot jar from java_library to java_sdk_library changed the contents of the updatable-bcp-packages.txt due to the code requiring the module to be *Library. This change updates that to allow it to be any module that implements the PermittedPackagesForUpdatableBootJars interface which is *Library and anything that embeds that like *SdkLibrary. Bug: 155164730 Test: m droid and check the contents of system/etc/updatable-bcp-packages.txt Change-Id: I464af74628da311734f102f77ec8158daec5b32d --- java/dexpreopt_bootjars.go | 4 ++-- java/java.go | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'java/java.go') diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index b518e9c0d..2f0cbdb8c 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -611,10 +611,10 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf // Collect `permitted_packages` for updatable boot jars. var updatablePackages []string ctx.VisitAllModules(func(module android.Module) { - if j, ok := module.(*Library); ok { + if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok { name := ctx.ModuleName(module) if i := android.IndexList(name, updatableModules); i != -1 { - pp := j.properties.Permitted_packages + pp := j.PermittedPackagesForUpdatableBootJars() if len(pp) > 0 { updatablePackages = append(updatablePackages, pp...) } else { diff --git a/java/java.go b/java/java.go index c30dc4e50..e01d10999 100644 --- a/java/java.go +++ b/java/java.go @@ -1839,6 +1839,17 @@ type Library struct { InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths) } +// Provides access to the list of permitted packages from updatable boot jars. +type PermittedPackagesForUpdatableBootJars interface { + PermittedPackagesForUpdatableBootJars() []string +} + +var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil) + +func (j *Library) PermittedPackagesForUpdatableBootJars() []string { + return j.properties.Permitted_packages +} + func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool { // Store uncompressed (and aligned) any dex files from jars in APEXes. if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() { -- cgit v1.2.3-59-g8ed1b From c05da0a90e29184df74c50a49a7905277a56aa3e Mon Sep 17 00:00:00 2001 From: Kousik Kumar Date: Wed, 20 May 2020 11:27:16 -0700 Subject: Add support for remote-execution / caching of jar/zip actions Test: Ran a build with `RBE_JAR="true" RBE_JAR_EXEC_STRATEGY="remote" RBE_ZIP="true" RBE_ZIP_EXEC_STRATEGY="remote" ... use_rbe m` and that succeeded. Bug: b/156765207 Change-Id: Ia17b532fbb282be414adf879914870082dd0841b Merged-In: Ia17b532fbb282be414adf879914870082dd0841b --- java/app_builder.go | 14 +++++++++---- java/builder.go | 51 +++++++++++++++++++++++++++++++++------------ java/config/config.go | 2 ++ java/dex.go | 54 ++++++++++++++++++++++++++++++++---------------- java/java.go | 14 +++++++++---- remoteexec/remoteexec.go | 16 ++++++++++++++ 6 files changed, 112 insertions(+), 39 deletions(-) (limited to 'java/java.go') diff --git a/java/app_builder.go b/java/app_builder.go index acc02f261..97ec269ee 100644 --- a/java/app_builder.go +++ b/java/app_builder.go @@ -237,14 +237,20 @@ func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.Writabl "-f", j.path.String()) } + rule := zip + args := map[string]string{ + "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), + } + if ctx.Config().IsEnvTrue("RBE_ZIP") { + rule = zipRE + args["implicits"] = strings.Join(deps.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: zip, + Rule: rule, Description: "zip jni libs", Output: outputFile, Implicits: deps, - Args: map[string]string{ - "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "), - }, + Args: args, }) } diff --git a/java/builder.go b/java/builder.go index b6cb2aeeb..a27e5c390 100644 --- a/java/builder.go +++ b/java/builder.go @@ -40,17 +40,17 @@ var ( // (if the rule produces .class files) or a .srcjar file (if the rule produces .java files). // .srcjar files are unzipped into a temporary directory when compiled with javac. // TODO(b/143658984): goma can't handle the --system argument to javac. - javac, javacRE = remoteexec.StaticRules(pctx, "javac", + javac, javacRE = remoteexec.MultiCommandStaticRules(pctx, "javac", blueprint.RuleParams{ Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + `(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` + - `${config.SoongJavacWrapper} $reTemplate${config.JavacCmd} ` + + `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` + `${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` + `$processorpath $processor $javacFlags $bootClasspath $classpath ` + `-source $javaVersion -target $javaVersion ` + `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` + - `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` + + `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ "${config.JavacCmd}", @@ -60,10 +60,19 @@ var ( CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, Rspfile: "$out.rsp", RspfileContent: "$in", - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"}, - ExecStrategy: "${config.REJavacExecStrategy}", - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$javaTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"}, + ExecStrategy: "${config.REJavacExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$out"}, + ExecStrategy: "${config.REJavacExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", "outDir", "annoDir", "javaVersion"}, nil) @@ -144,23 +153,35 @@ var ( Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"}) - jar = pctx.AndroidStaticRule("jar", + jar, jarRE = remoteexec.StaticRules(pctx, "jar", blueprint.RuleParams{ - Command: `${config.SoongZipCmd} -jar -o $out @$out.rsp`, + Command: `$reTemplate${config.SoongZipCmd} -jar -o $out @$out.rsp`, CommandDeps: []string{"${config.SoongZipCmd}"}, Rspfile: "$out.rsp", RspfileContent: "$jarArgs", }, - "jarArgs") + &remoteexec.REParams{ + ExecStrategy: "${config.REJarExecStrategy}", + Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"jarArgs"}, nil) - zip = pctx.AndroidStaticRule("zip", + zip, zipRE = remoteexec.StaticRules(pctx, "zip", blueprint.RuleParams{ Command: `${config.SoongZipCmd} -o $out @$out.rsp`, CommandDeps: []string{"${config.SoongZipCmd}"}, Rspfile: "$out.rsp", RspfileContent: "$jarArgs", }, - "jarArgs") + &remoteexec.REParams{ + ExecStrategy: "${config.REZipExecStrategy}", + Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp", "$implicits"}, + RSPFile: "${out}.rsp", + OutputFiles: []string{"$out"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, []string{"jarArgs"}, []string{"implicits"}) combineJar = pctx.AndroidStaticRule("combineJar", blueprint.RuleParams{ @@ -457,8 +478,12 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath, jarArgs []string, deps android.Paths) { + rule := jar + if ctx.Config().IsEnvTrue("RBE_JAR") { + rule = jarRE + } ctx.Build(pctx, android.BuildParams{ - Rule: jar, + Rule: rule, Description: "jar", Output: outputFile, Implicits: deps, diff --git a/java/config/config.go b/java/config/config.go index d2550b1c1..337355d80 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -152,6 +152,8 @@ func init() { pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) + pctx.VariableFunc("REZipExecStrategy", remoteexec.EnvOverrideFunc("RBE_ZIP_EXEC_STRATEGY", remoteexec.LocalExecStrategy)) pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar") diff --git a/java/dex.go b/java/dex.go index e2a8e7eae..9e61e95ad 100644 --- a/java/dex.go +++ b/java/dex.go @@ -24,48 +24,66 @@ import ( "android/soong/remoteexec" ) -var d8, d8RE = remoteexec.StaticRules(pctx, "d8", +var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `$reTemplate${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` + - `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + + `$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` + + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.D8Cmd}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "compiler": "d8"}, - Inputs: []string{"${config.D8Jar}"}, - ExecStrategy: "${config.RED8ExecStrategy}", - ToolchainInputs: []string{"${config.JavaCmd}"}, - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$d8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "d8"}, + Inputs: []string{"${config.D8Jar}"}, + ExecStrategy: "${config.RED8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RED8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"outDir", "d8Flags", "zipFlags"}, nil) -var r8, r8RE = remoteexec.StaticRules(pctx, "r8", +var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + `rm -f "$outDict" && ` + - `$reTemplate${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` + + `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` + `--force-proguard-compatibility ` + `--no-data-resources ` + `-printmapping $outDict ` + `$r8Flags && ` + `touch "$outDict" && ` + - `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`, CommandDeps: []string{ "${config.R8Cmd}", "${config.SoongZipCmd}", "${config.MergeZipsCmd}", }, - }, &remoteexec.REParams{ - Labels: map[string]string{"type": "compile", "compiler": "r8"}, - Inputs: []string{"$implicits", "${config.R8Jar}"}, - ExecStrategy: "${config.RER8ExecStrategy}", - ToolchainInputs: []string{"${config.JavaCmd}"}, - Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, map[string]*remoteexec.REParams{ + "$r8Template": &remoteexec.REParams{ + Labels: map[string]string{"type": "compile", "compiler": "r8"}, + Inputs: []string{"$implicits", "${config.R8Jar}"}, + ExecStrategy: "${config.RER8ExecStrategy}", + ToolchainInputs: []string{"${config.JavaCmd}"}, + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, + "$zipTemplate": &remoteexec.REParams{ + Labels: map[string]string{"type": "tool", "name": "soong_zip"}, + Inputs: []string{"${config.SoongZipCmd}", "$outDir"}, + OutputFiles: []string{"$outDir/classes.dex.jar"}, + ExecStrategy: "${config.RER8ExecStrategy}", + Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, + }, }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"}) func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string { diff --git a/java/java.go b/java/java.go index e01d10999..2623d2c10 100644 --- a/java/java.go +++ b/java/java.go @@ -1462,13 +1462,19 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { serviceFile := file.String() zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile) } + rule := zip + args := map[string]string{ + "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "), + } + if ctx.Config().IsEnvTrue("RBE_ZIP") { + rule = zipRE + args["implicits"] = strings.Join(services.Strings(), ",") + } ctx.Build(pctx, android.BuildParams{ - Rule: zip, + Rule: rule, Output: servicesJar, Implicits: services, - Args: map[string]string{ - "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "), - }, + Args: args, }) jars = append(jars, servicesJar) } diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go index 578af4edb..c7d518eec 100644 --- a/remoteexec/remoteexec.go +++ b/remoteexec/remoteexec.go @@ -164,6 +164,22 @@ func StaticRules(ctx android.PackageContext, name string, ruleParams blueprint.R ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...) } +// MultiCommandStaticRules returns a pair of rules based on the given RuleParams, where the first +// rule is a locally executable rule and the second rule is a remotely executable rule. This +// function supports multiple remote execution wrappers placed in the template when commands are +// chained together with &&. commonArgs are args used for both the local and remotely executable +// rules. reArgs are args used only for remote execution. +func MultiCommandStaticRules(ctx android.PackageContext, name string, ruleParams blueprint.RuleParams, reParams map[string]*REParams, commonArgs []string, reArgs []string) (blueprint.Rule, blueprint.Rule) { + ruleParamsRE := ruleParams + for k, v := range reParams { + ruleParams.Command = strings.ReplaceAll(ruleParams.Command, k, "") + ruleParamsRE.Command = strings.ReplaceAll(ruleParamsRE.Command, k, v.Template()) + } + + return ctx.AndroidStaticRule(name, ruleParams, commonArgs...), + ctx.AndroidRemoteStaticRule(name+"RE", android.RemoteRuleSupports{RBE: true}, ruleParamsRE, append(commonArgs, reArgs...)...) +} + // EnvOverrideFunc retrieves a variable func that evaluates to the value of the given environment // variable if set, otherwise the given default. func EnvOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string { -- cgit v1.2.3-59-g8ed1b From aa7359ab0c97cc198699607cc17f4df6b3977997 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Tue, 2 Jun 2020 09:52:17 +0100 Subject: Always run package check Previously, the package check was only run when building checkbuild or the phony target created for a specific module. It would not run when building a module that depended upon a library with the permitted_packages property. That was because the package check was only run when the package-check.stamp file was built and that was only added to the phony and checkbuild targets. Instead of touching a separate package-check.stamp file to indicate that the check has been performed this change copies the input jar file to the package check to a separate ../package-check/ file which is then treated as the output of the library and is the input for any dex processing. So, any modules that depend on this library will transitively depend on the output file produced by the package check command and so will ensure that the package check is always run. Test: Removed "android.net" from the permitted_packages for "framework-tethering", build "framework-tethering" which triggered and failed the package check and "com.android.tethering" which did not. Made this change. Built "com.android.tethering" which triggered and then failed the package check. Removed change to "framework-tethering" Bug: 157649935 Merged-In: Ib01aa09e13f80282218049270eb7a58ec5f9f605 Change-Id: Ib01aa09e13f80282218049270eb7a58ec5f9f605 (cherry picked from commit 91206d9ed1a1e3cb81d1ace021580c4be8362f1f) --- java/androidmk.go | 25 +------------------------ java/builder.go | 9 ++++++--- java/java.go | 11 ++++------- 3 files changed, 11 insertions(+), 34 deletions(-) (limited to 'java/java.go') diff --git a/java/androidmk.go b/java/androidmk.go index 75fb5fb02..85eaff4a6 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -69,26 +69,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) { hideFromMake = true } - if hideFromMake { - // May still need to add some additional dependencies. This will be called - // once for the platform variant (even if it is not being used) and once each - // for the APEX specific variants. In order to avoid adding the dependency - // multiple times only add it for the platform variant. - checkedModulePaths := library.additionalCheckedModules - if library.IsForPlatform() && len(checkedModulePaths) != 0 { - mainEntries = android.AndroidMkEntries{ - Class: "FAKE", - // Need at least one output file in order for this to take effect. - OutputFile: android.OptionalPathForPath(checkedModulePaths[0]), - Include: "$(BUILD_PHONY_PACKAGE)", - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(entries *android.AndroidMkEntries) { - entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...) - }, - }, - } - } - } else { + if !hideFromMake { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", DistFile: android.OptionalPathForPath(library.distFile), @@ -123,10 +104,6 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...) - if len(library.additionalCheckedModules) != 0 { - entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...) - } - if library.proguardDictionary != nil { entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary) } diff --git a/java/builder.go b/java/builder.go index a27e5c390..640dba93b 100644 --- a/java/builder.go +++ b/java/builder.go @@ -206,7 +206,7 @@ var ( blueprint.RuleParams{ Command: "rm -f $out && " + "${config.PackageCheckCmd} $in $packages && " + - "touch $out", + "cp $in $out", CommandDeps: []string{"${config.PackageCheckCmd}"}, }, "packages") @@ -547,8 +547,9 @@ func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, }) } -func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath, - classesJar android.Path, permittedPackages []string) { +func CheckJarPackages(ctx android.ModuleContext, classesJar android.Path, permittedPackages []string) android.ModuleOutPath { + outputFile := android.PathForModuleOut(ctx, "package-check", classesJar.Base()) + ctx.Build(pctx, android.BuildParams{ Rule: packageCheck, Description: "packageCheck", @@ -558,6 +559,8 @@ func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath "packages": strings.Join(permittedPackages, " "), }, }) + + return outputFile } func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePath, diff --git a/java/java.go b/java/java.go index 2623d2c10..1a5e86f3d 100644 --- a/java/java.go +++ b/java/java.go @@ -467,9 +467,6 @@ type Module struct { // expanded Jarjar_rules expandJarjarRules android.Path - // list of additional targets for checkbuild - additionalCheckedModules android.Paths - // Extra files generated by the module type to be added as java resources. extraResources android.Paths @@ -1527,10 +1524,10 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Check package restrictions if necessary. if len(j.properties.Permitted_packages) > 0 { - // Check packages and copy to package-checked file. - pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp") - CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages) - j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile) + // Check packages and copy input to package-checked file. + // Use the file copied after a successful package check as the output file for this + // module so that any dependencies on this module will trigger the package check. + outputFile = CheckJarPackages(ctx, outputFile, j.properties.Permitted_packages) if ctx.Failed() { return -- cgit v1.2.3-59-g8ed1b From 8383972ec0a4c2cc5129c4b92cfb8dbe79766987 Mon Sep 17 00:00:00 2001 From: Tej Singh Date: Wed, 3 Jun 2020 18:45:54 +0000 Subject: Revert "Always run package check" This reverts commit aa7359ab0c97cc198699607cc17f4df6b3977997. Reason for revert: package-check.sh doesn't work on mac Change-Id: Ia3dcee612c1f6b4121e1351c8710638ae41bc88a Merged-In: I50af71d54d5f1f8b516bfcf1efbcf6217e89c83a --- java/androidmk.go | 25 ++++++++++++++++++++++++- java/builder.go | 9 +++------ java/java.go | 11 +++++++---- 3 files changed, 34 insertions(+), 11 deletions(-) (limited to 'java/java.go') diff --git a/java/androidmk.go b/java/androidmk.go index 85eaff4a6..75fb5fb02 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -69,7 +69,26 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) { hideFromMake = true } - if !hideFromMake { + if hideFromMake { + // May still need to add some additional dependencies. This will be called + // once for the platform variant (even if it is not being used) and once each + // for the APEX specific variants. In order to avoid adding the dependency + // multiple times only add it for the platform variant. + checkedModulePaths := library.additionalCheckedModules + if library.IsForPlatform() && len(checkedModulePaths) != 0 { + mainEntries = android.AndroidMkEntries{ + Class: "FAKE", + // Need at least one output file in order for this to take effect. + OutputFile: android.OptionalPathForPath(checkedModulePaths[0]), + Include: "$(BUILD_PHONY_PACKAGE)", + ExtraEntries: []android.AndroidMkExtraEntriesFunc{ + func(entries *android.AndroidMkEntries) { + entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...) + }, + }, + } + } + } else { mainEntries = android.AndroidMkEntries{ Class: "JAVA_LIBRARIES", DistFile: android.OptionalPathForPath(library.distFile), @@ -104,6 +123,10 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...) + if len(library.additionalCheckedModules) != 0 { + entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...) + } + if library.proguardDictionary != nil { entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary) } diff --git a/java/builder.go b/java/builder.go index 640dba93b..a27e5c390 100644 --- a/java/builder.go +++ b/java/builder.go @@ -206,7 +206,7 @@ var ( blueprint.RuleParams{ Command: "rm -f $out && " + "${config.PackageCheckCmd} $in $packages && " + - "cp $in $out", + "touch $out", CommandDeps: []string{"${config.PackageCheckCmd}"}, }, "packages") @@ -547,9 +547,8 @@ func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath, }) } -func CheckJarPackages(ctx android.ModuleContext, classesJar android.Path, permittedPackages []string) android.ModuleOutPath { - outputFile := android.PathForModuleOut(ctx, "package-check", classesJar.Base()) - +func CheckJarPackages(ctx android.ModuleContext, outputFile android.WritablePath, + classesJar android.Path, permittedPackages []string) { ctx.Build(pctx, android.BuildParams{ Rule: packageCheck, Description: "packageCheck", @@ -559,8 +558,6 @@ func CheckJarPackages(ctx android.ModuleContext, classesJar android.Path, permit "packages": strings.Join(permittedPackages, " "), }, }) - - return outputFile } func TransformJetifier(ctx android.ModuleContext, outputFile android.WritablePath, diff --git a/java/java.go b/java/java.go index 1a5e86f3d..2623d2c10 100644 --- a/java/java.go +++ b/java/java.go @@ -467,6 +467,9 @@ type Module struct { // expanded Jarjar_rules expandJarjarRules android.Path + // list of additional targets for checkbuild + additionalCheckedModules android.Paths + // Extra files generated by the module type to be added as java resources. extraResources android.Paths @@ -1524,10 +1527,10 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Check package restrictions if necessary. if len(j.properties.Permitted_packages) > 0 { - // Check packages and copy input to package-checked file. - // Use the file copied after a successful package check as the output file for this - // module so that any dependencies on this module will trigger the package check. - outputFile = CheckJarPackages(ctx, outputFile, j.properties.Permitted_packages) + // Check packages and copy to package-checked file. + pkgckFile := android.PathForModuleOut(ctx, "package-check.stamp") + CheckJarPackages(ctx, pkgckFile, outputFile, j.properties.Permitted_packages) + j.additionalCheckedModules = append(j.additionalCheckedModules, pkgckFile) if ctx.Failed() { return -- cgit v1.2.3-59-g8ed1b From 2cd081cf06c552a562aabae25b7cc17f8242d22f Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 1 Jun 2020 21:39:15 +0900 Subject: dex_import can be added to apex Bug:157886942 Test: m Change-Id: Ida6f7bb784efe74cc1fa0e8d370eaee803f08b0f Merged-In: Ida6f7bb784efe74cc1fa0e8d370eaee803f08b0f --- apex/apex.go | 18 ++++++------------ apex/apex_test.go | 16 +++++++++++++++- java/java.go | 4 ++++ 3 files changed, 25 insertions(+), 13 deletions(-) (limited to 'java/java.go') diff --git a/apex/apex.go b/apex/apex.go index ba1c1d27e..b44199082 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1670,7 +1670,8 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) ap } type javaDependency interface { - java.Dependency + DexJar() android.Path + JacocoReportClassesFile() android.Path Stem() string } @@ -1954,23 +1955,16 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("binaries", "%q is neither cc_binary, (embedded) py_binary, (host) blueprint_go_binary, (host) bootstrap_go_binary, nor sh_binary", depName) } case javaLibTag: - if javaLib, ok := child.(*java.Library); ok { - af := apexFileForJavaLibrary(ctx, javaLib, javaLib) - if !af.Ok() { - ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) - } else { - filesInfo = append(filesInfo, af) - return true // track transitive dependencies - } - } else if sdkLib, ok := child.(*java.SdkLibrary); ok { - af := apexFileForJavaLibrary(ctx, sdkLib, sdkLib) + switch child.(type) { + case *java.Library, *java.SdkLibrary, *java.DexImport: + af := apexFileForJavaLibrary(ctx, child.(javaDependency), child.(android.Module)) if !af.Ok() { ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) return false } filesInfo = append(filesInfo, af) return true // track transitive dependencies - } else { + default: ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child)) } case androidAppTag: diff --git a/apex/apex_test.go b/apex/apex_test.go index 89f8c8993..42f9a94b3 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -289,7 +289,10 @@ func TestBasicApex(t *testing.T) { binaries: ["foo",], } }, - java_libs: ["myjar"], + java_libs: [ + "myjar", + "myjar_dex", + ], } apex { @@ -398,6 +401,15 @@ func TestBasicApex(t *testing.T) { ], } + dex_import { + name: "myjar_dex", + jars: ["prebuilt.jar"], + apex_available: [ + "//apex_available:platform", + "myapex", + ], + } + java_library { name: "myotherjar", srcs: ["foo/bar/MyClass.java"], @@ -433,6 +445,7 @@ func TestBasicApex(t *testing.T) { // Ensure that apex variant is created for the direct dep ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex") ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex") + ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_myapex") // Ensure that apex variant is created for the indirect dep ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex") @@ -442,6 +455,7 @@ func TestBasicApex(t *testing.T) { ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so") ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar") + ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar") // .. but not for java libs ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar") ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar") diff --git a/java/java.go b/java/java.go index 2623d2c10..f2f47b7d0 100644 --- a/java/java.go +++ b/java/java.go @@ -2684,6 +2684,10 @@ func (j *DexImport) Stem() string { return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name()) } +func (a *DexImport) JacocoReportClassesFile() android.Path { + return nil +} + func (j *DexImport) IsInstallable() bool { return true } -- cgit v1.2.3-59-g8ed1b From afd3d11a795b9f331637d3587a94142f20e8c55d Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Mon, 8 Jun 2020 19:24:09 +0900 Subject: dex_import that isn't available for platform isn't installed This change fixes a bug that dex_import module is always installed to the platform even when the module is not available to the platform. Bug: 158284983 Test: OUT_DIR=/tmp/ndk build/soong/scripts/build-ndk-prebuilts.sh Change-Id: I85570506e700be59ee63e4f1d7902a40e36df39c --- java/java.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index f2f47b7d0..b0865040e 100644 --- a/java/java.go +++ b/java/java.go @@ -2741,8 +2741,10 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.maybeStrippedDexJarFile = dexOutputFile - ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), - j.Stem()+".jar", dexOutputFile) + if j.IsForPlatform() { + ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), + j.Stem()+".jar", dexOutputFile) + } } func (j *DexImport) DexJar() android.Path { -- cgit v1.2.3-59-g8ed1b From 9855207d0e8b496327255c6bc3a4d36d8449775e Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 4 Jun 2020 13:25:17 -0700 Subject: Define Soong phony rules in Make To support dist-for-goals in Soong, we need to define all phony rules in Make so that dist-for-goals can insert additional dependencies on them. Collect all the phony rules in phonySingleton and write them out as Make rules when Soong is embedded in Make, or as blueprint.Phony rules when Soong is run standalone. Bug: 153485543 Test: m checkbuild Change-Id: I68201eff30744b0f487fc4f11f033767b53a627d Merged-In: I68201eff30744b0f487fc4f11f033767b53a627d (cherry picked from commit c3d87d31129405975f9a889e3c1c96cdcbe275a4) --- android/Android.bp | 1 + android/makevars.go | 66 +++++++++++++++++++++++++++++++++-------- android/module.go | 84 ++++++++++++++++++++-------------------------------- android/phony.go | 75 ++++++++++++++++++++++++++++++++++++++++++++++ android/register.go | 3 ++ android/singleton.go | 10 +++++++ android/writedocs.go | 6 +--- cc/cc.go | 7 +---- java/java.go | 6 +--- 9 files changed, 178 insertions(+), 80 deletions(-) create mode 100644 android/phony.go (limited to 'java/java.go') diff --git a/android/Android.bp b/android/Android.bp index 654110647..d904a86c7 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -34,6 +34,7 @@ bootstrap_go_package { "package_ctx.go", "path_properties.go", "paths.go", + "phony.go", "prebuilt.go", "proto.go", "register.go", diff --git a/android/makevars.go b/android/makevars.go index aba4ccec3..0acd0f665 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -17,12 +17,11 @@ package android import ( "bytes" "fmt" - "io/ioutil" - "os" "strconv" "strings" "github.com/google/blueprint" + "github.com/google/blueprint/pathtools" "github.com/google/blueprint/proptools" ) @@ -84,6 +83,11 @@ type MakeVarsContext interface { // builder whenever a file matching the pattern as added or removed, without rerunning if a // file that does not match the pattern is added to a searched directory. GlobWithDeps(pattern string, excludes []string) ([]string, error) + + // Phony creates a phony rule in Make, which will allow additional DistForGoal + // dependencies to be added to it. Phony can be called on the same name multiple + // times to add additional dependencies. + Phony(names string, deps ...Path) } var _ PathContext = MakeVarsContext(nil) @@ -130,9 +134,10 @@ var makeVarsProviders []makeVarsProvider type makeVarsContext struct { SingletonContext - config Config - pctx PackageContext - vars []makeVarsVariable + config Config + pctx PackageContext + vars []makeVarsVariable + phonies []phony } var _ MakeVarsContext = &makeVarsContext{} @@ -144,6 +149,11 @@ type makeVarsVariable struct { strict bool } +type phony struct { + name string + deps []string +} + func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { if !ctx.Config().EmbeddedInMake() { return @@ -152,11 +162,15 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { outFile := absolutePath(PathForOutput(ctx, "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()) + lateOutFile := absolutePath(PathForOutput(ctx, + "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String()) + if ctx.Failed() { return } vars := []makeVarsVariable{} + var phonies []phony for _, provider := range makeVarsProviders { mctx := &makeVarsContext{ SingletonContext: ctx, @@ -166,6 +180,7 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { provider.call(mctx) vars = append(vars, mctx.vars...) + phonies = append(phonies, mctx.phonies...) } if ctx.Failed() { @@ -174,17 +189,16 @@ func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) { outBytes := s.writeVars(vars) - if _, err := os.Stat(absolutePath(outFile)); err == nil { - if data, err := ioutil.ReadFile(absolutePath(outFile)); err == nil { - if bytes.Equal(data, outBytes) { - return - } - } + if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil { + ctx.Errorf(err.Error()) } - if err := ioutil.WriteFile(absolutePath(outFile), outBytes, 0666); err != nil { + lateOutBytes := s.writeLate(phonies) + + if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil { ctx.Errorf(err.Error()) } + } func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte { @@ -263,6 +277,26 @@ my_check_failed := fmt.Fprintln(buf, "\nsoong-compare-var :=") + fmt.Fprintln(buf) + + return buf.Bytes() +} + +func (s *makeVarsSingleton) writeLate(phonies []phony) []byte { + buf := &bytes.Buffer{} + + fmt.Fprint(buf, `# Autogenerated file + +# Values written by Soong read after parsing all Android.mk files. + + +`) + + for _, phony := range phonies { + fmt.Fprintf(buf, ".PHONY: %s\n", phony.name) + fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n ")) + } + return buf.Bytes() } @@ -299,6 +333,10 @@ func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool) c.addVariableRaw(name, value, strict, sort) } +func (c *makeVarsContext) addPhony(name string, deps []string) { + c.phonies = append(c.phonies, phony{name, deps}) +} + func (c *makeVarsContext) Strict(name, ninjaStr string) { c.addVariable(name, ninjaStr, true, false) } @@ -318,3 +356,7 @@ func (c *makeVarsContext) CheckSorted(name, ninjaStr string) { func (c *makeVarsContext) CheckRaw(name, value string) { c.addVariableRaw(name, value, false, false) } + +func (c *makeVarsContext) Phony(name string, deps ...Path) { + c.addPhony(name, Paths(deps).Strings()) +} diff --git a/android/module.go b/android/module.go index baf348aaf..0bf48d597 100644 --- a/android/module.go +++ b/android/module.go @@ -194,6 +194,10 @@ type ModuleContext interface { // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string, // and performs more verification. Build(pctx PackageContext, params BuildParams) + // Phony creates a Make-style phony rule, a rule with no commands that can depend on other + // phony rules or real files. Phony can be called on the same name multiple times to add + // additional dependencies. + Phony(phony string, deps ...Path) PrimaryModule() Module FinalModule() Module @@ -706,6 +710,7 @@ type ModuleBase struct { installFiles Paths checkbuildFiles Paths noticeFile OptionalPath + phonies map[string]Paths // Used by buildTargetSingleton to create checkbuild and per-directory build targets // Only set on the final variant of each module @@ -1075,26 +1080,17 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) { } if len(allInstalledFiles) > 0 { - name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-install") - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: name, - Implicits: allInstalledFiles, - Default: !ctx.Config().EmbeddedInMake(), - }) - deps = append(deps, name) - m.installTarget = name + name := namespacePrefix + ctx.ModuleName() + "-install" + ctx.Phony(name, allInstalledFiles...) + m.installTarget = PathForPhony(ctx, name) + deps = append(deps, m.installTarget) } if len(allCheckbuildFiles) > 0 { - name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+"-checkbuild") - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: name, - Implicits: allCheckbuildFiles, - }) - deps = append(deps, name) - m.checkbuildTarget = name + name := namespacePrefix + ctx.ModuleName() + "-checkbuild" + ctx.Phony(name, allCheckbuildFiles...) + m.checkbuildTarget = PathForPhony(ctx, name) + deps = append(deps, m.checkbuildTarget) } if len(deps) > 0 { @@ -1103,12 +1099,7 @@ func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) { suffix = "-soong" } - name := PathForPhony(ctx, namespacePrefix+ctx.ModuleName()+suffix) - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Outputs: []WritablePath{name}, - Implicits: deps, - }) + ctx.Phony(namespacePrefix+ctx.ModuleName()+suffix, deps...) m.blueprintDir = ctx.ModuleDir() } @@ -1282,6 +1273,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...) m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc) m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments) + for k, v := range ctx.phonies { + m.phonies[k] = append(m.phonies[k], v...) + } } else if ctx.Config().AllowMissingDependencies() { // If the module is not enabled it will not create any build rules, nothing will call // ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled @@ -1419,6 +1413,7 @@ type moduleContext struct { installFiles Paths checkbuildFiles Paths module Module + phonies map[string]Paths // For tests buildParams []BuildParams @@ -1533,6 +1528,11 @@ func (m *moduleContext) Build(pctx PackageContext, params BuildParams) { m.bp.Build(pctx.PackageContext, convertBuildParams(params)) } + +func (m *moduleContext) Phony(name string, deps ...Path) { + addPhony(m.config, name, deps...) +} + func (m *moduleContext) GetMissingDependencies() []string { var missingDeps []string missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...) @@ -2167,9 +2167,8 @@ type buildTargetSingleton struct{} func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { var checkbuildDeps Paths - mmTarget := func(dir string) WritablePath { - return PathForPhony(ctx, - "MODULES-IN-"+strings.Replace(filepath.Clean(dir), "/", "-", -1)) + mmTarget := func(dir string) string { + return "MODULES-IN-" + strings.Replace(filepath.Clean(dir), "/", "-", -1) } modulesInDir := make(map[string]Paths) @@ -2195,11 +2194,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { } // Create a top-level checkbuild target that depends on all modules - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: PathForPhony(ctx, "checkbuild"+suffix), - Implicits: checkbuildDeps, - }) + ctx.Phony("checkbuild"+suffix, checkbuildDeps...) // Make will generate the MODULES-IN-* targets if ctx.Config().EmbeddedInMake() { @@ -2223,7 +2218,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { for _, dir := range dirs { p := parentDir(dir) if p != "." && p != "/" { - modulesInDir[p] = append(modulesInDir[p], mmTarget(dir)) + modulesInDir[p] = append(modulesInDir[p], PathForPhony(ctx, mmTarget(dir))) } } @@ -2231,14 +2226,7 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { // depends on the MODULES-IN-* targets of all of its subdirectories that contain Android.bp // files. for _, dir := range dirs { - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: mmTarget(dir), - Implicits: modulesInDir[dir], - // HACK: checkbuild should be an optional build, but force it - // enabled for now in standalone builds - Default: !ctx.Config().EmbeddedInMake(), - }) + ctx.Phony(mmTarget(dir), modulesInDir[dir]...) } // Create (host|host-cross|target)- phony rules to build a reduced checkbuild. @@ -2265,23 +2253,15 @@ func (c *buildTargetSingleton) GenerateBuildActions(ctx SingletonContext) { continue } - name := PathForPhony(ctx, className+"-"+os.Name) - osClass[className] = append(osClass[className], name) + name := className + "-" + os.Name + osClass[className] = append(osClass[className], PathForPhony(ctx, name)) - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: name, - Implicits: deps, - }) + ctx.Phony(name, deps...) } // Wrap those into host|host-cross|target phony rules for _, class := range SortedStringKeys(osClass) { - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: PathForPhony(ctx, class), - Implicits: osClass[class], - }) + ctx.Phony(class, osClass[class]...) } } diff --git a/android/phony.go b/android/phony.go new file mode 100644 index 000000000..f8e5a4401 --- /dev/null +++ b/android/phony.go @@ -0,0 +1,75 @@ +// Copyright 2020 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package android + +import ( + "sync" + + "github.com/google/blueprint" +) + +var phonyMapOnceKey = NewOnceKey("phony") + +type phonyMap map[string]Paths + +var phonyMapLock sync.Mutex + +func getPhonyMap(config Config) phonyMap { + return config.Once(phonyMapOnceKey, func() interface{} { + return make(phonyMap) + }).(phonyMap) +} + +func addPhony(config Config, name string, deps ...Path) { + phonyMap := getPhonyMap(config) + phonyMapLock.Lock() + defer phonyMapLock.Unlock() + phonyMap[name] = append(phonyMap[name], deps...) +} + +type phonySingleton struct { + phonyMap phonyMap + phonyList []string +} + +var _ SingletonMakeVarsProvider = (*phonySingleton)(nil) + +func (p *phonySingleton) GenerateBuildActions(ctx SingletonContext) { + p.phonyMap = getPhonyMap(ctx.Config()) + p.phonyList = SortedStringKeys(p.phonyMap) + for _, phony := range p.phonyList { + p.phonyMap[phony] = SortedUniquePaths(p.phonyMap[phony]) + } + + if !ctx.Config().EmbeddedInMake() { + for _, phony := range p.phonyList { + ctx.Build(pctx, BuildParams{ + Rule: blueprint.Phony, + Outputs: []WritablePath{PathForPhony(ctx, phony)}, + Implicits: p.phonyMap[phony], + }) + } + } +} + +func (p phonySingleton) MakeVars(ctx MakeVarsContext) { + for _, phony := range p.phonyList { + ctx.Phony(phony, p.phonyMap[phony]...) + } +} + +func phonySingletonFactory() Singleton { + return &phonySingleton{} +} diff --git a/android/register.go b/android/register.go index ccfe01e74..036a8113f 100644 --- a/android/register.go +++ b/android/register.go @@ -104,6 +104,9 @@ func (ctx *Context) Register() { registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps) + // Register phony just before makevars so it can write out its phony rules as Make rules + ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory)) + // Register makevars after other singletons so they can export values through makevars ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(makeVarsSingletonFunc)) diff --git a/android/singleton.go b/android/singleton.go index 568398cdd..2c51c6c48 100644 --- a/android/singleton.go +++ b/android/singleton.go @@ -36,6 +36,12 @@ type SingletonContext interface { Variable(pctx PackageContext, name, value string) Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule Build(pctx PackageContext, params BuildParams) + + // Phony creates a Make-style phony rule, a rule with no commands that can depend on other + // phony rules or real files. Phony can be called on the same name multiple times to add + // additional dependencies. + Phony(name string, deps ...Path) + RequireNinjaVersion(major, minor, micro int) // SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable @@ -156,6 +162,10 @@ func (s *singletonContextAdaptor) Build(pctx PackageContext, params BuildParams) } +func (s *singletonContextAdaptor) Phony(name string, deps ...Path) { + addPhony(s.Config(), name, deps...) +} + func (s *singletonContextAdaptor) SetNinjaBuildDir(pctx PackageContext, value string) { s.SingletonContext.SetNinjaBuildDir(pctx.PackageContext, value) } diff --git a/android/writedocs.go b/android/writedocs.go index 7262ad810..9e43e80a6 100644 --- a/android/writedocs.go +++ b/android/writedocs.go @@ -69,9 +69,5 @@ func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) { }) // Add a phony target for building the documentation - ctx.Build(pctx, BuildParams{ - Rule: blueprint.Phony, - Output: PathForPhony(ctx, "soong_docs"), - Input: docsFile, - }) + ctx.Phony("soong_docs", docsFile) } diff --git a/cc/cc.go b/cc/cc.go index 3d3a841ff..0f874f13c 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -3188,12 +3188,7 @@ func (ks *kytheExtractAllSingleton) GenerateBuildActions(ctx android.SingletonCo }) // TODO(asmundak): Perhaps emit a rule to output a warning if there were no xrefTargets if len(xrefTargets) > 0 { - ctx.Build(pctx, android.BuildParams{ - Rule: blueprint.Phony, - Output: android.PathForPhony(ctx, "xref_cxx"), - Inputs: xrefTargets, - //Default: true, - }) + ctx.Phony("xref_cxx", xrefTargets...) } } diff --git a/java/java.go b/java/java.go index b0865040e..f563a3878 100644 --- a/java/java.go +++ b/java/java.go @@ -2852,11 +2852,7 @@ func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonC }) // TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets if len(xrefTargets) > 0 { - ctx.Build(pctx, android.BuildParams{ - Rule: blueprint.Phony, - Output: android.PathForPhony(ctx, "xref_java"), - Inputs: xrefTargets, - }) + ctx.Phony("xref_java", xrefTargets...) } } -- cgit v1.2.3-59-g8ed1b From 1c14b4ecf632f0b90b66b086df03f8eb4c6a33b0 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Mon, 15 Jun 2020 16:09:53 -0700 Subject: Consolidate adding common java properties Use a method to add the properties that are present on all java modules. Bug: 153485543 Test: m checkbuild Change-Id: I7803b15eb0de810c8ab8d4b9acf2511935a26fb6 Merged-In: I7803b15eb0de810c8ab8d4b9acf2511935a26fb6 (cherry picked from commit ce6734e666086814df721b681158dc90f7bcf6dd) --- java/aar.go | 5 +---- java/app.go | 15 +++---------- java/java.go | 63 ++++++++++++++++++++++++----------------------------- java/plugin.go | 6 ++--- java/robolectric.go | 3 +-- java/sdk_library.go | 9 ++------ 6 files changed, 37 insertions(+), 64 deletions(-) (limited to 'java/java.go') diff --git a/java/aar.go b/java/aar.go index c8daf835b..66a1c53bf 100644 --- a/java/aar.go +++ b/java/aar.go @@ -506,11 +506,8 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) func AndroidLibraryFactory() android.Module { module := &AndroidLibrary{} + module.Module.addHostAndDeviceProperties() module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, &module.aaptProperties, &module.androidLibraryProperties) diff --git a/java/app.go b/java/app.go index 6eeaf348c..6aaae0786 100755 --- a/java/app.go +++ b/java/app.go @@ -970,11 +970,8 @@ func AndroidAppFactory() android.Module { module.Module.properties.Instrument = true module.Module.properties.Installable = proptools.BoolPtr(true) + module.addHostAndDeviceProperties() module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, &module.aaptProperties, &module.appProperties, &module.overridableAppProperties, @@ -1093,11 +1090,8 @@ func AndroidTestFactory() android.Module { module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true + module.addHostAndDeviceProperties() module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, &module.aaptProperties, &module.appProperties, &module.appTestProperties, @@ -1145,11 +1139,8 @@ func AndroidTestHelperAppFactory() android.Module { module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true + module.addHostAndDeviceProperties() module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, &module.aaptProperties, &module.appProperties, &module.appTestHelperAppProperties, diff --git a/java/java.go b/java/java.go index f563a3878..c80eef97f 100644 --- a/java/java.go +++ b/java/java.go @@ -482,6 +482,21 @@ type Module struct { distFile android.Path } +func (j *Module) addHostProperties() { + j.AddProperties( + &j.properties, + &j.protoProperties, + ) +} + +func (j *Module) addHostAndDeviceProperties() { + j.addHostProperties() + j.AddProperties( + &j.deviceProperties, + &j.dexpreoptProperties, + ) +} + func (j *Module) OutputFiles(tag string) (android.Paths, error) { switch tag { case "": @@ -2024,12 +2039,8 @@ var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{ func LibraryFactory() android.Module { module := &Library{} - module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, - &module.libraryProperties) + module.addHostAndDeviceProperties() + module.AddProperties(&module.libraryProperties) module.initModuleAndImport(&module.ModuleBase) @@ -2051,9 +2062,7 @@ func LibraryStaticFactory() android.Module { func LibraryHostFactory() android.Module { module := &Library{} - module.AddProperties( - &module.Module.properties, - &module.Module.protoProperties) + module.addHostProperties() module.Module.properties.Installable = proptools.BoolPtr(true) @@ -2221,12 +2230,8 @@ func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, func TestFactory() android.Module { module := &Test{} - module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, - &module.testProperties) + module.addHostAndDeviceProperties() + module.AddProperties(&module.testProperties) module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true @@ -2239,12 +2244,8 @@ func TestFactory() android.Module { func TestHelperLibraryFactory() android.Module { module := &TestHelperLibrary{} - module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, - &module.testHelperLibraryProperties) + module.addHostAndDeviceProperties() + module.AddProperties(&module.testHelperLibraryProperties) module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true @@ -2285,10 +2286,8 @@ func JavaTestImportFactory() android.Module { func TestHostFactory() android.Module { module := &Test{} - module.AddProperties( - &module.Module.properties, - &module.Module.protoProperties, - &module.testProperties) + module.addHostProperties() + module.AddProperties(&module.testProperties) module.Module.properties.Installable = proptools.BoolPtr(true) @@ -2372,12 +2371,8 @@ func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { func BinaryFactory() android.Module { module := &Binary{} - module.AddProperties( - &module.Module.properties, - &module.Module.deviceProperties, - &module.Module.dexpreoptProperties, - &module.Module.protoProperties, - &module.binaryProperties) + module.addHostAndDeviceProperties() + module.AddProperties(&module.binaryProperties) module.Module.properties.Installable = proptools.BoolPtr(true) @@ -2393,10 +2388,8 @@ func BinaryFactory() android.Module { func BinaryHostFactory() android.Module { module := &Binary{} - module.AddProperties( - &module.Module.properties, - &module.Module.protoProperties, - &module.binaryProperties) + module.addHostProperties() + module.AddProperties(&module.binaryProperties) module.Module.properties.Installable = proptools.BoolPtr(true) diff --git a/java/plugin.go b/java/plugin.go index a5e8292e7..947c28626 100644 --- a/java/plugin.go +++ b/java/plugin.go @@ -24,10 +24,8 @@ func init() { func PluginFactory() android.Module { module := &Plugin{} - module.AddProperties( - &module.Module.properties, - &module.Module.protoProperties, - &module.pluginProperties) + module.addHostProperties() + module.AddProperties(&module.pluginProperties) InitJavaModule(module, android.HostSupported) return module diff --git a/java/robolectric.go b/java/robolectric.go index 3195615ff..64bd32570 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -215,10 +215,9 @@ func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, test func RobolectricTestFactory() android.Module { module := &robolectricTest{} + module.addHostProperties() module.AddProperties( - &module.Module.properties, &module.Module.deviceProperties, - &module.Module.protoProperties, &module.robolectricProperties) module.Module.dexpreopter.isTest = true diff --git a/java/sdk_library.go b/java/sdk_library.go index c97a04a5b..a6549ea5f 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1553,13 +1553,8 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont } func (module *SdkLibrary) InitSdkLibraryProperties() { - module.AddProperties( - &module.sdkLibraryProperties, - &module.properties, - &module.dexpreoptProperties, - &module.deviceProperties, - &module.protoProperties, - ) + module.addHostAndDeviceProperties() + module.AddProperties(&module.sdkLibraryProperties) module.initSdkLibraryComponent(&module.ModuleBase) -- cgit v1.2.3-59-g8ed1b From 1e28e3c61593571db5ecea328d134ee50501104d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 2 Jun 2020 20:09:13 -0700 Subject: Add support for running Android lint on java and android modules. Add a rule that runs Android lint on each java and android module and produces reports in xml, html and text formats. Bug: 153485543 Test: m out/soong/.intermediates/packages/apps/Settings/Settings-core/android_common/lint-report.html Change-Id: I5a530975b73ba767fef45b257d4f9ec901a19fcb Merged-In: I5a530975b73ba767fef45b257d4f9ec901a19fcb (cherry picked from commit 014489c1e6cbd2801970b88d5b608dc5c45b403c) --- java/Android.bp | 1 + java/aar.go | 7 + java/app.go | 6 + java/droiddoc.go | 15 ++ java/java.go | 27 ++++ java/lint.go | 355 ++++++++++++++++++++++++++++++++++++++++++++ java/lint_defaults.txt | 78 ++++++++++ java/robolectric.go | 1 + java/sdk_library.go | 1 + scripts/Android.bp | 6 + scripts/lint-project-xml.py | 213 ++++++++++++++++++++++++++ 11 files changed, 710 insertions(+) create mode 100644 java/lint.go create mode 100644 java/lint_defaults.txt create mode 100755 scripts/lint-project-xml.py (limited to 'java/java.go') diff --git a/java/Android.bp b/java/Android.bp index 2de1b8ea1..1fda7f71d 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -37,6 +37,7 @@ bootstrap_go_package { "jdeps.go", "java_resources.go", "kotlin.go", + "lint.go", "platform_compat_config.go", "plugin.go", "prebuilt_apis.go", diff --git a/java/aar.go b/java/aar.go index 66a1c53bf..53b50d60d 100644 --- a/java/aar.go +++ b/java/aar.go @@ -102,6 +102,7 @@ type aapt struct { sdkLibraries []string hasNoCode bool LoggingParent string + resourceFiles android.Paths splitNames []string splits []split @@ -275,6 +276,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex var compiledResDirs []android.Paths for _, dir := range resDirs { + a.resourceFiles = append(a.resourceFiles, dir.files...) compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()) } @@ -473,6 +475,10 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) // apps manifests are handled by aapt, don't let Module see them a.properties.Manifest = nil + a.linter.mergedManifest = a.aapt.mergedManifestFile + a.linter.manifest = a.aapt.manifestPath + a.linter.resources = a.aapt.resourceFiles + a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile) @@ -512,6 +518,7 @@ func AndroidLibraryFactory() android.Module { &module.androidLibraryProperties) module.androidLibraryProperties.BuildAAR = true + module.Module.linter.library = true android.InitApexModule(module) InitJavaModule(module, android.DeviceSupported) diff --git a/java/app.go b/java/app.go index 6aaae0786..245c586e1 100755 --- a/java/app.go +++ b/java/app.go @@ -737,6 +737,10 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { a.proguardBuildActions(ctx) + a.linter.mergedManifest = a.aapt.mergedManifestFile + a.linter.manifest = a.aapt.manifestPath + a.linter.resources = a.aapt.resourceFiles + dexJarFile := a.dexBuildActions(ctx) jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) @@ -1089,6 +1093,7 @@ func AndroidTestFactory() android.Module { module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true + module.Module.linter.test = true module.addHostAndDeviceProperties() module.AddProperties( @@ -1138,6 +1143,7 @@ func AndroidTestHelperAppFactory() android.Module { module.appProperties.Use_embedded_native_libs = proptools.BoolPtr(true) module.appProperties.AlwaysPackageNativeLibs = true module.Module.dexpreopter.isTest = true + module.Module.linter.test = true module.addHostAndDeviceProperties() module.AddProperties( diff --git a/java/droiddoc.go b/java/droiddoc.go index 8db688fec..39cadebf1 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -1224,6 +1224,21 @@ func DroidstubsHostFactory() android.Module { return module } +func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) { + switch tag { + case "": + return android.Paths{d.stubsSrcJar}, nil + case ".docs.zip": + return android.Paths{d.docZip}, nil + case ".annotations.zip": + return android.Paths{d.annotationsZip}, nil + case ".api_versions.xml": + return android.Paths{d.apiVersionsXml}, nil + default: + return nil, fmt.Errorf("unsupported module reference tag %q", tag) + } +} + func (d *Droidstubs) ApiFilePath() android.Path { return d.apiFilePath } diff --git a/java/java.go b/java/java.go index c80eef97f..0c0c659e9 100644 --- a/java/java.go +++ b/java/java.go @@ -475,6 +475,7 @@ type Module struct { hiddenAPI dexpreopter + linter // list of the xref extraction files kytheFiles android.Paths @@ -494,6 +495,7 @@ func (j *Module) addHostAndDeviceProperties() { j.AddProperties( &j.deviceProperties, &j.dexpreoptProperties, + &j.linter.properties, ) } @@ -1635,6 +1637,28 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { outputFile = implementationAndResourcesJar } + if ctx.Device() { + lintSDKVersionString := func(sdkSpec sdkSpec) string { + if v := sdkSpec.version; v.isNumbered() { + return v.String() + } else { + return ctx.Config().DefaultAppTargetSdk() + } + } + + j.linter.name = ctx.ModuleName() + j.linter.srcs = srcFiles + j.linter.srcJars = srcJars + j.linter.classpath = append(append(android.Paths(nil), flags.bootClasspath...), flags.classpath...) + j.linter.classes = j.implementationJarFile + j.linter.minSdkVersion = lintSDKVersionString(j.minSdkVersion()) + j.linter.targetSdkVersion = lintSDKVersionString(j.targetSdkVersion()) + j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion()) + j.linter.javaLanguageLevel = flags.javaVersion.String() + j.linter.kotlinLanguageLevel = "1.3" + j.linter.lint(ctx) + } + ctx.CheckbuildFile(outputFile) // Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource @@ -2235,6 +2259,7 @@ func TestFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true + module.Module.linter.test = true InitJavaModule(module, android.HostAndDeviceSupported) return module @@ -2249,6 +2274,7 @@ func TestHelperLibraryFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true + module.Module.linter.test = true InitJavaModule(module, android.HostAndDeviceSupported) return module @@ -2823,6 +2849,7 @@ func DefaultsFactory() android.Module { &DexImportProperties{}, &android.ApexProperties{}, &RuntimeResourceOverlayProperties{}, + &LintProperties{}, ) android.InitDefaultsModule(module) diff --git a/java/lint.go b/java/lint.go new file mode 100644 index 000000000..441e110cd --- /dev/null +++ b/java/lint.go @@ -0,0 +1,355 @@ +// Copyright 2020 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 ( + "fmt" + "sort" + + "android/soong/android" +) + +type LintProperties struct { + // Controls for running Android Lint on the module. + Lint struct { + + // If true, run Android Lint on the module. Defaults to true. + Enabled *bool + + // Flags to pass to the Android Lint tool. + Flags []string + + // Checks that should be treated as fatal. + Fatal_checks []string + + // Checks that should be treated as errors. + Error_checks []string + + // Checks that should be treated as warnings. + Warning_checks []string + + // Checks that should be skipped. + Disabled_checks []string + } +} + +type linter struct { + name string + manifest android.Path + mergedManifest android.Path + srcs android.Paths + srcJars android.Paths + resources android.Paths + classpath android.Paths + classes android.Path + extraLintCheckJars android.Paths + test bool + library bool + minSdkVersion string + targetSdkVersion string + compileSdkVersion string + javaLanguageLevel string + kotlinLanguageLevel string + outputs lintOutputs + properties LintProperties +} + +type lintOutputs struct { + html android.ModuleOutPath + text android.ModuleOutPath + xml android.ModuleOutPath +} + +func (l *linter) enabled() bool { + return BoolDefault(l.properties.Lint.Enabled, true) +} + +func (l *linter) writeLintProjectXML(ctx android.ModuleContext, + rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir android.WritablePath, deps android.Paths) { + + var resourcesList android.WritablePath + if len(l.resources) > 0 { + // The list of resources may be too long to put on the command line, but + // we can't use the rsp file because it is already being used for srcs. + // Insert a second rule to write out the list of resources to a file. + resourcesList = android.PathForModuleOut(ctx, "lint", "resources.list") + resListRule := android.NewRuleBuilder() + resListRule.Command().Text("cp").FlagWithRspFileInputList("", l.resources).Output(resourcesList) + resListRule.Build(pctx, ctx, "lint_resources_list", "lint resources list") + deps = append(deps, l.resources...) + } + + projectXMLPath = android.PathForModuleOut(ctx, "lint", "project.xml") + // Lint looks for a lint.xml file next to the project.xml file, give it one. + configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml") + cacheDir = android.PathForModuleOut(ctx, "lint", "cache") + + srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars") + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars) + + cmd := rule.Command(). + BuiltTool(ctx, "lint-project-xml"). + FlagWithOutput("--project_out ", projectXMLPath). + FlagWithOutput("--config_out ", configXMLPath). + FlagWithArg("--name ", ctx.ModuleName()) + + if l.library { + cmd.Flag("--library") + } + if l.test { + cmd.Flag("--test") + } + if l.manifest != nil { + deps = append(deps, l.manifest) + cmd.FlagWithArg("--manifest ", l.manifest.String()) + } + if l.mergedManifest != nil { + deps = append(deps, l.mergedManifest) + cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String()) + } + + // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to + // lint separately. + cmd.FlagWithRspFileInputList("--srcs ", l.srcs) + deps = append(deps, l.srcs...) + + cmd.FlagWithInput("--generated_srcs ", srcJarList) + deps = append(deps, l.srcJars...) + + if resourcesList != nil { + cmd.FlagWithInput("--resources ", resourcesList) + } + + if l.classes != nil { + deps = append(deps, l.classes) + cmd.FlagWithArg("--classes ", l.classes.String()) + } + + cmd.FlagForEachArg("--classpath ", l.classpath.Strings()) + deps = append(deps, l.classpath...) + + cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings()) + deps = append(deps, l.extraLintCheckJars...) + + // The cache tag in project.xml is relative to the project.xml file. + cmd.FlagWithArg("--cache_dir ", "cache") + + cmd.FlagWithInput("@", + android.PathForSource(ctx, "build/soong/java/lint_defaults.txt")) + + cmd.FlagForEachArg("--disable_check ", l.properties.Lint.Disabled_checks) + cmd.FlagForEachArg("--warning_check ", l.properties.Lint.Warning_checks) + cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks) + cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks) + + return projectXMLPath, configXMLPath, cacheDir, deps +} + +// generateManifest adds a command to the rule to write a dummy manifest cat contains the +// minSdkVersion and targetSdkVersion for modules (like java_library) that don't have a manifest. +func (l *linter) generateManifest(ctx android.ModuleContext, rule *android.RuleBuilder) android.Path { + manifestPath := android.PathForModuleOut(ctx, "lint", "AndroidManifest.xml") + + rule.Command().Text("("). + Text(`echo "" &&`). + Text(`echo "" &&`). + Textf(`echo " " &&`, + l.minSdkVersion, l.targetSdkVersion). + Text(`echo ""`). + Text(") >").Output(manifestPath) + + return manifestPath +} + +func (l *linter) lint(ctx android.ModuleContext) { + if !l.enabled() { + return + } + + rule := android.NewRuleBuilder() + + if l.manifest == nil { + manifest := l.generateManifest(ctx, rule) + l.manifest = manifest + } + + projectXML, lintXML, cacheDir, deps := l.writeLintProjectXML(ctx, rule) + + l.outputs.html = android.PathForModuleOut(ctx, "lint-report.html") + l.outputs.text = android.PathForModuleOut(ctx, "lint-report.txt") + l.outputs.xml = android.PathForModuleOut(ctx, "lint-report.xml") + + rule.Command().Text("rm -rf").Flag(cacheDir.String()) + rule.Command().Text("mkdir -p").Flag(cacheDir.String()) + + rule.Command(). + Text("("). + Flag("JAVA_OPTS=-Xmx2048m"). + FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath(ctx)). + FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXmlPath(ctx)). + Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")). + Implicit(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar")). + Flag("--quiet"). + FlagWithInput("--project ", projectXML). + FlagWithInput("--config ", lintXML). + FlagWithOutput("--html ", l.outputs.html). + FlagWithOutput("--text ", l.outputs.text). + FlagWithOutput("--xml ", l.outputs.xml). + FlagWithArg("--compile-sdk-version ", l.compileSdkVersion). + FlagWithArg("--java-language-level ", l.javaLanguageLevel). + FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel). + FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())). + Flag("--exitcode"). + Flags(l.properties.Lint.Flags). + Implicits(deps). + Text("|| (").Text("cat").Input(l.outputs.text).Text("; exit 7)"). + Text(")") + + rule.Command().Text("rm -rf").Flag(cacheDir.String()) + + rule.Build(pctx, ctx, "lint", "lint") +} + +func (l *linter) lintOutputs() *lintOutputs { + return &l.outputs +} + +type lintOutputIntf interface { + lintOutputs() *lintOutputs +} + +var _ lintOutputIntf = (*linter)(nil) + +type lintSingleton struct { + htmlZip android.WritablePath + textZip android.WritablePath + xmlZip android.WritablePath +} + +func (l *lintSingleton) GenerateBuildActions(ctx android.SingletonContext) { + l.generateLintReportZips(ctx) + l.copyLintDependencies(ctx) +} + +func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) { + if ctx.Config().UnbundledBuild() { + return + } + + var frameworkDocStubs android.Module + ctx.VisitAllModules(func(m android.Module) { + if ctx.ModuleName(m) == "framework-doc-stubs" { + if frameworkDocStubs == nil { + frameworkDocStubs = m + } else { + ctx.Errorf("lint: multiple framework-doc-stubs modules found: %s and %s", + ctx.ModuleSubDir(m), ctx.ModuleSubDir(frameworkDocStubs)) + } + } + }) + + if frameworkDocStubs == nil { + if !ctx.Config().AllowMissingDependencies() { + ctx.Errorf("lint: missing framework-doc-stubs") + } + return + } + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"), + Output: annotationsZipPath(ctx), + }) + + ctx.Build(pctx, android.BuildParams{ + Rule: android.Cp, + Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"), + Output: apiVersionsXmlPath(ctx), + }) +} + +func annotationsZipPath(ctx android.PathContext) android.WritablePath { + return android.PathForOutput(ctx, "lint", "annotations.zip") +} + +func apiVersionsXmlPath(ctx android.PathContext) android.WritablePath { + return android.PathForOutput(ctx, "lint", "api_versions.xml") +} + +func (l *lintSingleton) generateLintReportZips(ctx android.SingletonContext) { + var outputs []*lintOutputs + var dirs []string + ctx.VisitAllModules(func(m android.Module) { + if ctx.Config().EmbeddedInMake() && !m.ExportedToMake() { + return + } + + if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() && apex.IsForPlatform() { + // There are stray platform variants of modules in apexes that are not available for + // the platform, and they sometimes can't be built. Don't depend on them. + return + } + + if l, ok := m.(lintOutputIntf); ok { + outputs = append(outputs, l.lintOutputs()) + } + }) + + dirs = android.SortedUniqueStrings(dirs) + + zip := func(outputPath android.WritablePath, get func(*lintOutputs) android.Path) { + var paths android.Paths + + for _, output := range outputs { + paths = append(paths, get(output)) + } + + sort.Slice(paths, func(i, j int) bool { + return paths[i].String() < paths[j].String() + }) + + rule := android.NewRuleBuilder() + + rule.Command().BuiltTool(ctx, "soong_zip"). + FlagWithOutput("-o ", outputPath). + FlagWithArg("-C ", android.PathForIntermediates(ctx).String()). + FlagWithRspFileInputList("-l ", paths) + + rule.Build(pctx, ctx, outputPath.Base(), outputPath.Base()) + } + + l.htmlZip = android.PathForOutput(ctx, "lint-report-html.zip") + zip(l.htmlZip, func(l *lintOutputs) android.Path { return l.html }) + + l.textZip = android.PathForOutput(ctx, "lint-report-text.zip") + zip(l.textZip, func(l *lintOutputs) android.Path { return l.text }) + + l.xmlZip = android.PathForOutput(ctx, "lint-report-xml.zip") + zip(l.xmlZip, func(l *lintOutputs) android.Path { return l.xml }) + + ctx.Phony("lint-check", l.htmlZip, l.textZip, l.xmlZip) +} + +func (l *lintSingleton) MakeVars(ctx android.MakeVarsContext) { + ctx.DistForGoal("lint-check", l.htmlZip, l.textZip, l.xmlZip) +} + +var _ android.SingletonMakeVarsProvider = (*lintSingleton)(nil) + +func init() { + android.RegisterSingletonType("lint", + func() android.Singleton { return &lintSingleton{} }) +} diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt new file mode 100644 index 000000000..0786b7c00 --- /dev/null +++ b/java/lint_defaults.txt @@ -0,0 +1,78 @@ +# Treat LintError as fatal to catch invocation errors +--fatal_check LintError + +# Downgrade existing errors to warnings +--warning_check AppCompatResource # 55 occurences in 10 modules +--warning_check AppLinkUrlError # 111 occurences in 53 modules +--warning_check BlockedPrivateApi # 2 occurences in 2 modules +--warning_check ByteOrderMark # 2 occurences in 2 modules +--warning_check DuplicateActivity # 3 occurences in 3 modules +--warning_check DuplicateDefinition # 3623 occurences in 48 modules +--warning_check DuplicateIds # 207 occurences in 22 modules +--warning_check EllipsizeMaxLines # 12 occurences in 7 modules +--warning_check ExtraTranslation # 21276 occurences in 27 modules +--warning_check FontValidationError # 4 occurences in 1 modules +--warning_check FullBackupContent # 16 occurences in 1 modules +--warning_check GetContentDescriptionOverride # 3 occurences in 2 modules +--warning_check HalfFloat # 31 occurences in 1 modules +--warning_check HardcodedDebugMode # 99 occurences in 95 modules +--warning_check ImpliedQuantity # 703 occurences in 27 modules +--warning_check ImpliedTouchscreenHardware # 4 occurences in 4 modules +--warning_check IncludeLayoutParam # 11 occurences in 6 modules +--warning_check Instantiatable # 145 occurences in 19 modules +--warning_check InvalidPermission # 6 occurences in 4 modules +--warning_check InvalidUsesTagAttribute # 6 occurences in 2 modules +--warning_check InvalidWakeLockTag # 111 occurences in 37 modules +--warning_check JavascriptInterface # 3 occurences in 2 modules +--warning_check LibraryCustomView # 9 occurences in 4 modules +--warning_check LogTagMismatch # 81 occurences in 13 modules +--warning_check LongLogTag # 249 occurences in 12 modules +--warning_check MenuTitle # 5 occurences in 4 modules +--warning_check MissingClass # 537 occurences in 141 modules +--warning_check MissingConstraints # 39 occurences in 10 modules +--warning_check MissingDefaultResource # 1257 occurences in 40 modules +--warning_check MissingIntentFilterForMediaSearch # 1 occurences in 1 modules +--warning_check MissingLeanbackLauncher # 3 occurences in 3 modules +--warning_check MissingLeanbackSupport # 2 occurences in 2 modules +--warning_check MissingOnPlayFromSearch # 1 occurences in 1 modules +--warning_check MissingPermission # 2071 occurences in 150 modules +--warning_check MissingPrefix # 46 occurences in 41 modules +--warning_check MissingQuantity # 100 occurences in 1 modules +--warning_check MissingSuperCall # 121 occurences in 36 modules +--warning_check MissingTvBanner # 3 occurences in 3 modules +--warning_check NamespaceTypo # 3 occurences in 3 modules +--warning_check NetworkSecurityConfig # 46 occurences in 12 modules +--warning_check NewApi # 1996 occurences in 122 modules +--warning_check NotSibling # 15 occurences in 10 modules +--warning_check ObjectAnimatorBinding # 14 occurences in 5 modules +--warning_check OnClick # 49 occurences in 21 modules +--warning_check Orientation # 77 occurences in 19 modules +--warning_check Override # 385 occurences in 36 modules +--warning_check ParcelCreator # 23 occurences in 2 modules +--warning_check ProtectedPermissions # 2413 occurences in 381 modules +--warning_check Range # 80 occurences in 28 modules +--warning_check RecyclerView # 1 occurences in 1 modules +--warning_check ReferenceType # 4 occurences in 1 modules +--warning_check ResourceAsColor # 19 occurences in 14 modules +--warning_check RequiredSize # 52 occurences in 13 modules +--warning_check ResAuto # 3 occurences in 1 modules +--warning_check ResourceCycle # 37 occurences in 10 modules +--warning_check ResourceType # 137 occurences in 36 modules +--warning_check RestrictedApi # 28 occurences in 5 modules +--warning_check RtlCompat # 9 occurences in 6 modules +--warning_check ServiceCast # 3 occurences in 1 modules +--warning_check SoonBlockedPrivateApi # 5 occurences in 3 modules +--warning_check StringFormatInvalid # 148 occurences in 11 modules +--warning_check StringFormatMatches # 4800 occurences in 30 modules +--warning_check UnknownId # 8 occurences in 7 modules +--warning_check ValidFragment # 12 occurences in 5 modules +--warning_check ValidRestrictions # 5 occurences in 1 modules +--warning_check WebViewLayout # 3 occurences in 1 modules +--warning_check WrongCall # 21 occurences in 3 modules +--warning_check WrongConstant # 894 occurences in 126 modules +--warning_check WrongManifestParent # 10 occurences in 4 modules +--warning_check WrongThread # 14 occurences in 6 modules +--warning_check WrongViewCast # 1 occurences in 1 modules + +# TODO(b/158390965): remove this when lint doesn't crash +--disable_check HardcodedDebugMode diff --git a/java/robolectric.go b/java/robolectric.go index 64bd32570..c6b07a17e 100644 --- a/java/robolectric.go +++ b/java/robolectric.go @@ -221,6 +221,7 @@ func RobolectricTestFactory() android.Module { &module.robolectricProperties) module.Module.dexpreopter.isTest = true + module.Module.linter.test = true InitJavaModule(module, android.DeviceSupported) return module diff --git a/java/sdk_library.go b/java/sdk_library.go index a6549ea5f..8e9c0774e 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1101,6 +1101,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) &module.protoProperties, &module.deviceProperties, &module.dexpreoptProperties, + &module.linter.properties, &props, module.sdkComponentPropertiesForChildLibrary(), } diff --git a/scripts/Android.bp b/scripts/Android.bp index e848b5019..1f5503051 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -148,3 +148,9 @@ python_test_host { ], test_suites: ["general-tests"], } + +python_binary_host { + name: "lint-project-xml", + main: "lint-project-xml.py", + srcs: ["lint-project-xml.py"], +} diff --git a/scripts/lint-project-xml.py b/scripts/lint-project-xml.py new file mode 100755 index 000000000..7ab4f0150 --- /dev/null +++ b/scripts/lint-project-xml.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018 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. +# + +"""This file generates project.xml and lint.xml files used to drive the Android Lint CLI tool.""" + +import argparse + + +def check_action(check_type): + """ + Returns an action that appends a tuple of check_type and the argument to the dest. + """ + class CheckAction(argparse.Action): + def __init__(self, option_strings, dest, nargs=None, **kwargs): + if nargs is not None: + raise ValueError("nargs must be None, was %s" % nargs) + super(CheckAction, self).__init__(option_strings, dest, **kwargs) + def __call__(self, parser, namespace, values, option_string=None): + checks = getattr(namespace, self.dest, []) + checks.append((check_type, values)) + setattr(namespace, self.dest, checks) + return CheckAction + + +def parse_args(): + """Parse commandline arguments.""" + + def convert_arg_line_to_args(arg_line): + for arg in arg_line.split(): + if arg.startswith('#'): + return + if not arg.strip(): + continue + yield arg + + parser = argparse.ArgumentParser(fromfile_prefix_chars='@') + parser.convert_arg_line_to_args = convert_arg_line_to_args + parser.add_argument('--project_out', dest='project_out', + help='file to which the project.xml contents will be written.') + parser.add_argument('--config_out', dest='config_out', + help='file to which the lint.xml contents will be written.') + parser.add_argument('--name', dest='name', + help='name of the module.') + parser.add_argument('--srcs', dest='srcs', action='append', default=[], + help='file containing whitespace separated list of source files.') + parser.add_argument('--generated_srcs', dest='generated_srcs', action='append', default=[], + help='file containing whitespace separated list of generated source files.') + parser.add_argument('--resources', dest='resources', action='append', default=[], + help='file containing whitespace separated list of resource files.') + parser.add_argument('--classes', dest='classes', action='append', default=[], + help='file containing the module\'s classes.') + parser.add_argument('--classpath', dest='classpath', action='append', default=[], + help='file containing classes from dependencies.') + parser.add_argument('--extra_checks_jar', dest='extra_checks_jars', action='append', default=[], + help='file containing extra lint checks.') + parser.add_argument('--manifest', dest='manifest', + help='file containing the module\'s manifest.') + parser.add_argument('--merged_manifest', dest='merged_manifest', + help='file containing merged manifest for the module and its dependencies.') + parser.add_argument('--library', dest='library', action='store_true', + help='mark the module as a library.') + parser.add_argument('--test', dest='test', action='store_true', + help='mark the module as a test.') + parser.add_argument('--cache_dir', dest='cache_dir', + help='directory to use for cached file.') + group = parser.add_argument_group('check arguments', 'later arguments override earlier ones.') + group.add_argument('--fatal_check', dest='checks', action=check_action('fatal'), default=[], + help='treat a lint issue as a fatal error.') + group.add_argument('--error_check', dest='checks', action=check_action('error'), default=[], + help='treat a lint issue as an error.') + group.add_argument('--warning_check', dest='checks', action=check_action('warning'), default=[], + help='treat a lint issue as a warning.') + group.add_argument('--disable_check', dest='checks', action=check_action('ignore'), default=[], + help='disable a lint issue.') + return parser.parse_args() + + +class NinjaRspFileReader: + """ + Reads entries from a Ninja rsp file. Ninja escapes any entries in the file that contain a + non-standard character by surrounding the whole entry with single quotes, and then replacing + any single quotes in the entry with the escape sequence '\''. + """ + + def __init__(self, filename): + self.f = open(filename, 'r') + self.r = self.character_reader(self.f) + + def __iter__(self): + return self + + def character_reader(self, f): + """Turns a file into a generator that returns one character at a time.""" + while True: + c = f.read(1) + if c: + yield c + else: + return + + def __next__(self): + entry = self.read_entry() + if entry: + return entry + else: + raise StopIteration + + def read_entry(self): + c = next(self.r, "") + if not c: + return "" + elif c == "'": + return self.read_quoted_entry() + else: + entry = c + for c in self.r: + if c == " " or c == "\n": + break + entry += c + return entry + + def read_quoted_entry(self): + entry = "" + for c in self.r: + if c == "'": + # Either the end of the quoted entry, or the beginning of an escape sequence, read the next + # character to find out. + c = next(self.r) + if not c or c == " " or c == "\n": + # End of the item + return entry + elif c == "\\": + # Escape sequence, expect a ' + c = next(self.r) + if c != "'": + # Malformed escape sequence + raise "malformed escape sequence %s'\\%s" % (entry, c) + entry += "'" + else: + raise "malformed escape sequence %s'%s" % (entry, c) + else: + entry += c + raise "unterminated quoted entry %s" % entry + + +def write_project_xml(f, args): + test_attr = "test='true' " if args.test else "" + + f.write("\n") + f.write("\n") + f.write(" \n" % (args.name, "library='true' " if args.library else "")) + if args.manifest: + f.write(" \n" % (args.manifest, test_attr)) + if args.merged_manifest: + f.write(" \n" % (args.merged_manifest, test_attr)) + for src_file in args.srcs: + for src in NinjaRspFileReader(src_file): + f.write(" \n" % (src, test_attr)) + for src_file in args.generated_srcs: + for src in NinjaRspFileReader(src_file): + f.write(" \n" % (src, test_attr)) + for res_file in args.resources: + for res in NinjaRspFileReader(res_file): + f.write(" \n" % (res, test_attr)) + for classes in args.classes: + f.write(" \n" % classes) + for classpath in args.classpath: + f.write(" \n" % classpath) + for extra in args.extra_checks_jars: + f.write(" \n" % extra) + f.write(" \n") + if args.cache_dir: + f.write(" \n" % args.cache_dir) + f.write("\n") + + +def write_config_xml(f, args): + f.write("\n") + f.write("\n") + for check in args.checks: + f.write(" \n" % (check[1], check[0])) + f.write("\n") + + +def main(): + """Program entry point.""" + args = parse_args() + + if args.project_out: + with open(args.project_out, 'w') as f: + write_project_xml(f, args) + + if args.config_out: + with open(args.config_out, 'w') as f: + write_config_xml(f, args) + + +if __name__ == '__main__': + main() -- cgit v1.2.3-59-g8ed1b From 3791b45f670062d8d01c87b1debb7c36cbed9e70 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 18 Jun 2020 15:46:32 -0700 Subject: Fix annotation processors in kotlin modules that generate resources The kapt rule was only keeping the generated sources, and not the generated classes directory. The generated classes directory will contain resources generated by the annotation processor and needs to be added to the final jar. Test: m ApiFinder Bug: 153485543 Change-Id: I89197d0afcb1eee011c01aa400f9977e66f43768 Merged-In: I89197d0afcb1eee011c01aa400f9977e66f43768 (cherry picked from commit 9ca38d22a49127901dadb14ffa093e29a2942f2d) --- java/java.go | 4 +++- java/kotlin.go | 21 +++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 0c0c659e9..e8d434424 100644 --- a/java/java.go +++ b/java/java.go @@ -1327,8 +1327,10 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { if len(flags.processorPath) > 0 { // Use kapt for annotation processing kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar") - kotlinKapt(ctx, kaptSrcJar, kotlinSrcFiles, srcJars, flags) + kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar") + kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, srcJars, flags) srcJars = append(srcJars, kaptSrcJar) + kotlinJars = append(kotlinJars, kaptResJar) // Disable annotation processing in javac, it's already been handled by kapt flags.processorPath = nil flags.processors = nil diff --git a/java/kotlin.go b/java/kotlin.go index 9b160a082..673970b9c 100644 --- a/java/kotlin.go +++ b/java/kotlin.go @@ -90,7 +90,8 @@ func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath, var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: true}, blueprint.RuleParams{ - Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && mkdir -p "$srcJarDir" "$kaptDir" && ` + + Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` + + `mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` + `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + `${config.GenKotlinBuildFileCmd} $classpath "$name" "" $out.rsp $srcJarDir/list > $kotlinBuildFile &&` + `${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` + @@ -105,6 +106,7 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: `$kaptProcessor ` + `-Xbuild-file=$kotlinBuildFile && ` + `${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources && ` + + `${config.SoongZipCmd} -jar -o $classesJarOut -C $kaptDir/classes -D $kaptDir/classes && ` + `rm -rf "$srcJarDir"`, CommandDeps: []string{ "${config.KotlincCmd}", @@ -118,13 +120,14 @@ var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: RspfileContent: `$in`, }, "kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor", - "classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name") + "classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name", + "classesJarOut") // kotlinKapt performs Kotlin-compatible annotation processing. It takes .kt and .java sources and srcjars, and runs // annotation processors over all of them, producing a srcjar of generated code in outputFile. The srcjar should be // added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing // disabled. -func kotlinKapt(ctx android.ModuleContext, outputFile android.WritablePath, +func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath, srcFiles, srcJars android.Paths, flags javaBuilderFlags) { @@ -152,11 +155,12 @@ func kotlinKapt(ctx android.ModuleContext, outputFile android.WritablePath, kotlinName = strings.ReplaceAll(kotlinName, "/", "__") ctx.Build(pctx, android.BuildParams{ - Rule: kapt, - Description: "kapt", - Output: outputFile, - Inputs: srcFiles, - Implicits: deps, + Rule: kapt, + Description: "kapt", + Output: srcJarOutputFile, + ImplicitOutput: resJarOutputFile, + Inputs: srcFiles, + Implicits: deps, Args: map[string]string{ "classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"), "kotlincFlags": flags.kotlincFlags, @@ -168,6 +172,7 @@ func kotlinKapt(ctx android.ModuleContext, outputFile android.WritablePath, "kaptDir": android.PathForModuleOut(ctx, "kapt/gen").String(), "encodedJavacFlags": encodedJavacFlags, "name": kotlinName, + "classesJarOut": resJarOutputFile.String(), }, }) } -- cgit v1.2.3-59-g8ed1b From aaf58061a09be3723d8bc644240394391a8d2e0d Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 18 Jun 2020 15:52:01 -0700 Subject: Allow kotlin modules to skip packaging the kotlin stdlib Host tools like lint may package their own version of the kotlin stdlib, and any jars loaded by them shouldn't contain the platform version. Add a static_kotlin_stdlib property that defaults to true to allow building the module without staticalling including the kotlin stdlib. Bug: 153485543 Test: m ApiFinder Change-Id: I7da78ef493806ce4ab0050e4ee9e8d330b0509c8 Merged-In: I7da78ef493806ce4ab0050e4ee9e8d330b0509c8 (cherry picked from commit 0b67a8bd0fc87c7c584d165abfeeb9314ce22f18) --- java/java.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index e8d434424..1d4d45972 100644 --- a/java/java.go +++ b/java/java.go @@ -253,6 +253,9 @@ type CompilerProperties struct { // List of files to include in the META-INF/services folder of the resulting jar. Services []string `android:"path,arch_variant"` + + // If true, package the kotlin stdlib into the jar. Defaults to true. + Static_kotlin_stdlib *bool `android:"arch_variant"` } type CompilerDeviceProperties struct { @@ -1345,9 +1348,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Make javac rule depend on the kotlinc rule flags.classpath = append(flags.classpath, kotlinJar) - // Jar kotlin classes into the final jar after javac kotlinJars = append(kotlinJars, kotlinJar) - kotlinJars = append(kotlinJars, deps.kotlinStdlib...) + // Jar kotlin classes into the final jar after javac + if BoolDefault(j.properties.Static_kotlin_stdlib, true) { + kotlinJars = append(kotlinJars, deps.kotlinStdlib...) + } } jars := append(android.Paths(nil), kotlinJars...) -- cgit v1.2.3-59-g8ed1b From 205a504053505699fbf19bb38ec07f8674a8fb1b Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 18 Jun 2020 15:56:48 -0700 Subject: Support adding extra lint checks Add a lint.extra_check_modules property to list modules to use as plugins to Lint. Bug: 153485543 Test: m checkbuild Change-Id: I25c7799438cfec43163e757637c65b8657488d36 Merged-In: I25c7799438cfec43163e757637c65b8657488d36 (cherry picked from commit 92e4b46af561503506b54f9e4c925615bd03a069) --- java/java.go | 3 +++ java/lint.go | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'java/java.go') diff --git a/java/java.go b/java/java.go index 1d4d45972..9e196f43d 100644 --- a/java/java.go +++ b/java/java.go @@ -574,6 +574,7 @@ var ( certificateTag = dependencyTag{name: "certificate"} instrumentationForTag = dependencyTag{name: "instrumentation_for"} usesLibTag = dependencyTag{name: "uses-library"} + extraLintCheckTag = dependencyTag{name: "extra-lint-check"} ) func IsLibDepTag(depTag blueprint.DependencyTag) bool { @@ -668,6 +669,8 @@ func (j *Module) AvailableFor(what string) bool { func (j *Module) deps(ctx android.BottomUpMutatorContext) { if ctx.Device() { + j.linter.deps(ctx) + sdkDep := decodeSdkDep(ctx, sdkContext(j)) if sdkDep.useDefaultLibs { ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...) diff --git a/java/lint.go b/java/lint.go index 441e110cd..fac9a1983 100644 --- a/java/lint.go +++ b/java/lint.go @@ -42,6 +42,9 @@ type LintProperties struct { // Checks that should be skipped. Disabled_checks []string + + // Modules that provide extra lint checks + Extra_check_modules []string } } @@ -76,6 +79,14 @@ func (l *linter) enabled() bool { return BoolDefault(l.properties.Lint.Enabled, true) } +func (l *linter) deps(ctx android.BottomUpMutatorContext) { + if !l.enabled() { + return + } + + ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), extraLintCheckTag, l.properties.Lint.Extra_check_modules...) +} + func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir android.WritablePath, deps android.Paths) { @@ -179,6 +190,16 @@ func (l *linter) lint(ctx android.ModuleContext) { return } + extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag) + for _, extraLintCheckModule := range extraLintCheckModules { + if dep, ok := extraLintCheckModule.(Dependency); ok { + l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars()...) + } else { + ctx.PropertyErrorf("lint.extra_check_modules", + "%s is not a java module", ctx.OtherModuleName(extraLintCheckModule)) + } + } + rule := android.NewRuleBuilder() if l.manifest == nil { -- cgit v1.2.3-59-g8ed1b From 9ee66da850cbc0be76e556f57af37781e5631662 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 17 Jun 2020 16:59:43 +0100 Subject: Fix check-boot-jars when a boot jar is provided by prebuilt Previously, when a boot jar was provided by a java_sdk_library_import module the check-boot-jars check failed because the file it depended on was not available. In an incremental build the build failed due to the file in the out directory not having a rule to generate it. That was because the module was named prebuilt_. instead of .. This was fixed by simply removing prebuilt_ prefix from the name if it was present. After fixing that the check-boot-jars still did not work properly because it was expecting a jar file containing .class files but instead was given a jar file containing .dex files which meant the check did not work properly. This was fixed by defining a new ApexDependency interface for use by the apex/apex.go code to use instead of java.Dependency for generating the androidmk entries. The *SdkLibraryImport type then implemented those, by delegating to the implementation library. Bug: 158304459 Bug: 159112414 Test: m check-boot-jars m checkbuild manual inspection of the .jar file used by check-boot-jars to ensure it contained .class files and not .dex files. Change-Id: I545c5c9072dd472337d2f9b4dfdf08f53c981662 Merged-In: I545c5c9072dd472337d2f9b4dfdf08f53c981662 --- apex/androidmk.go | 2 +- apex/apex.go | 4 +++- java/java.go | 9 +++++++-- java/sdk_library.go | 20 ++++++++++++++++++++ 4 files changed, 31 insertions(+), 4 deletions(-) (limited to 'java/java.go') diff --git a/apex/androidmk.go b/apex/androidmk.go index 811bc426e..cbff7f4f4 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -171,7 +171,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.jar.jar fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", strings.TrimSuffix(fi.Stem(), ".jar")) - if javaModule, ok := fi.module.(java.Dependency); ok { + if javaModule, ok := fi.module.(java.ApexDependency); ok { fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", javaModule.ImplementationAndResourcesJars()[0].String()) fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", javaModule.HeaderJars()[0].String()) } else { diff --git a/apex/apex.go b/apex/apex.go index 387b29b14..994a05176 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1685,7 +1685,9 @@ type javaDependency interface { func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaDependency, module android.Module) apexFile { dirInApex := "javalib" fileToCopy := lib.DexJar() - af := newApexFile(ctx, fileToCopy, module.Name(), dirInApex, javaSharedLib, module) + // Remove prebuilt_ if necessary so the source and prebuilt modules have the same name. + name := strings.TrimPrefix(module.Name(), "prebuilt_") + af := newApexFile(ctx, fileToCopy, name, dirInApex, javaSharedLib, module) af.jacocoReportClassesFile = lib.JacocoReportClassesFile() af.stem = lib.Stem() + ".jar" return af diff --git a/java/java.go b/java/java.go index 9e196f43d..90e9b1f6f 100644 --- a/java/java.go +++ b/java/java.go @@ -517,11 +517,16 @@ func (j *Module) OutputFiles(tag string) (android.Paths, error) { var _ android.OutputFileProducer = (*Module)(nil) -type Dependency interface { +// Methods that need to be implemented for a module that is added to apex java_libs property. +type ApexDependency interface { HeaderJars() android.Paths + ImplementationAndResourcesJars() android.Paths +} + +type Dependency interface { + ApexDependency ImplementationJars() android.Paths ResourceJars() android.Paths - ImplementationAndResourcesJars() android.Paths DexJar() android.Path AidlIncludeDirs() android.Paths ExportedSdkLibs() []string diff --git a/java/sdk_library.go b/java/sdk_library.go index 8e9c0774e..f000af91e 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -2005,6 +2005,26 @@ func (module *SdkLibraryImport) Stem() string { return module.BaseModuleName() } +var _ ApexDependency = (*SdkLibraryImport)(nil) + +// to satisfy java.ApexDependency interface +func (module *SdkLibraryImport) HeaderJars() android.Paths { + if module.implLibraryModule == nil { + return nil + } else { + return module.implLibraryModule.HeaderJars() + } +} + +// to satisfy java.ApexDependency interface +func (module *SdkLibraryImport) ImplementationAndResourcesJars() android.Paths { + if module.implLibraryModule == nil { + return nil + } else { + return module.implLibraryModule.ImplementationAndResourcesJars() + } +} + // // java_sdk_library_xml // -- cgit v1.2.3-59-g8ed1b From c4422106a7cf4731e27d664646bc0d57ad3f37fa Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 24 Jun 2020 16:22:38 +0100 Subject: Apply hiddenapi encoding to java_sdk_library .impl Adds a ConfigurationName property, and ConfigurationName() method that allows a library to separate its name (e.g. framework-tethering.impl) from the name used in the build configuration, e.g. ctx.Config().BootJars(). Updates hiddenapi processing to use ConfigurationName() instead of ctx.ModuleName(). Changes java_sdk_library to set the ConfigurationName property of the implementation library to the name of the module instead of .impl so that it will match the name in the boot jars list. Bug: 159683330 Test: m framework-tethering dexdump ${PRODUCT_OUT}/apex/com.android.tethering/javalib/framework-tethering.jar | grep hiddenapi | wc -l Verify that there are >0 hiddenapi entries. Add java_sdk_library_import prefer=true for framework-tethering and repeat the above to verify that there are 0 hiddenapi entries. Apply this change, repeat above and verify that there are the same # of entries as before. Remove the prebuilt for framework-tethering Repeat the above and verify that there is no change to the # of entries Change-Id: I6c3016c35d0fcb1b95d4f9b37a307a69878f8e0a --- java/hiddenapi.go | 12 +++++++++--- java/java.go | 15 ++++++++++++++- java/sdk_library.go | 13 ++++++++++--- 3 files changed, 33 insertions(+), 7 deletions(-) (limited to 'java/java.go') diff --git a/java/hiddenapi.go b/java/hiddenapi.go index ce624bfc1..130b63496 100644 --- a/java/hiddenapi.go +++ b/java/hiddenapi.go @@ -59,10 +59,9 @@ type hiddenAPIIntf interface { var _ hiddenAPIIntf = (*hiddenAPI)(nil) -func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOutPath, +func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bool, dexJar android.ModuleOutPath, implementationJar android.Path, uncompressDex bool) android.ModuleOutPath { if !ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") { - name := ctx.ModuleName() // Modules whose names are of the format -hiddenapi provide hiddenapi information // for the boot jar module . Otherwise, the module provides information for itself. @@ -90,7 +89,14 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, dexJar android.ModuleOu // the gathered information in the generated dex file. if name == bootJarName { hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar") - h.bootDexJarPath = dexJar + + // More than one library with the same classes can be encoded but only one can + // be added to the global set of flags, otherwise it will result in duplicate + // classes which is an error. Therefore, only add the dex jar of one of them + // to the global set of flags. + if primary { + h.bootDexJarPath = dexJar + } hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex) dexJar = hiddenAPIJar } diff --git a/java/java.go b/java/java.go index 90e9b1f6f..5632ff586 100644 --- a/java/java.go +++ b/java/java.go @@ -342,6 +342,12 @@ type CompilerDeviceProperties struct { // otherwise provides defaults libraries to add to the bootclasspath. System_modules *string + // The name of the module as used in build configuration. + // + // Allows a library to separate its actual name from the name used in + // build configuration, e.g.ctx.Config().BootJars(). + ConfigurationName *string `blueprint:"mutated"` + // set the name of the output Stem *string @@ -1617,8 +1623,11 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { return } + configurationName := j.ConfigurationName() + primary := configurationName == ctx.ModuleName() + // Hidden API CSV generation and dex encoding - dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, + dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, configurationName, primary, dexOutputFile, j.implementationJarFile, proptools.Bool(j.deviceProperties.Uncompress_dex)) // merge dex jar with resources if necessary @@ -1872,6 +1881,10 @@ func (j *Module) Stem() string { return proptools.StringDefault(j.deviceProperties.Stem, j.Name()) } +func (j *Module) ConfigurationName() string { + return proptools.StringDefault(j.deviceProperties.ConfigurationName, j.BaseModuleName()) +} + func (j *Module) JacocoReportClassesFile() android.Path { return j.jacocoReportClassesFile } diff --git a/java/sdk_library.go b/java/sdk_library.go index e64310fbb..679c07597 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1088,15 +1088,22 @@ func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) stri // Creates the implementation java library func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) { + + moduleNamePtr := proptools.StringPtr(module.BaseModuleName()) + props := struct { - Name *string - Visibility []string - Instrument bool + Name *string + Visibility []string + Instrument bool + ConfigurationName *string }{ Name: proptools.StringPtr(module.implLibraryModuleName()), Visibility: module.sdkLibraryProperties.Impl_library_visibility, // Set the instrument property to ensure it is instrumented when instrumentation is required. Instrument: true, + + // Make the created library behave as if it had the same name as this module. + ConfigurationName: moduleNamePtr, } properties := []interface{}{ -- cgit v1.2.3-59-g8ed1b