| Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2014 The Bazel Authors. All rights reserved. |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package com.google.devtools.build.lib.analysis; |
| 16 | |
| tomlu | a155b53 | 2017-11-08 20:12:47 +0100 | [diff] [blame] | 17 | import static com.google.common.base.Preconditions.checkNotNull; |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 18 | |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 19 | import com.google.common.annotations.VisibleForTesting; |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 20 | import com.google.devtools.build.lib.actions.Artifact; |
| ulfjack | ab21d18 | 2017-08-10 15:36:14 +0200 | [diff] [blame] | 21 | import com.google.devtools.build.lib.analysis.test.TestProvider; |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 22 | import com.google.devtools.build.lib.cmdline.Label; |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 23 | import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| 24 | import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder; |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 25 | import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 26 | import com.google.devtools.build.lib.profiler.AutoProfiler; |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 27 | import com.google.devtools.build.lib.skyframe.AspectValue; |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 28 | import com.google.devtools.build.lib.util.RegexFilter; |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 29 | import java.util.logging.Logger; |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 30 | import javax.annotation.Nullable; |
| 31 | |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 32 | /** |
| 33 | * A small static class containing utility methods for handling the inclusion of |
| 34 | * extra top-level artifacts into the build. |
| 35 | */ |
| 36 | public final class TopLevelArtifactHelper { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 37 | private static Logger logger = Logger.getLogger(TopLevelArtifactHelper.class.getName()); |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 38 | |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 39 | /** Set of {@link Artifact}s in an output group. */ |
| 40 | @Immutable |
| 41 | public static final class ArtifactsInOutputGroup { |
| 42 | private final String outputGroup; |
| 43 | private final boolean important; |
| 44 | private final NestedSet<Artifact> artifacts; |
| 45 | |
| 46 | private ArtifactsInOutputGroup( |
| 47 | String outputGroup, boolean important, NestedSet<Artifact> artifacts) { |
| 48 | this.outputGroup = checkNotNull(outputGroup); |
| 49 | this.important = important; |
| 50 | this.artifacts = checkNotNull(artifacts); |
| 51 | } |
| 52 | |
| 53 | public String getOutputGroup() { |
| 54 | return outputGroup; |
| 55 | } |
| 56 | |
| 57 | public NestedSet<Artifact> getArtifacts() { |
| 58 | return artifacts; |
| 59 | } |
| 60 | |
| 61 | /** Returns {@code true} if the user should know about this output group. */ |
| 62 | public boolean areImportant() { |
| 63 | return important; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | /** |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 68 | * The set of artifacts to build. |
| 69 | * |
| Lukacs Berki | 8af211f | 2015-02-19 15:42:57 +0000 | [diff] [blame] | 70 | * <p>There are two kinds: the ones that the user cares about (e.g. files to build) and the ones |
| hlopko | e1d9b58 | 2018-07-23 03:06:32 -0700 | [diff] [blame] | 71 | * they don't (e.g. baseline coverage artifacts). The latter type doesn't get reported on various |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 72 | * outputs, e.g. on the console output listing the output artifacts of targets on the command |
| Lukacs Berki | 8af211f | 2015-02-19 15:42:57 +0000 | [diff] [blame] | 73 | * line. |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 74 | */ |
| 75 | @Immutable |
| 76 | public static final class ArtifactsToBuild { |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 77 | private NestedSet<ArtifactsInOutputGroup> artifacts; |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 78 | |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 79 | private ArtifactsToBuild(NestedSet<ArtifactsInOutputGroup> artifacts) { |
| 80 | this.artifacts = checkNotNull(artifacts); |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | /** |
| 84 | * Returns the artifacts that the user should know about. |
| 85 | */ |
| 86 | public NestedSet<Artifact> getImportantArtifacts() { |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 87 | NestedSetBuilder<Artifact> builder = new NestedSetBuilder<>(artifacts.getOrder()); |
| 88 | for (ArtifactsInOutputGroup artifactsInOutputGroup : artifacts) { |
| 89 | if (artifactsInOutputGroup.areImportant()) { |
| 90 | builder.addTransitive(artifactsInOutputGroup.getArtifacts()); |
| 91 | } |
| 92 | } |
| 93 | return builder.build(); |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Returns the actual set of artifacts that need to be built. |
| 98 | */ |
| 99 | public NestedSet<Artifact> getAllArtifacts() { |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 100 | NestedSetBuilder<Artifact> builder = new NestedSetBuilder<>(artifacts.getOrder()); |
| 101 | for (ArtifactsInOutputGroup artifactsInOutputGroup : artifacts) { |
| 102 | builder.addTransitive(artifactsInOutputGroup.getArtifacts()); |
| 103 | } |
| 104 | return builder.build(); |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Returns the set of all {@link Artifact}s grouped by their corresponding output group. |
| 109 | * |
| 110 | * <p>If an {@link Artifact} belongs to two or more output groups, it appears once in each |
| 111 | * output group. |
| 112 | */ |
| 113 | public NestedSet<ArtifactsInOutputGroup> getAllArtifactsByOutputGroup() { |
| 114 | return artifacts; |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 115 | } |
| 116 | } |
| 117 | |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 118 | private TopLevelArtifactHelper() { |
| 119 | // Prevent instantiation. |
| 120 | } |
| 121 | |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 122 | @VisibleForTesting |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 123 | public static ArtifactsToOwnerLabels makeTopLevelArtifactsToOwnerLabels( |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 124 | AnalysisResult analysisResult, Iterable<AspectValue> aspects) { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 125 | try (AutoProfiler ignored = AutoProfiler.logged("assigning owner labels", logger, 10)) { |
| 126 | |
| 127 | ArtifactsToOwnerLabels.Builder artifactsToOwnerLabelsBuilder = |
| 128 | analysisResult.getTopLevelArtifactsToOwnerLabels().toBuilder(); |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 129 | TopLevelArtifactContext artifactContext = analysisResult.getTopLevelContext(); |
| 130 | for (ConfiguredTarget target : analysisResult.getTargetsToBuild()) { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 131 | addArtifactsWithOwnerLabel( |
| 132 | getAllArtifactsToBuild(target, artifactContext).getAllArtifacts(), |
| 133 | null, |
| 134 | target.getLabel(), |
| 135 | artifactsToOwnerLabelsBuilder); |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 136 | } |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 137 | for (AspectValue aspect : aspects) { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 138 | addArtifactsWithOwnerLabel( |
| 139 | getAllArtifactsToBuild(aspect, artifactContext).getAllArtifacts(), |
| 140 | null, |
| 141 | aspect.getLabel(), |
| 142 | artifactsToOwnerLabelsBuilder); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 143 | } |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 144 | if (analysisResult.getTargetsToTest() != null) { |
| 145 | for (ConfiguredTarget target : analysisResult.getTargetsToTest()) { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 146 | addArtifactsWithOwnerLabel( |
| 147 | TestProvider.getTestStatusArtifacts(target), |
| 148 | null, |
| 149 | target.getLabel(), |
| 150 | artifactsToOwnerLabelsBuilder); |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 151 | } |
| 152 | } |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 153 | // TODO(dslomov): Artifacts to test from aspects? |
| 154 | return artifactsToOwnerLabelsBuilder.build(); |
| 155 | } |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 156 | } |
| 157 | |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 158 | static void addArtifactsWithOwnerLabel( |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 159 | Iterable<Artifact> artifacts, |
| 160 | @Nullable RegexFilter filter, |
| 161 | Label ownerLabel, |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 162 | ArtifactsToOwnerLabels.Builder artifactsToOwnerLabelsBuilder) { |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 163 | for (Artifact artifact : artifacts) { |
| 164 | if (filter == null || filter.isIncluded(artifact.getOwnerLabel().toString())) { |
| janakr | ccb7456 | 2018-07-30 10:56:57 -0700 | [diff] [blame] | 165 | artifactsToOwnerLabelsBuilder.addArtifact(artifact, ownerLabel); |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 166 | } |
| 167 | } |
| 168 | } |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 169 | |
| 170 | /** |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 171 | * Returns all artifacts to build if this target is requested as a top-level target. The resulting |
| 172 | * set includes the temps and either the files to compile, if |
| Lukacs Berki | c1f894e | 2015-02-17 13:00:26 +0000 | [diff] [blame] | 173 | * {@code context.compileOnly() == true}, or the files to run. |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 174 | * |
| 175 | * <p>Calls to this method should generally return quickly; however, the runfiles computation can |
| 176 | * be lazy, in which case it can be expensive on the first call. Subsequent calls may or may not |
| 177 | * return the same {@code Iterable} instance. |
| 178 | */ |
| Lukacs Berki | c340a07 | 2015-02-18 13:16:53 +0000 | [diff] [blame] | 179 | public static ArtifactsToBuild getAllArtifactsToBuild(TransitiveInfoCollection target, |
| Lukacs Berki | c1f894e | 2015-02-17 13:00:26 +0000 | [diff] [blame] | 180 | TopLevelArtifactContext context) { |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 181 | return getAllArtifactsToBuild( |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 182 | OutputGroupInfo.get(target), |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 183 | target.getProvider(FileProvider.class), |
| 184 | context |
| 185 | ); |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 186 | } |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 187 | |
| 188 | public static ArtifactsToBuild getAllArtifactsToBuild( |
| 189 | AspectValue aspectValue, TopLevelArtifactContext context) { |
| Dmitry Lomov | b487ac6 | 2015-11-09 13:09:12 +0000 | [diff] [blame] | 190 | ConfiguredAspect configuredAspect = aspectValue.getConfiguredAspect(); |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 191 | return getAllArtifactsToBuild( |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 192 | OutputGroupInfo.get(configuredAspect), |
| Dmitry Lomov | b487ac6 | 2015-11-09 13:09:12 +0000 | [diff] [blame] | 193 | configuredAspect.getProvider(FileProvider.class), |
| 194 | context); |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 195 | } |
| 196 | |
| janakr | 75bc18a | 2018-07-13 00:52:17 -0700 | [diff] [blame] | 197 | static ArtifactsToBuild getAllArtifactsToBuild( |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 198 | @Nullable OutputGroupInfo outputGroupInfo, |
| Googler | 3ca7b78 | 2015-10-12 15:44:09 +0000 | [diff] [blame] | 199 | @Nullable FileProvider fileProvider, |
| 200 | TopLevelArtifactContext context) { |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 201 | NestedSetBuilder<ArtifactsInOutputGroup> allBuilder = NestedSetBuilder.stableOrder(); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 202 | |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 203 | for (String outputGroup : context.outputGroups()) { |
| 204 | NestedSetBuilder<Artifact> results = NestedSetBuilder.stableOrder(); |
| 205 | |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 206 | if (outputGroup.equals(OutputGroupInfo.DEFAULT) && fileProvider != null) { |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 207 | results.addTransitive(fileProvider.getFilesToBuild()); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 208 | } |
| 209 | |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 210 | if (outputGroupInfo != null) { |
| 211 | results.addTransitive(outputGroupInfo.getOutputGroup(outputGroup)); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 212 | } |
| 213 | |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 214 | // Ignore output groups that have no artifacts. |
| 215 | if (results.isEmpty()) { |
| 216 | continue; |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 217 | } |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 218 | |
| 219 | boolean isImportantGroup = |
| dslomov | 69c45f8 | 2017-12-14 11:15:43 -0500 | [diff] [blame] | 220 | !outputGroup.startsWith(OutputGroupInfo.HIDDEN_OUTPUT_GROUP_PREFIX); |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 221 | |
| 222 | ArtifactsInOutputGroup artifacts = |
| 223 | new ArtifactsInOutputGroup(outputGroup, isImportantGroup, results.build()); |
| 224 | |
| 225 | allBuilder.add(artifacts); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 226 | } |
| 227 | |
| Jakob Buchgraber | fb64609 | 2017-02-27 18:53:25 +0000 | [diff] [blame] | 228 | return new ArtifactsToBuild(allBuilder.build()); |
| Dmitry Lomov | e2033b1 | 2015-08-19 16:57:49 +0000 | [diff] [blame] | 229 | } |
| Han-Wen Nienhuys | d08b27f | 2015-02-25 16:45:20 +0100 | [diff] [blame] | 230 | } |