diff --git a/android/config.go b/android/config.go index 1cb543db9..5c4f0a855 100644 --- a/android/config.go +++ b/android/config.go @@ -1027,6 +1027,10 @@ func (c *deviceConfig) NativeCoverageEnabled() bool { return Bool(c.config.productVariables.NativeCoverage) } +func (c *deviceConfig) ClangCoverageEnabled() bool { + return Bool(c.config.productVariables.ClangCoverage) +} + func (c *deviceConfig) CoverageEnabledForPath(path string) bool { coverage := false if c.config.productVariables.CoveragePaths != nil { diff --git a/android/variable.go b/android/variable.go index 2bf84dd99..c58867201 100644 --- a/android/variable.go +++ b/android/variable.go @@ -243,6 +243,7 @@ type productVariables struct { TidyChecks *string `json:",omitempty"` NativeCoverage *bool `json:",omitempty"` + ClangCoverage *bool `json:",omitempty"` CoveragePaths []string `json:",omitempty"` CoverageExcludePaths []string `json:",omitempty"` diff --git a/apex/apex.go b/apex/apex.go index d293fcc3d..6ad8b623e 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1098,7 +1098,7 @@ func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizer } func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool { - return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled() + return ctx.Device() && (ctx.DeviceConfig().NativeCoverageEnabled() || ctx.DeviceConfig().ClangCoverageEnabled()) } func (a *apexBundle) PreventInstall() { diff --git a/cc/coverage.go b/cc/coverage.go index b6451eea1..b94b628fc 100644 --- a/cc/coverage.go +++ b/cc/coverage.go @@ -43,7 +43,7 @@ func (cov *coverage) props() []interface{} { return []interface{}{&cov.Properties} } -func getProfileLibraryName(ctx ModuleContextIntf) string { +func getGcovProfileLibraryName(ctx ModuleContextIntf) string { // This function should only ever be called for a cc.Module, so the // following statement should always succeed. if ctx.useSdk() { @@ -53,28 +53,47 @@ func getProfileLibraryName(ctx ModuleContextIntf) string { } } +func getClangProfileLibraryName(ctx ModuleContextIntf) string { + if ctx.useSdk() { + return "libprofile-clang-extras_ndk" + } else { + return "libprofile-clang-extras" + } +} + func (cov *coverage) deps(ctx DepsContext, deps Deps) Deps { if cov.Properties.NeedCoverageVariant { ctx.AddVariationDependencies([]blueprint.Variation{ {Mutator: "link", Variation: "static"}, - }, coverageDepTag, getProfileLibraryName(ctx)) + }, coverageDepTag, getGcovProfileLibraryName(ctx)) + ctx.AddVariationDependencies([]blueprint.Variation{ + {Mutator: "link", Variation: "static"}, + }, coverageDepTag, getClangProfileLibraryName(ctx)) } return deps } func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags, PathDeps) { - if !ctx.DeviceConfig().NativeCoverageEnabled() { + gcovCoverage := ctx.DeviceConfig().NativeCoverageEnabled() + clangCoverage := ctx.DeviceConfig().ClangCoverageEnabled() + + if !gcovCoverage && !clangCoverage { return flags, deps } if cov.Properties.CoverageEnabled { flags.Coverage = true - flags.Local.CommonFlags = append(flags.Local.CommonFlags, "--coverage", "-O0") cov.linkCoverage = true - // Override -Wframe-larger-than and non-default optimization - // flags that the module may use. - flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0") + if gcovCoverage { + flags.Local.CommonFlags = append(flags.Local.CommonFlags, "--coverage", "-O0") + + // Override -Wframe-larger-than and non-default optimization + // flags that the module may use. + flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0") + } else if clangCoverage { + flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-fprofile-instr-generate", "-fcoverage-mapping") + } } // Even if we don't have coverage enabled, if any of our object files were compiled @@ -112,12 +131,19 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags } if cov.linkCoverage { - flags.Local.LdFlags = append(flags.Local.LdFlags, "--coverage") + if gcovCoverage { + flags.Local.LdFlags = append(flags.Local.LdFlags, "--coverage") - coverage := ctx.GetDirectDepWithTag(getProfileLibraryName(ctx), coverageDepTag).(*Module) - deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) + coverage := ctx.GetDirectDepWithTag(getGcovProfileLibraryName(ctx), coverageDepTag).(*Module) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) - flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv") + flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--wrap,getenv") + } else if clangCoverage { + flags.Local.LdFlags = append(flags.Local.LdFlags, "-fprofile-instr-generate") + + coverage := ctx.GetDirectDepWithTag(getClangProfileLibraryName(ctx), coverageDepTag).(*Module) + deps.WholeStaticLibs = append(deps.WholeStaticLibs, coverage.OutputFile().Path()) + } } return flags, deps @@ -125,7 +151,7 @@ func (cov *coverage) flags(ctx ModuleContext, flags Flags, deps PathDeps) (Flags func (cov *coverage) begin(ctx BaseModuleContext) { // Coverage is disabled globally - if !ctx.DeviceConfig().NativeCoverageEnabled() { + if !ctx.DeviceConfig().NativeCoverageEnabled() && !ctx.DeviceConfig().ClangCoverageEnabled() { return }