diff options
author | 2015-09-22 13:51:48 +0000 | |
---|---|---|
committer | 2015-09-22 17:09:47 +0000 | |
commit | 8ddc32d3cf5bc1e92206f84b9e1cc5b6e70e2375 (patch) | |
tree | bd4879dc54e79d13dbe8ce6ffc0bd8cb79b7b9c5 /src/main | |
parent | f1b537ae1e8928a36929be72f2b7789e0807303c (diff) |
Switch objc rules to standard coverage propagation using InstrumentedFilesCollector.
--
MOS_MIGRATED_REVID=103642172
Diffstat (limited to 'src/main')
17 files changed, 258 insertions, 219 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java b/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java index 73519f95a7..bd5bc75b84 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/OutputFileConfiguredTarget.java @@ -15,15 +15,12 @@ package com.google.devtools.build.lib.analysis; import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.packages.OutputFile; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProviderImpl; -import java.util.Map; - /** * A ConfiguredTarget for an OutputFile. */ @@ -79,11 +76,6 @@ public class OutputFileConfiguredTarget extends FileConfiguredTarget .getBaselineCoverageArtifacts(); } - @Override - public Map<String, String> getExtraEnv() { - return ImmutableMap.of(); - } - /** * Returns the corresponding provider from the generating rule, if it is non-null, or {@code * defaultValue} otherwise. diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java index bec3a9b9ee..887a03c181 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleConfiguredTargetBuilder.java @@ -43,6 +43,7 @@ import com.google.devtools.build.lib.rules.extra.ExtraActionSpec; import com.google.devtools.build.lib.rules.test.ExecutionInfoProvider; import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.rules.test.TestActionBuilder; +import com.google.devtools.build.lib.rules.test.TestEnvironmentProvider; import com.google.devtools.build.lib.rules.test.TestProvider; import com.google.devtools.build.lib.rules.test.TestProvider.TestParams; import com.google.devtools.build.lib.syntax.ClassObject; @@ -165,19 +166,21 @@ public final class RuleConfiguredTargetBuilder { "Having more than 50 shards is indicative of poor test organization. " + "Please reduce the number of shards."); } - TestActionBuilder testActionBuilder = new TestActionBuilder(ruleContext); - InstrumentedFilesProvider instrumentedFilesProvider = - findProvider(InstrumentedFilesProvider.class); - if (instrumentedFilesProvider != null) { - testActionBuilder - .setInstrumentedFiles(instrumentedFilesProvider) - .setExtraEnv(instrumentedFilesProvider.getExtraEnv()); + TestActionBuilder testActionBuilder = + new TestActionBuilder(ruleContext) + .setInstrumentedFiles(findProvider(InstrumentedFilesProvider.class)); + + TestEnvironmentProvider environmentProvider = findProvider(TestEnvironmentProvider.class); + if (environmentProvider != null) { + testActionBuilder.setExtraEnv(environmentProvider.getEnvironment()); } - final TestParams testParams = testActionBuilder - .setFilesToRunProvider(filesToRunProvider) - .setExecutionRequirements(findProvider(ExecutionInfoProvider.class)) - .setShardCount(explicitShardCount) - .build(); + + final TestParams testParams = + testActionBuilder + .setFilesToRunProvider(filesToRunProvider) + .setExecutionRequirements(findProvider(ExecutionInfoProvider.class)) + .setShardCount(explicitShardCount) + .build(); final ImmutableList<String> testTags = ImmutableList.copyOf(ruleContext.getRule().getRuleTags()); return new TestProvider(testParams, testTags); @@ -233,9 +236,9 @@ public final class RuleConfiguredTargetBuilder { List<Label> actionListenerLabels = configuration.getActionListeners(); if (!actionListenerLabels.isEmpty() - && ruleContext.getRule().getAttributeDefinition(":action_listener") != null) { - ExtraActionsVisitor visitor = new ExtraActionsVisitor(ruleContext, - computeMnemonicsToExtraActionMap()); + && ruleContext.attributes().getAttributeDefinition(":action_listener") != null) { + ExtraActionsVisitor visitor = + new ExtraActionsVisitor(ruleContext, computeMnemonicsToExtraActionMap()); // The action list is modified within the body of the loop by the addExtraAction() call, // thus the copy @@ -446,7 +449,7 @@ public final class RuleConfiguredTargetBuilder { return result; } - result = NestedSetBuilder.<Artifact>stableOrder(); + result = NestedSetBuilder.stableOrder(); outputGroupBuilders.put(name, result); return result; } diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelIosTest.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelIosTest.java index 150041b880..c92e385647 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelIosTest.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/objc/BazelIosTest.java @@ -44,10 +44,11 @@ public final class BazelIosTest extends IosTest { NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(filesToBuild); - TestSupport testSupport = new TestSupport(ruleContext) - .registerTestRunnerActions() - .addRunfiles(runfilesBuilder, common.getObjcProvider()) - .addFilesToBuild(filesToBuildBuilder); + TestSupport testSupport = + new TestSupport(ruleContext) + .registerTestRunnerActions() + .addRunfiles(runfilesBuilder) + .addFilesToBuild(filesToBuildBuilder); Artifact executable = testSupport.generatedTestScript(); @@ -59,9 +60,10 @@ public final class BazelIosTest extends IosTest { .setFilesToBuild(filesToBuildBuilder.build()) .add(XcodeProvider.class, xcodeProvider) .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles)) - .add(ExecutionInfoProvider.class, + .add( + ExecutionInfoProvider.class, new ExecutionInfoProvider(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, ""))) - .addProviders(testSupport.getExtraProviders(common.getObjcProvider())) + .addProviders(testSupport.getExtraProviders()) .setRunfilesSupport(runfilesSupport, executable) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java index 9e757e2bdc..da2607a36f 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/BinaryLinkingTargetFactory.java @@ -35,6 +35,7 @@ import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; /** * Implementation for rules that link binaries. @@ -95,13 +96,14 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory return null; } - new CompilationSupport(ruleContext) - .registerJ2ObjcCompileAndArchiveActions(objcProvider) - .registerCompileAndArchiveActions(common) - .addXcodeSettings(xcodeProviderBuilder, common) - .registerLinkActions(objcProvider, getExtraLinkArgs(ruleContext), - ImmutableList.<Artifact>of()) - .validateAttributes(); + CompilationSupport compilationSupport = + new CompilationSupport(ruleContext) + .registerJ2ObjcCompileAndArchiveActions(objcProvider) + .registerCompileAndArchiveActions(common) + .addXcodeSettings(xcodeProviderBuilder, common) + .registerLinkActions( + objcProvider, getExtraLinkArgs(ruleContext), ImmutableList.<Artifact>of()) + .validateAttributes(); if (ruleContext.hasErrors()) { return null; @@ -157,7 +159,10 @@ abstract class BinaryLinkingTargetFactory implements RuleConfiguredTargetFactory RuleConfiguredTargetBuilder targetBuilder = ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) .addProvider(XcodeProvider.class, xcodeProvider) - .addProvider(ObjcProvider.class, objcProvider); + .addProvider(ObjcProvider.class, objcProvider) + .addProvider( + InstrumentedFilesProvider.class, + compilationSupport.getInstrumentedFilesProvider(common)); if (xcTestAppProvider.isPresent()) { // TODO(bazel-team): Stop exporting an XcTestAppProvider once objc_binary no longer creates an // application bundle. diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java index 1ea050a779..e20ae818ef 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/CompilationSupport.java @@ -41,6 +41,7 @@ import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.NON_ARC_S import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SRCS_TYPE; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.STRIP; import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SWIFT; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.intermediateArtifacts; import static java.nio.charset.StandardCharsets.ISO_8859_1; import com.google.common.annotations.VisibleForTesting; @@ -56,6 +57,7 @@ import com.google.common.collect.Sets; import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.actions.ParameterFile; +import com.google.devtools.build.lib.analysis.AnalysisEnvironment; import com.google.devtools.build.lib.analysis.PrerequisiteArtifacts; import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode; import com.google.devtools.build.lib.analysis.RuleContext; @@ -66,6 +68,7 @@ import com.google.devtools.build.lib.analysis.actions.FileWriteAction; import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction; import com.google.devtools.build.lib.analysis.actions.SpawnAction; import com.google.devtools.build.lib.collect.nestedset.NestedSet; +import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.packages.BuildType; import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction; import com.google.devtools.build.lib.packages.TargetUtils; @@ -75,7 +78,12 @@ import com.google.devtools.build.lib.rules.cpp.LinkerInputs; import com.google.devtools.build.lib.rules.java.J2ObjcConfiguration; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.XcodeProvider.Builder; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.InstrumentationSpec; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector.LocalMetadataCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.shell.ShellUtils; +import com.google.devtools.build.lib.util.FileTypeSet; import com.google.devtools.build.lib.vfs.FileSystemUtils; import com.google.devtools.build.lib.vfs.PathFragment; @@ -106,6 +114,21 @@ public final class CompilationSupport { static final ImmutableList<String> CLANG_COVERAGE_FLAGS = ImmutableList.of("-fprofile-arcs", "-ftest-coverage"); + /** + * Files which can be instrumented along with the attributes in which they may occur and the + * attributes along which they are propagated from dependencies (via + * {@link InstrumentedFilesProvider}). + */ + private static final InstrumentationSpec INSTRUMENTATION_SPEC = + new InstrumentationSpec( + FileTypeSet.of( + ObjcRuleClasses.NON_CPP_SOURCES, + ObjcRuleClasses.CPP_SOURCES, + ObjcRuleClasses.SWIFT_SOURCES, + HEADERS)) + .withSourceAttributes("srcs", "non_arc_srcs", "hdrs") + .withDependencyAttributes("deps", "data", "binary", "xctest_app"); + private static final String FRAMEWORK_SUFFIX = ".framework"; private static final Predicate<String> INCLUDE_DIR_OPTION_IN_COPTS = @@ -191,7 +214,7 @@ public final class CompilationSupport { if (ObjcRuleClasses.objcConfiguration(ruleContext).moduleMapsEnabled()) { moduleMap = Optional.of(intermediateArtifacts.moduleMap()); } else { - moduleMap = Optional.<CppModuleMap>absent(); + moduleMap = Optional.absent(); } registerCompileAndArchiveActions( common.getCompilationArtifacts().get(), @@ -543,6 +566,32 @@ public final class CompilationSupport { } /** + * Returns a provider that collects this target's instrumented sources as well as those of its + * dependencies. + * + * @param common common information about this rule and its dependencies + * @return an instrumented files provider + */ + public InstrumentedFilesProvider getInstrumentedFilesProvider(ObjcCommon common) { + ImmutableList.Builder<Artifact> oFiles = ImmutableList.builder(); + + if (common.getCompilationArtifacts().isPresent()) { + CompilationArtifacts artifacts = common.getCompilationArtifacts().get(); + IntermediateArtifacts intermediateArtifacts = intermediateArtifacts(ruleContext); + for (Artifact artifact : Iterables.concat(artifacts.getSrcs(), artifacts.getNonArcSrcs())) { + oFiles.add(intermediateArtifacts.objFile(artifact)); + } + } + + return InstrumentedFilesCollector.collect( + ruleContext, + INSTRUMENTATION_SPEC, + new ObjcCoverageMetadataCollector(), + oFiles.build(), + !TargetUtils.isTestRule(ruleContext.getTarget())); + } + + /** * Registers any actions necessary to link this rule and its dependencies. * * <p>Dsym bundle and breakpad files are generated if @@ -579,11 +628,11 @@ public final class CompilationSupport { * Registers an action that will generate a clang module map for this target, using the hdrs * attribute of this rule. */ - public CompilationSupport registerGenerateModuleMapAction( + CompilationSupport registerGenerateModuleMapAction( Optional<CompilationArtifacts> compilationArtifacts) { if (ObjcRuleClasses.objcConfiguration(ruleContext).moduleMapsEnabled()) { Iterable<Artifact> publicHeaders = attributes.hdrs(); - Iterable<Artifact> privateHeaders = ImmutableList.<Artifact>of(); + Iterable<Artifact> privateHeaders = ImmutableList.of(); if (compilationArtifacts.isPresent()) { CompilationArtifacts artifacts = compilationArtifacts.get(); publicHeaders = Iterables.concat(publicHeaders, artifacts.getAdditionalHdrs()); @@ -864,7 +913,7 @@ public final class CompilationSupport { if (ObjcRuleClasses.objcConfiguration(ruleContext).moduleMapsEnabled()) { moduleMap = Optional.of(ObjcRuleClasses.intermediateArtifacts(ruleContext).moduleMap()); } else { - moduleMap = Optional.<CppModuleMap>absent(); + moduleMap = Optional.absent(); } registerCompileAndArchiveActions( compilationArtifact, @@ -1035,20 +1084,20 @@ public final class CompilationSupport { .replaceName(linkedBinary.getFilename()) .relativeTo(dsymOutputDir); - StringBuilder unzipDsymCommand = new StringBuilder(); - unzipDsymCommand - .append( - String.format( - "unzip -p %s %s > %s", - dsymBundle.getExecPathString(), - dsymPlistZipEntry, - dsymPlist.getExecPathString())) - .append( - String.format( - " && unzip -p %s %s > %s", - dsymBundle.getExecPathString(), - debugSymbolFileZipEntry, - debugSymbolFile.getExecPathString())); + StringBuilder unzipDsymCommand = + new StringBuilder() + .append( + String.format( + "unzip -p %s %s > %s", + dsymBundle.getExecPathString(), + dsymPlistZipEntry, + dsymPlist.getExecPathString())) + .append( + String.format( + " && unzip -p %s %s > %s", + dsymBundle.getExecPathString(), + debugSymbolFileZipEntry, + debugSymbolFile.getExecPathString())); ruleContext.registerAction( new SpawnAction.Builder() @@ -1092,4 +1141,24 @@ public final class CompilationSupport { private String getModuleName() { return ruleContext.getLabel().getName(); } + + /** + * Collector that, given a list of output artifacts, finds and registers coverage notes metadata + * for any compilation action. + */ + private static class ObjcCoverageMetadataCollector extends LocalMetadataCollector { + + @Override + public void collectMetadataArtifacts( + Iterable<Artifact> artifacts, + AnalysisEnvironment analysisEnvironment, + NestedSetBuilder<Artifact> metadataFilesBuilder) { + for (Artifact artifact : artifacts) { + Action action = analysisEnvironment.getLocalGeneratingAction(artifact); + if (action.getMnemonic().equals("ObjcCompile")) { + addOutputs(metadataFilesBuilder, action, ObjcRuleClasses.COVERAGE_NOTES); + } + } + } + } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java index dd034b7f0c..b86e54fbe4 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ExperimentalIosTest.java @@ -25,6 +25,7 @@ import com.google.devtools.build.lib.analysis.RunfilesSupport; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.test.ExecutionInfoProvider; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; /** * Implementation for {@code experimental_ios_test} rule in Bazel. @@ -43,10 +44,11 @@ public final class ExperimentalIosTest extends IosTest { NestedSetBuilder<Artifact> filesToBuildBuilder = NestedSetBuilder.<Artifact>stableOrder() .addTransitive(filesToBuild); - TestSupport testSupport = new TestSupport(ruleContext) - .registerTestRunnerActions() - .addRunfiles(runfilesBuilder, common.getObjcProvider()) - .addFilesToBuild(filesToBuildBuilder); + TestSupport testSupport = + new TestSupport(ruleContext) + .registerTestRunnerActions() + .addRunfiles(runfilesBuilder) + .addFilesToBuild(filesToBuildBuilder); Artifact executable = testSupport.generatedTestScript(); @@ -58,9 +60,13 @@ public final class ExperimentalIosTest extends IosTest { .setFilesToBuild(filesToBuildBuilder.build()) .add(XcodeProvider.class, xcodeProvider) .add(RunfilesProvider.class, RunfilesProvider.simple(runfiles)) - .add(ExecutionInfoProvider.class, + .add( + ExecutionInfoProvider.class, new ExecutionInfoProvider(ImmutableMap.of(ExecutionRequirements.REQUIRES_DARWIN, ""))) - .addProviders(testSupport.getExtraProviders(common.getObjcProvider())) + .addProvider( + InstrumentedFilesProvider.class, + new CompilationSupport(ruleContext).getInstrumentedFilesProvider(common)) + .addProviders(testSupport.getExtraProviders()) .setRunfilesSupport(runfilesSupport, executable) .build(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java index c2c19d5d6b..8018218436 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcCommon.java @@ -27,14 +27,12 @@ import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_DI import static com.google.devtools.build.lib.rules.objc.ObjcProvider.FRAMEWORK_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_CPP; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.Flag.USES_SWIFT; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GCNO; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_DIR; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.IMPORTED_LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE_SYSTEM; -import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INSTRUMENTED_SOURCE; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LINKED_BINARY; import static com.google.devtools.build.lib.rules.objc.ObjcProvider.MODULE_MAP; @@ -68,7 +66,6 @@ import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.cpp.CppModuleMap; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; -import com.google.devtools.build.lib.util.RegexFilter; import com.google.devtools.build.lib.vfs.PathFragment; import java.util.ArrayList; @@ -227,7 +224,7 @@ public final class ObjcCommon { /** * Returns whether this target uses language features that require clang modules, such as - * @import. + * {@literal @}import. */ public boolean enableModules() { return ruleContext.attributes().has("enable_modules", Type.BOOLEAN) @@ -518,17 +515,6 @@ public final class ObjcCommon { .addAll(HEADER, artifacts.getAdditionalHdrs()) .addAll(LIBRARY, artifacts.getArchive().asSet()) .addAll(SOURCE, allSources); - BuildConfiguration configuration = context.getConfiguration(); - RegexFilter filter = configuration.getInstrumentationFilter(); - if (configuration.isCodeCoverageEnabled() - && filter.isIncluded(context.getLabel().toString())) { - for (Artifact source : allSources) { - if (ObjcRuleClasses.isInstrumentable(source)) { - objcProvider.add(INSTRUMENTED_SOURCE, source); - objcProvider.add(GCNO, intermediateArtifacts.gcnoFile(source)); - } - } - } boolean usesCpp = false; boolean usesSwift = false; @@ -607,22 +593,12 @@ public final class ObjcCommon { * compilation information has no sources. */ public Optional<Artifact> getCompiledArchive() { - for (CompilationArtifacts justCompilationArtifacts : compilationArtifacts.asSet()) { - return justCompilationArtifacts.getArchive(); + if (compilationArtifacts.isPresent()) { + return compilationArtifacts.get().getArchive(); } return Optional.absent(); } - /** - * Reports any known errors to the {@link RuleContext}. This should be called exactly once for - * a target. - */ - public void reportErrors() { - - // TODO(bazel-team): Report errors for rules that are not actually useful (i.e. objc_library - // without sources or resources, empty objc_bundles) - } - static ImmutableList<PathFragment> userHeaderSearchPaths(BuildConfiguration configuration) { return ImmutableList.of( new PathFragment("."), @@ -734,4 +710,5 @@ public final class ObjcCommon { } return errors; } + } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java index 048dce7ec8..f76cbd8a05 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcLibrary.java @@ -27,6 +27,7 @@ import com.google.devtools.build.lib.rules.cpp.CcLinkParamsProvider; import com.google.devtools.build.lib.rules.cpp.CppCompilationContext; import com.google.devtools.build.lib.rules.objc.ObjcCommon.CompilationAttributes; import com.google.devtools.build.lib.rules.objc.ObjcCommon.ResourceAttributes; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import com.google.devtools.build.lib.syntax.Type; /** @@ -93,10 +94,11 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { NestedSetBuilder<Artifact> filesToBuild = NestedSetBuilder.<Artifact>stableOrder() .addAll(common.getCompiledArchive().asSet()); - new CompilationSupport(ruleContext) - .registerCompileAndArchiveActions(common) - .addXcodeSettings(xcodeProviderBuilder, common) - .validateAttributes(); + CompilationSupport compilationSupport = + new CompilationSupport(ruleContext) + .registerCompileAndArchiveActions(common) + .addXcodeSettings(xcodeProviderBuilder, common) + .validateAttributes(); new ResourceSupport(ruleContext) .validateAttributes() @@ -117,6 +119,9 @@ public class ObjcLibrary implements RuleConfiguredTargetFactory { .addProvider(J2ObjcSrcsProvider.class, J2ObjcSrcsProvider.buildFrom(ruleContext)) .addProvider( J2ObjcMappingFileProvider.class, ObjcRuleClasses.j2ObjcMappingFileProvider(ruleContext)) + .addProvider( + InstrumentedFilesProvider.class, + compilationSupport.getInstrumentedFilesProvider(common)) .build(); } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java index bbee7c675c..5e3e5204e8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcProvider.java @@ -88,18 +88,6 @@ public final class ObjcProvider implements TransitiveInfoProvider { public static final Key<Artifact> SOURCE = new Key<>(STABLE_ORDER); /** - * Contains all coverage instrumented source files. - */ - public static final Key<Artifact> INSTRUMENTED_SOURCE = new Key<>(STABLE_ORDER); - - /** - * Contains all .gcno files one for every source file if in coverage mode. - * It contains information to reconstruct the basic block graphs and assign source line numbers - * to blocks. - */ - public static final Key<Artifact> GCNO = new Key<>(STABLE_ORDER); - - /** * Include search paths specified with {@code -I} on the command line. Also known as header search * paths (and distinct from <em>user</em> header search paths). */ @@ -384,16 +372,6 @@ public final class ObjcProvider implements TransitiveInfoProvider { return this; } - /** - * Add element, but don't propagate dependers on this ObjcProvider. These elements will be - * exposed to {@link #get(Key)} calls, but not to any ObjcProviders which add this provider to - * themselves. - */ - public <E> Builder addWithoutPropagating(Key<E> key, E toAdd) { - uncheckedAddAll(key, ImmutableList.of(toAdd), false); - return this; - } - public ObjcProvider build() { ImmutableMap.Builder<Key<?>, NestedSet<?>> propagated = new ImmutableMap.Builder<>(); for (Map.Entry<Key<?>, NestedSetBuilder<?>> typeEntry : items.entrySet()) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java index 07f3ad45df..05bdd6c1d8 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcRuleClasses.java @@ -331,7 +331,7 @@ public class ObjcRuleClasses { */ static final FileType CPP_SOURCES = FileType.of(".cc", ".cpp", ".mm", ".cxx", ".C"); - private static final FileType NON_CPP_SOURCES = FileType.of(".m", ".c"); + static final FileType NON_CPP_SOURCES = FileType.of(".m", ".c"); static final FileType ASSEMBLY_SOURCES = FileType.of(".s", ".S", ".asm"); @@ -366,6 +366,12 @@ public class ObjcRuleClasses { static final FileTypeSet HDRS_TYPE = FileTypeSet.ANY_FILE; /** + * Coverage note files which contain information to reconstruct the basic block graphs and assign + * source line numbers to blocks. + */ + static final FileType COVERAGE_NOTES = FileType.of(".gcno"); + + /** * Common attributes for {@code objc_*} rules that allow the definition of resources such as * storyboards. These resources are used during compilation of the declaring rule as well as when * bundling a dependent bundle (application, extension, etc.). diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java index b6b534025d..a3ea622d25 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingSupport.java @@ -402,10 +402,8 @@ public final class ReleaseBundlingSupport { // want to link anything since that stuff is shared automatically by way of the // -bundle_loader linker flag. ObjcProvider partialObjcProvider = new ObjcProvider.Builder() - .addTransitiveAndPropagate(ObjcProvider.GCNO, objcProvider) .addTransitiveAndPropagate(ObjcProvider.HEADER, objcProvider) .addTransitiveAndPropagate(ObjcProvider.INCLUDE, objcProvider) - .addTransitiveAndPropagate(ObjcProvider.INSTRUMENTED_SOURCE, objcProvider) .addTransitiveAndPropagate(ObjcProvider.SDK_DYLIB, objcProvider) .addTransitiveAndPropagate(ObjcProvider.SDK_FRAMEWORK, objcProvider) .addTransitiveAndPropagate(ObjcProvider.SOURCE, objcProvider) diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java index 54aeb675f3..57c488ea65 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ReleaseBundlingTargetFactory.java @@ -23,6 +23,8 @@ import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.LinkedBinary; import com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.SplitArchTransition.ConfigurationDistinguisher; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesCollector; +import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; import javax.annotation.Nullable; @@ -89,7 +91,10 @@ public abstract class ReleaseBundlingTargetFactory implements RuleConfiguredTarg RuleConfiguredTargetBuilder targetBuilder = ObjcRuleClasses.ruleConfiguredTarget(ruleContext, filesToBuild.build()) .addProvider(XcTestAppProvider.class, releaseBundlingSupport.xcTestAppProvider()) - .addProvider(XcodeProvider.class, xcodeProviderBuilder.build()); + .addProvider(XcodeProvider.class, xcodeProviderBuilder.build()) + .addProvider( + InstrumentedFilesProvider.class, + InstrumentedFilesCollector.forward(ruleContext, "binary")); ObjcProvider exposedObjcProvider = exposedObjcProvider(ruleContext); if (exposedObjcProvider != null) { diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java index c882f0581e..b920e4fc18 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/TestSupport.java @@ -32,9 +32,7 @@ import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction; import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; -import com.google.devtools.build.lib.rules.objc.ObjcProvider.Key; -import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider; -import com.google.devtools.build.lib.rules.test.InstrumentedFilesProviderImpl; +import com.google.devtools.build.lib.rules.test.TestEnvironmentProvider; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileType; @@ -197,12 +195,8 @@ public class TestSupport { /** * Adds all files needed to run this test to the passed Runfiles builder. - * - * @param objcProvider common information about this rule's attributes and its dependencies - * @throws InterruptedException */ - public TestSupport addRunfiles(Builder runfilesBuilder, ObjcProvider objcProvider) - throws InterruptedException { + public TestSupport addRunfiles(Builder runfilesBuilder) throws InterruptedException { runfilesBuilder .addArtifact(testIpa()) .addArtifacts(xctestIpa().asSet()) @@ -218,67 +212,28 @@ public class TestSupport { runfilesBuilder.addTransitiveArtifacts(labDeviceRunfiles()); } - if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - runfilesBuilder - .addTransitiveArtifacts(objcProvider.get(ObjcProvider.SOURCE)) - .addTransitiveArtifacts(gcnoFiles(objcProvider)); - } return this; } /** * Returns any additional providers that need to be exported to the rule context to the passed * builder. - * - * @param objcProvider common information about this rule's attributes and its dependencies - */ - public Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> - getExtraProviders(ObjcProvider objcProvider) { - return ImmutableMap.<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider>of( - InstrumentedFilesProvider.class, - new InstrumentedFilesProviderImpl( - instrumentedFiles(objcProvider), gcnoFiles(objcProvider), gcovEnv())); - } - - /** - * Returns a map of extra environment variable names to their values used to point to gcov binary, - * which should be added to the test action environment, if coverage is enabled. */ - private Map<String, String> gcovEnv() { + public Map<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider> getExtraProviders() { if (ruleContext.getConfiguration().isCodeCoverageEnabled()) { - return ImmutableMap.of("COVERAGE_GCOV_PATH", - ruleContext.getHostPrerequisiteArtifact(":gcov").getExecPathString()); + return ImmutableMap.<Class<? extends TransitiveInfoProvider>, TransitiveInfoProvider>of( + TestEnvironmentProvider.class, new TestEnvironmentProvider(gcovEnv())); } return ImmutableMap.of(); } /** - * Returns all GCC coverage notes files available for computing coverage. + * Returns a map of extra environment variable names to their values used to point to gcov binary, + * which should be added to the test action environment, if coverage is enabled. */ - private NestedSet<Artifact> gcnoFiles(ObjcProvider objcProvider) { - return filesWithXcTestApp(ObjcProvider.GCNO, objcProvider); - } - - /** - * Returns all source files from the test (and if present xctest app) which have been - * instrumented for code coverage. - */ - private NestedSet<Artifact> instrumentedFiles(ObjcProvider objcProvider) { - return filesWithXcTestApp(ObjcProvider.INSTRUMENTED_SOURCE, objcProvider); - } - - private NestedSet<Artifact> filesWithXcTestApp(Key<Artifact> key, ObjcProvider objcProvider) { - NestedSet<Artifact> underlying = objcProvider.get(key); - XcTestAppProvider provider = ruleContext.getPrerequisite( - IosTest.XCTEST_APP, Mode.TARGET, XcTestAppProvider.class); - if (provider == null) { - return underlying; - } - - return NestedSetBuilder.<Artifact>stableOrder() - .addTransitive(underlying) - .addTransitive(provider.getObjcProvider().get(key)) - .build(); + private ImmutableMap<String, String> gcovEnv() { + return ImmutableMap.of( + "COVERAGE_GCOV_PATH", ruleContext.getHostPrerequisiteArtifact(":gcov").getExecPathString()); } /** @@ -307,7 +262,6 @@ public class TestSupport { /** * Adds files which must be built in order to run this test to builder. - * @throws InterruptedException */ public TestSupport addFilesToBuild(NestedSetBuilder<Artifact> builder) throws InterruptedException { 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 2266b54d1d..84b13a96fe 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 @@ -15,7 +15,6 @@ package com.google.devtools.build.lib.rules.test; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Action; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.AnalysisEnvironment; @@ -35,15 +34,32 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import javax.annotation.Nullable; - /** * A helper class for collecting instrumented files and metadata for a target. */ public final class InstrumentedFilesCollector { - public static InstrumentedFilesProvider collect(RuleContext ruleContext, InstrumentationSpec spec, - @Nullable LocalMetadataCollector localMetadataCollector, - @Nullable Iterable<Artifact> rootFiles) { + + /** + * Forwards any instrumented files from the given target's dependencies (as defined in + * {@code dependencyAttributes}) for further export. No files from this target are considered + * instrumented. + * + * @return instrumented file provider of all dependencies in {@code dependencyAttributes} + */ + public static InstrumentedFilesProvider forward( + RuleContext ruleContext, String... dependencyAttributes) { + return collect( + ruleContext, + new InstrumentationSpec(FileTypeSet.NO_FILE).withDependencyAttributes(dependencyAttributes), + null, + null); + } + + public static InstrumentedFilesProvider collect( + RuleContext ruleContext, + InstrumentationSpec spec, + LocalMetadataCollector localMetadataCollector, + Iterable<Artifact> rootFiles) { return collect(ruleContext, spec, localMetadataCollector, rootFiles, false); } @@ -53,9 +69,12 @@ public final class InstrumentedFilesCollector { * configured target, and creates baseline coverage actions for the transitive closure of source * files (if <code>withBaselineCoverage</code> is true). */ - public static InstrumentedFilesProvider collect(RuleContext ruleContext, - InstrumentationSpec spec, @Nullable LocalMetadataCollector localMetadataCollector, - @Nullable Iterable<Artifact> rootFiles, boolean withBaselineCoverage) { + public static InstrumentedFilesProvider collect( + RuleContext ruleContext, + InstrumentationSpec spec, + LocalMetadataCollector localMetadataCollector, + Iterable<Artifact> rootFiles, + boolean withBaselineCoverage) { Preconditions.checkNotNull(ruleContext); Preconditions.checkNotNull(spec); @@ -118,11 +137,11 @@ public final class InstrumentedFilesCollector { // Create one baseline coverage action per target, but for the transitive closure of files. NestedSet<Artifact> baselineCoverageArtifacts = BaselineCoverageAction.create(ruleContext, baselineCoverageFiles); - return new InstrumentedFilesProviderImpl(instrumentedFilesBuilder.build(), + return new InstrumentedFilesProviderImpl( + instrumentedFilesBuilder.build(), metadataFilesBuilder.build(), baselineCoverageFiles, - baselineCoverageArtifacts, - ImmutableMap.<String, String>of()); + baselineCoverageArtifacts); } /** diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProvider.java b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProvider.java index 24017da115..0a2be739c9 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProvider.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProvider.java @@ -18,8 +18,6 @@ import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; import com.google.devtools.build.lib.collect.nestedset.NestedSet; -import java.util.Map; - /** * A provider of instrumented file sources and instrumentation metadata. */ @@ -51,9 +49,4 @@ public interface InstrumentedFilesProvider extends TransitiveInfoProvider { // particular because baseline coverage is language-specific (it requires a parser for the // specific language), and we don't want to depend on all language parsers from any single rule. NestedSet<Artifact> getBaselineCoverageArtifacts(); - - /** - * Returns environment variables which should be set for coverage to function. - */ - Map<String, String> getExtraEnv(); } diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProviderImpl.java b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProviderImpl.java index a56e8d89e3..439c4e3aa3 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProviderImpl.java +++ b/src/main/java/com/google/devtools/build/lib/rules/test/InstrumentedFilesProviderImpl.java @@ -13,47 +13,36 @@ // limitations under the License. package com.google.devtools.build.lib.rules.test; -import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.Artifact; import com.google.devtools.build.lib.collect.nestedset.NestedSet; import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; import com.google.devtools.build.lib.collect.nestedset.Order; -import java.util.Map; - /** * An implementation class for the InstrumentedFilesProvider interface. */ public final class InstrumentedFilesProviderImpl implements InstrumentedFilesProvider { - public static final InstrumentedFilesProvider EMPTY = new InstrumentedFilesProviderImpl( - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), - ImmutableMap.<String, String>of()); + public static final InstrumentedFilesProvider EMPTY = + new InstrumentedFilesProviderImpl( + NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), + NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), + NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), + NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)); private final NestedSet<Artifact> instrumentedFiles; private final NestedSet<Artifact> instrumentationMetadataFiles; private final NestedSet<Artifact> baselineCoverageFiles; private final NestedSet<Artifact> baselineCoverageArtifacts; - private final ImmutableMap<String, String> extraEnv; - public InstrumentedFilesProviderImpl(NestedSet<Artifact> instrumentedFiles, + public InstrumentedFilesProviderImpl( + NestedSet<Artifact> instrumentedFiles, NestedSet<Artifact> instrumentationMetadataFiles, NestedSet<Artifact> baselineCoverageFiles, - NestedSet<Artifact> baselineCoverageArtifacts, Map<String, String> extraEnv) { + NestedSet<Artifact> baselineCoverageArtifacts) { this.instrumentedFiles = instrumentedFiles; this.instrumentationMetadataFiles = instrumentationMetadataFiles; this.baselineCoverageFiles = baselineCoverageFiles; this.baselineCoverageArtifacts = baselineCoverageArtifacts; - this.extraEnv = ImmutableMap.copyOf(extraEnv); - } - - public InstrumentedFilesProviderImpl(NestedSet<Artifact> instrumentedFiles, - NestedSet<Artifact> instrumentationMetadataFiles, Map<String, String> extraEnv) { - this(instrumentedFiles, instrumentationMetadataFiles, - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), - NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER), extraEnv); } @Override @@ -75,9 +64,4 @@ public final class InstrumentedFilesProviderImpl implements InstrumentedFilesPro public NestedSet<Artifact> getBaselineCoverageArtifacts() { return baselineCoverageArtifacts; } - - @Override - public Map<String, String> getExtraEnv() { - return extraEnv; - } } diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestEnvironmentProvider.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestEnvironmentProvider.java new file mode 100644 index 0000000000..fa98fc6f0a --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestEnvironmentProvider.java @@ -0,0 +1,43 @@ +// Copyright 2015 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 com.google.devtools.build.lib.rules.test; + +import com.google.common.collect.ImmutableMap; +import com.google.devtools.build.lib.analysis.TransitiveInfoProvider; +import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; + +import java.util.Map; + +/** + * Provider containing any additional environment variables for use in the test action. + */ +@Immutable +public final class TestEnvironmentProvider implements TransitiveInfoProvider { + private final ImmutableMap<String, String> environment; + + /** + * Constructs a new provider with the given variable name to variable value mapping. + */ + public TestEnvironmentProvider(ImmutableMap<String, String> environment) { + this.environment = environment; + } + + /** + * Returns environment variables which should be set on the test action. + */ + public Map<String, String> getEnvironment() { + return environment; + } +} |