From 1acd4475f2cd7312bcf86a6c5674605baf68f4ce Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Mon, 10 Dec 2018 15:12:40 -0800 Subject: Extend coverage mutator to allow variants with coverage on and off Bug: http://b/116873221 This allows us to enable coverage for a module (typically static libraries) even if a dependent module cannot build with coverage. In this case, the dependent module can just pick the variant with coverage off. - Create the following variants from the coverage mutator: - "" (empty): Don't build with coverage and always pick the non-coverage variants for dependents. This variant is created for modules with 'native_coverage: false'. - "cov": If this module's path is covered by the COVERAGE_PATHS option, build this module with coverage. If not, build this module without coverage. In either case, pick coverage variants ("cov") for dependencies if available. - Do not enable coverage: - for NDK stub libraries - if sdk_version < 23 since libc doesn't export 'stderr' which is needed by the coverage/profile runtime library. - for VNDK libraries Test: In AOSP: m COVERAGE_PATHS=system/security NATIVE_COVERAGE=true nothing Change-Id: I4d08790d35cdeaf12fb3c4f999d69a870e65836a --- cc/cc.go | 21 +++++++++++++++++-- cc/coverage.go | 64 ++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/cc/cc.go b/cc/cc.go index 081da123..7b19e98d 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -63,7 +63,7 @@ func init() { ctx.TopDown("sanitize_runtime_deps", sanitizerRuntimeDepsMutator) ctx.BottomUp("sanitize_runtime", sanitizerRuntimeMutator).Parallel() - ctx.BottomUp("coverage", coverageLinkingMutator).Parallel() + ctx.BottomUp("coverage", coverageMutator).Parallel() ctx.TopDown("vndk_deps", sabiDepsMutator) ctx.TopDown("lto_deps", ltoDepsMutator) @@ -258,6 +258,7 @@ type ModuleContextIntf interface { baseModuleName() string getVndkExtendsModuleName() string isPgoCompile() bool + isNDKStubLibrary() bool useClangLld(actx ModuleContext) bool apexName() string hasStubsVariants() bool @@ -497,6 +498,10 @@ func (c *Module) useVndk() bool { return c.Properties.UseVndk } +func (c *Module) isCoverageVariant() bool { + return c.coverage.Properties.IsCoverageVariant +} + func (c *Module) isNdk() bool { return inList(c.Name(), ndkMigratedLibs) } @@ -530,6 +535,13 @@ func (c *Module) isPgoCompile() bool { return false } +func (c *Module) isNDKStubLibrary() bool { + if _, ok := c.compiler.(*stubDecorator); ok { + return true + } + return false +} + func (c *Module) isVndkSp() bool { if vndkdep := c.vndkdep; vndkdep != nil { return vndkdep.isVndkSp() @@ -675,6 +687,10 @@ func (ctx *moduleContextImpl) isPgoCompile() bool { return ctx.mod.isPgoCompile() } +func (ctx *moduleContextImpl) isNDKStubLibrary() bool { + return ctx.mod.isNDKStubLibrary() +} + func (ctx *moduleContextImpl) isVndkSp() bool { return ctx.mod.isVndkSp() } @@ -956,7 +972,8 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // module is marked with 'bootstrap: true'). if c.HasStubsVariants() && android.DirectlyInAnyApex(ctx, ctx.baseModuleName()) && - !c.inRecovery() && !c.useVndk() && !c.static() && c.IsStubs() { + !c.inRecovery() && !c.useVndk() && !c.static() && !c.isCoverageVariant() && + c.IsStubs() { c.Properties.HideFromMake = false // unhide // Note: this is still non-installable } diff --git a/cc/coverage.go b/cc/coverage.go index 391b1181..79f7d7d8 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -15,13 +15,16 @@ package cc import ( + "strconv" + "android/soong/android" ) type CoverageProperties struct { Native_coverage *bool - CoverageEnabled bool `blueprint:"mutated"` + CoverageEnabled bool `blueprint:"mutated"` + IsCoverageVariant bool `blueprint:"mutated"` } type coverage struct { @@ -93,27 +96,54 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags) Flags { return flags } -func coverageLinkingMutator(mctx android.BottomUpMutatorContext) { - if c, ok := mctx.Module().(*Module); ok && c.coverage != nil { - var enabled bool +func coverageMutator(mctx android.BottomUpMutatorContext) { + // Coverage is disabled globally + if !mctx.DeviceConfig().NativeCoverageEnabled() { + return + } + + if c, ok := mctx.Module().(*Module); ok { + var needCoverageVariant bool + var needCoverageBuild bool - if !mctx.DeviceConfig().NativeCoverageEnabled() { - // Coverage is disabled globally - } else if mctx.Host() { + if mctx.Host() { // TODO(dwillemsen): because of -nodefaultlibs, we must depend on libclang_rt.profile-*.a // Just turn off for now. - } else if c.coverage.Properties.Native_coverage != nil { - enabled = *c.coverage.Properties.Native_coverage - } else { - enabled = mctx.DeviceConfig().CoverageEnabledForPath(mctx.ModuleDir()) + } else if c.useVndk() || c.hasVendorVariant() { + // Do not enable coverage for VNDK libraries + } else if c.isNDKStubLibrary() { + // Do not enable coverage for NDK stub libraries + } else if c.coverage != nil { + // Check if Native_coverage is set to false. This property defaults to true. + needCoverageVariant = BoolDefault(c.coverage.Properties.Native_coverage, true) + + if sdk_version := String(c.Properties.Sdk_version); sdk_version != "current" { + // Native coverage is not supported for SDK versions < 23 + if fromApi, err := strconv.Atoi(sdk_version); err == nil && fromApi < 23 { + needCoverageVariant = false + } + } + + if needCoverageVariant { + // Coverage variant is actually built with coverage if enabled for its module path + needCoverageBuild = mctx.DeviceConfig().CoverageEnabledForPath(mctx.ModuleDir()) + } } - if enabled { - // Create a variation so that we don't need to recompile objects - // when turning on or off coverage. We'll still relink the necessary - // binaries, since we don't know which ones those are until later. - m := mctx.CreateLocalVariations("cov") - m[0].(*Module).coverage.Properties.CoverageEnabled = true + if needCoverageVariant { + m := mctx.CreateVariations("", "cov") + + // Setup the non-coverage version and set HideFromMake and + // PreventInstall to true. + m[0].(*Module).coverage.Properties.CoverageEnabled = false + m[0].(*Module).coverage.Properties.IsCoverageVariant = false + m[0].(*Module).Properties.HideFromMake = true + m[0].(*Module).Properties.PreventInstall = true + + // The coverage-enabled version inherits HideFromMake, + // PreventInstall from the original module. + m[1].(*Module).coverage.Properties.CoverageEnabled = needCoverageBuild + m[1].(*Module).coverage.Properties.IsCoverageVariant = true } } } -- cgit v1.2.3