aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/TopLevelArtifactHelper.java
blob: 3c025f40a1deb81d7f9714e7abcbd7080c5441b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright 2014 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.analysis;

import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
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.rules.test.TestProvider;

/**
 * A small static class containing utility methods for handling the inclusion of
 * extra top-level artifacts into the build.
 */
public final class TopLevelArtifactHelper {

  private TopLevelArtifactHelper() {
    // Prevent instantiation.
  }

  /** Returns command-specific artifacts which may exist for a given target and build command. */
  public static final Iterable<Artifact> getCommandArtifacts(TransitiveInfoCollection target,
      String buildCommand) {
    TopLevelArtifactProvider provider = target.getProvider(TopLevelArtifactProvider.class);
    if (provider != null
        && provider.getCommandsForExtraArtifacts().contains(buildCommand.toLowerCase())) {
      return provider.getArtifactsForCommand();
    } else {
      return ImmutableList.of();
    }
  }

  /**
   * Utility function to form a list of all test output Artifacts of the given targets to test.
   */
  public static ImmutableCollection<Artifact> getAllArtifactsToTest(
      Iterable<? extends TransitiveInfoCollection> targets) {
    if (targets == null) {
      return ImmutableList.of();
    }
    ImmutableList.Builder<Artifact> allTestArtifacts = ImmutableList.builder();
    for (TransitiveInfoCollection target : targets) {
      allTestArtifacts.addAll(TestProvider.getTestStatusArtifacts(target));
    }
    return allTestArtifacts.build();
  }

  /**
   * Utility function to form a NestedSet of all top-level Artifacts of the given targets.
   */
  public static NestedSet<Artifact> getAllArtifactsToBuild(
      Iterable<? extends TransitiveInfoCollection> targets, TopLevelArtifactContext options) {
    NestedSetBuilder<Artifact> allArtifacts = NestedSetBuilder.stableOrder();
    for (TransitiveInfoCollection target : targets) {
      allArtifacts.addTransitive(getAllArtifactsToBuild(target, options));
    }
    return allArtifacts.build();
  }

  /**
   * Returns all artifacts to build if this target is requested as a top-level target. The resulting
   * set includes the temps and either the files to compile, if
   * {@code options.compileOnly() == true}, or the files to run.
   *
   * <p>Calls to this method should generally return quickly; however, the runfiles computation can
   * be lazy, in which case it can be expensive on the first call. Subsequent calls may or may not
   * return the same {@code Iterable} instance.
   */
  public static NestedSet<Artifact> getAllArtifactsToBuild(TransitiveInfoCollection target,
      TopLevelArtifactContext options) {
    NestedSetBuilder<Artifact> allArtifacts = NestedSetBuilder.stableOrder();
    TempsProvider tempsProvider = target.getProvider(TempsProvider.class);
    if (tempsProvider != null) {
      allArtifacts.addAll(tempsProvider.getTemps());
    }

    TopLevelArtifactProvider topLevelArtifactProvider =
        target.getProvider(TopLevelArtifactProvider.class);
    if (topLevelArtifactProvider != null) {
      for (String outputGroup : options.outputGroups()) {
        NestedSet<Artifact> results = topLevelArtifactProvider.getOutputGroup(outputGroup);
        if (results != null) {
          allArtifacts.addTransitive(results);            
        }         
      }
    }

    if (options.compileOnly()) {
      FilesToCompileProvider provider = target.getProvider(FilesToCompileProvider.class);
      if (provider != null) {
        allArtifacts.addAll(provider.getFilesToCompile());
      }
    } else if (options.compilationPrerequisitesOnly()) {
      CompilationPrerequisitesProvider provider =
          target.getProvider(CompilationPrerequisitesProvider.class);
      if (provider != null) {
        allArtifacts.addTransitive(provider.getCompilationPrerequisites());
      }
    } else {
      FilesToRunProvider filesToRunProvider = target.getProvider(FilesToRunProvider.class);
      boolean hasRunfilesSupport = false;
      if (filesToRunProvider != null) {
        allArtifacts.addAll(filesToRunProvider.getFilesToRun());
        hasRunfilesSupport = filesToRunProvider.getRunfilesSupport() != null;
      }

      if (!hasRunfilesSupport) {
        RunfilesProvider runfilesProvider =
            target.getProvider(RunfilesProvider.class);
        if (runfilesProvider != null) {
          allArtifacts.addTransitive(runfilesProvider.getDefaultRunfiles().getAllArtifacts());
        }
      }

      AlwaysBuiltArtifactsProvider forcedArtifacts = target.getProvider(
          AlwaysBuiltArtifactsProvider.class);
      if (forcedArtifacts != null) {
        allArtifacts.addTransitive(forcedArtifacts.getArtifactsToAlwaysBuild());
      }
    }

    allArtifacts.addAll(getCommandArtifacts(target, options.buildCommand()));
    allArtifacts.addAll(getCoverageArtifacts(target, options));
    return allArtifacts.build();
  }

  private static Iterable<Artifact> getCoverageArtifacts(TransitiveInfoCollection target,
                                                         TopLevelArtifactContext topLevelOptions) {
    if (!topLevelOptions.compileOnly() && !topLevelOptions.compilationPrerequisitesOnly()
        && topLevelOptions.shouldRunTests()) {
      // Add baseline code coverage artifacts if we are collecting code coverage. We do that only
      // when running tests.
      // It might be slightly faster to first check if any configuration has coverage enabled.
      if (target.getConfiguration() != null
          && target.getConfiguration().isCodeCoverageEnabled()) {
        BaselineCoverageArtifactsProvider provider =
            target.getProvider(BaselineCoverageArtifactsProvider.class);
        if (provider != null) {
          return provider.getBaselineCoverageArtifacts();
        }
      }
    }
    return ImmutableList.of();
  }
}