diff options
author | 2016-11-17 16:01:26 +0000 | |
---|---|---|
committer | 2016-11-17 18:18:39 +0000 | |
commit | e4f5c82209dc939857815cefb52933bf249cc52d (patch) | |
tree | 362989d76a2bc6f8388cd3b4871fe8af250001dc /src/main/java/com | |
parent | a2bbe67ecf5a95777e13820c165f2955037a14fd (diff) |
Add ctx.coverage_instrumented function to Skylark
Skylark already has ctx.configuration.coverage_enabled to determine if coverage data collection is on for an entire run. But that does not reveal which targets specifically are supposed to be instrumented (based on the values of --instrumentation_filer and --instrument_test_targets). This is inefficient for languages which add coverage instrumentation at compile-time, though correct coverage output can still be produced by instrumenting everything and filtering later.
By default, this function returns whether the rule represented by ctx should be instrumented. If a Skylark Target (e.g. from a label or label_list attribute in ctx.attr) is passed to the function, it instead returns whether that Target is a rule whose sources should be instrumented. Rules that directly incorporate source-files from their dependencies before compilation (e.g. header files) may need to know if those source files need to be instrumented when compiled.
Expanded the documentation of instrumented_files to be a more general section on implementing code coverage instrumentation in Skylark.
Also tweaked the code comment and variable names for the version of shouldIncludeLocalSources that takes a TransitiveInfoCollection.
RELNOTES: Add ctx.coverage_instrumented function to Skylark, to indicate whether a specific targets should be instrumented for code coverage data collection.
--
MOS_MIGRATED_REVID=139460989
Diffstat (limited to 'src/main/java/com')
3 files changed, 43 insertions, 7 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java index b8b670acdb..1abd5fca84 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java @@ -2228,7 +2228,10 @@ public final class BuildConfiguration { } @SkylarkCallable(name = "coverage_enabled", structField = true, - doc = "A boolean that tells whether code coverage is enabled.") + doc = "A boolean that tells whether code coverage is enabled for this run. Note that this " + + "does not compute whether a specific rule should be instrumented for code coverage " + + "data collection. For that, see the <a href=\"ctx.html#coverage_instrumented\"><code>" + + "ctx.coverage_instrumented</code></a> function.") public boolean isCodeCoverageEnabled() { return options.collectCodeCoverage; } diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java index ae6a630955..50fe8510cf 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java +++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleContext.java @@ -31,6 +31,7 @@ import com.google.devtools.build.lib.analysis.LabelExpander.NotUniqueExpansionEx import com.google.devtools.build.lib.analysis.MakeVariableExpander.ExpansionException; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; +import com.google.devtools.build.lib.analysis.TransitiveInfoCollection; import com.google.devtools.build.lib.analysis.config.BuildConfiguration; import com.google.devtools.build.lib.analysis.config.FragmentCollection; import com.google.devtools.build.lib.cmdline.Label; @@ -47,8 +48,11 @@ import com.google.devtools.build.lib.packages.RawAttributeMapper; import com.google.devtools.build.lib.packages.SkylarkAspect; import com.google.devtools.build.lib.packages.SkylarkClassObject; import com.google.devtools.build.lib.packages.SkylarkClassObjectConstructor; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.shell.ShellUtils; import com.google.devtools.build.lib.shell.ShellUtils.TokenizationException; +import com.google.devtools.build.lib.skylarkinterface.Param; import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable; import com.google.devtools.build.lib.skylarkinterface.SkylarkModule; import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory; @@ -514,6 +518,35 @@ public final class SkylarkRuleContext { return ruleContext.getHostConfiguration(); } + @SkylarkCallable(name = "coverage_instrumented", + doc = "Returns whether code coverage instrumentation should be generated when performing " + + "compilation actions for this rule or, if <code>target</code> is provided, the rule " + + "specified by that Target. (If a non-rule Target is provided, this returns False.) This " + + "differs from <code>coverage_enabled</code> in the <a href=\"configuration.html\">" + + "configuration</a>, which notes whether coverage data collection is enabled for the " + + "entire run, but not whether a specific target should be instrumented.", + parameters = { + @Param( + name = "target", + type = TransitiveInfoCollection.class, + defaultValue = "None", + noneable = true, + named = true, + doc = "A Target specifying a rule. If not provided, defaults to the current rule.") + }) + public boolean instrumentCoverage(Object targetUnchecked) { + BuildConfiguration config = ruleContext.getConfiguration(); + if (!config.isCodeCoverageEnabled()) { + return false; + } + if (targetUnchecked == Runtime.NONE) { + return InstrumentedFilesCollector.shouldIncludeLocalSources(ruleContext); + } + TransitiveInfoCollection target = (TransitiveInfoCollection) targetUnchecked; + return (target.getProvider(InstrumentedFilesProvider.class) != null) + && InstrumentedFilesCollector.shouldIncludeLocalSources(config, target); + } + @SkylarkCallable(name = "features", structField = true, doc = "Returns the set of features that are enabled for this rule." ) diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java index 1fb2fbfeea..c2ba279bf3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesCollector.java @@ -174,14 +174,14 @@ public final class InstrumentedFilesCollector { } /** - * Return whether the sources included from {@code dep} (a {@link TransitiveInfoCollection} - * representing a rule's dependency) should be instrumented according the --instrumentation_filter - * and --instrument_test_targets settings in {@code config}. + * Return whether the sources included by {@code target} (a {@link TransitiveInfoCollection} + * representing a rule) should be instrumented according the --instrumentation_filter and + * --instrument_test_targets settings in {@code config}. */ public static boolean shouldIncludeLocalSources(BuildConfiguration config, - TransitiveInfoCollection dep) { - return shouldIncludeLocalSources(config, dep.getLabel(), - dep.getProvider(TestProvider.class) != null); + TransitiveInfoCollection target) { + return shouldIncludeLocalSources(config, target.getLabel(), + target.getProvider(TestProvider.class) != null); } private static boolean shouldIncludeLocalSources(BuildConfiguration config, Label label, |