diff --git a/apex/apex_test.go b/apex/apex_test.go index d6803f639..18052912a 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -8843,19 +8843,7 @@ func TestApexJavaCoverage(t *testing.T) { android.FixtureWithRootAndroidBp(bp), dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"), dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"), - android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - }), - // need to mock jacocoagent here to satisfy dependency added for - // instrumented libraries at build time - android.FixtureAddFile("jacocoagent/Android.bp", []byte(` - java_library { - name: "jacocoagent", - srcs: ["Test.java"], - system_modules: "none", - sdk_version: "none", - } - `)), + java.PrepareForTestWithJacocoInstrumentation, ).RunTest(t) // Make sure jacoco ran on both mylib and mybootclasspathlib diff --git a/java/base.go b/java/base.go index 53f0f52c2..995d257f9 100644 --- a/java/base.go +++ b/java/base.go @@ -650,6 +650,10 @@ func (j *Module) shouldInstrumentInApex(ctx android.BaseModuleContext) bool { return false } +func (j *Module) setInstrument(value bool) { + j.properties.Instrument = value +} + func (j *Module) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return android.SdkSpecFrom(ctx, String(j.deviceProperties.Sdk_version)) } @@ -789,9 +793,6 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) { } else if j.shouldInstrumentStatic(ctx) { ctx.AddVariationDependencies(nil, staticLibTag, "jacocoagent") } - if j.shouldInstrument(ctx) { - ctx.AddVariationDependencies(nil, libTag, "jacocoagent") - } if j.useCompose() { ctx.AddVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), kotlinPluginTag, @@ -1435,10 +1436,6 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { j.headerJarFile = j.implementationJarFile } - if j.shouldInstrumentInApex(ctx) { - j.properties.Instrument = true - } - // enforce syntax check to jacoco filters for any build (http://b/183622051) specs := j.jacocoModuleToZipCommand(ctx) if ctx.Failed() { diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go index 2bfb255af..c63df599a 100644 --- a/java/bootclasspath_fragment_test.go +++ b/java/bootclasspath_fragment_test.go @@ -96,23 +96,6 @@ func TestBootclasspathFragmentInconsistentArtConfiguration_ApexMixture(t *testin } func TestBootclasspathFragment_Coverage(t *testing.T) { - prepareForTestWithFrameworkCoverage := android.GroupFixturePreparers( - android.FixtureMergeEnv(map[string]string{ - "EMMA_INSTRUMENT": "true", - "EMMA_INSTRUMENT_FRAMEWORK": "true", - }), - // need to mock jacocoagent here to satisfy dependency added for - // instrumented libraries at build time - android.FixtureAddFile("jacocoagent/Android.bp", []byte(` - java_library { - name: "jacocoagent", - srcs: ["Test.java"], - system_modules: "none", - sdk_version: "none", - } - `)), - ) - prepareWithBp := android.FixtureWithRootAndroidBp(` bootclasspath_fragment { name: "myfragment", @@ -191,7 +174,7 @@ func TestBootclasspathFragment_Coverage(t *testing.T) { t.Run("with coverage", func(t *testing.T) { result := android.GroupFixturePreparers( - prepareForTestWithFrameworkCoverage, + prepareForTestWithFrameworkJacocoInstrumentation, preparer, ).RunTest(t) checkContents(t, result, "mybootlib", "coveragelib") diff --git a/java/jacoco.go b/java/jacoco.go index e11c2ce69..f8012b852 100644 --- a/java/jacoco.go +++ b/java/jacoco.go @@ -47,6 +47,34 @@ var ( "strippedJar", "stripSpec", "tmpDir", "tmpJar") ) +func jacocoDepsMutator(ctx android.BottomUpMutatorContext) { + type instrumentable interface { + shouldInstrument(ctx android.BaseModuleContext) bool + shouldInstrumentInApex(ctx android.BaseModuleContext) bool + setInstrument(value bool) + } + + j, ok := ctx.Module().(instrumentable) + if !ctx.Module().Enabled() || !ok { + return + } + + if j.shouldInstrumentInApex(ctx) { + j.setInstrument(true) + } + + if j.shouldInstrument(ctx) && ctx.ModuleName() != "jacocoagent" { + // We can use AddFarVariationDependencies here because, since this dep + // is added as libs only (i.e. a compiletime CLASSPATH entry only), + // the first variant of jacocoagent is sufficient to prevent + // compile time errors. + // At this stage in the build, AddVariationDependencies is not always + // able to procure a variant of jacocoagent that matches the calling + // module. + ctx.AddFarVariationDependencies(ctx.Module().Target().Variations(), libTag, "jacocoagent") + } +} + // Instruments a jar using the Jacoco command line interface. Uses stripSpec to extract a subset // of the classes in inputJar into strippedJar, instruments strippedJar into tmpJar, and then // combines the classes in tmpJar with inputJar (preferring the instrumented classes in tmpJar) diff --git a/java/java.go b/java/java.go index 0251b5754..d04e52a2c 100644 --- a/java/java.go +++ b/java/java.go @@ -66,6 +66,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { // to support the checks in dexpreoptDisabled(). ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel() + // needs access to ApexInfoProvider which is available after variant creation + ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel() }) ctx.RegisterSingletonType("logtags", LogtagsSingleton) diff --git a/java/testing.go b/java/testing.go index 511cc5ddb..1f411913b 100644 --- a/java/testing.go +++ b/java/testing.go @@ -59,11 +59,9 @@ var PrepareForTestWithJavaBuildComponents = android.GroupFixturePreparers( }.AddToFixture(), ) -// Test fixture preparer that will define all default java modules except the -// fake_tool_binary for dex2oatd. -var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers( - // Make sure that all the module types used in the defaults are registered. - PrepareForTestWithJavaBuildComponents, +var prepareForTestWithFrameworkDeps = android.GroupFixturePreparers( + // The java default module definitions. + android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), // Additional files needed when test disallows non-existent source. android.MockFS{ // Needed for framework-res @@ -77,8 +75,14 @@ var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixtu "build/make/core/proguard.flags": nil, "build/make/core/proguard_basic_keeps.flags": nil, }.AddToFixture(), - // The java default module definitions. - android.FixtureAddTextFile(defaultJavaDir+"/Android.bp", gatherRequiredDepsForTest()), +) + +// Test fixture preparer that will define all default java modules except the +// fake_tool_binary for dex2oatd. +var PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd = android.GroupFixturePreparers( + // Make sure that all the module types used in the defaults are registered. + PrepareForTestWithJavaBuildComponents, + prepareForTestWithFrameworkDeps, // Add dexpreopt compat libs (android.test.base, etc.) and a fake dex2oatd module. dexpreopt.PrepareForTestWithDexpreoptCompatLibs, ) @@ -141,6 +145,30 @@ var PrepareForTestWithPrebuiltsOfCurrentApi = FixtureWithPrebuiltApis(map[string "30": {}, }) +var prepareForTestWithFrameworkJacocoInstrumentation = android.GroupFixturePreparers( + android.FixtureMergeEnv(map[string]string{ + "EMMA_INSTRUMENT_FRAMEWORK": "true", + }), + PrepareForTestWithJacocoInstrumentation, +) + +// PrepareForTestWithJacocoInstrumentation creates a mock jacocoagent library that can be +// depended on as part of the build process for instrumented Java modules. +var PrepareForTestWithJacocoInstrumentation = android.GroupFixturePreparers( + android.FixtureMergeEnv(map[string]string{ + "EMMA_INSTRUMENT": "true", + }), + android.FixtureAddFile("jacocoagent/Test.java", nil), + android.FixtureAddFile("jacocoagent/Android.bp", []byte(` + java_library { + name: "jacocoagent", + host_supported: true, + srcs: ["Test.java"], + sdk_version: "current", + } + `)), +) + // FixtureWithPrebuiltApis creates a preparer that will define prebuilt api modules for the // specified releases and modules. //