|  | // Copyright 2014 The Bazel Authors. 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.auto.value.AutoValue; | 
|  | import com.google.common.base.Preconditions; | 
|  | import com.google.common.collect.ImmutableList; | 
|  | import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue; | 
|  | import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition; | 
|  | import com.google.devtools.build.lib.cmdline.Label; | 
|  | import com.google.devtools.build.lib.packages.AspectDescriptor; | 
|  | import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey; | 
|  | import javax.annotation.Nullable; | 
|  |  | 
|  | /** | 
|  | * A dependency of a configured target through a label. | 
|  | * | 
|  | * <p>All instances have an explicit configuration, which includes the target and the configuration | 
|  | * of the dependency configured target and any aspects that may be required, as well as the | 
|  | * configurations for these aspects and transition keys. {@link Dependency#getTransitionKeys} | 
|  | * provides some more context on transition keys. | 
|  | * | 
|  | * <p>Note that the presence of an aspect here does not necessarily mean that it will be created. | 
|  | * They will be filtered based on the {@link TransitiveInfoProvider} instances their associated | 
|  | * configured targets have (we cannot do that here because the configured targets are not available | 
|  | * yet). No error or warning is reported in this case, because it is expected that rules sometimes | 
|  | * over-approximate the providers they supply in their definitions. | 
|  | */ | 
|  | @AutoValue | 
|  | public abstract class Dependency { | 
|  | /** Builder to assist in creating dependency instances. */ | 
|  | @AutoValue.Builder | 
|  | public abstract static class Builder { | 
|  | /** Sets the label of the target this dependency points to. */ | 
|  | public abstract Builder setLabel(Label label); | 
|  |  | 
|  | /** Sets the configuration intended for this dependency. */ | 
|  | public abstract Builder setConfiguration(BuildConfigurationValue configuration); | 
|  |  | 
|  | /** Explicitly set the configuration for this dependency to null. */ | 
|  | public Builder withNullConfiguration() { | 
|  | return setConfiguration(null); | 
|  | } | 
|  |  | 
|  | /** Add aspects to this Dependency. The same configuration is applied to all aspects. */ | 
|  | public abstract Builder setAspects(AspectCollection aspects); | 
|  |  | 
|  | /** Sets the keys of a configuration transition. */ | 
|  | public Builder setTransitionKey(String key) { | 
|  | if (key.isEmpty()) { | 
|  | // Ignore empty keys. | 
|  | return this; | 
|  | } | 
|  | return setTransitionKeys(ImmutableList.of(key)); | 
|  | } | 
|  |  | 
|  | /** Sets the keys of a configuration transition. */ | 
|  | public abstract Builder setTransitionKeys(ImmutableList<String> keys); | 
|  |  | 
|  | /** | 
|  | * Sets the execution platform {@link Label} that this dependency should use as an override for | 
|  | * toolchain resolution. | 
|  | */ | 
|  | public abstract Builder setExecutionPlatformLabel(@Nullable Label executionPlatformLabel); | 
|  |  | 
|  | // Not public. | 
|  | abstract Dependency autoBuild(); | 
|  |  | 
|  | /** Returns the full Dependency instance. */ | 
|  | public Dependency build() { | 
|  | Dependency dependency = autoBuild(); | 
|  | if (dependency.getConfiguration() == null) { | 
|  | Preconditions.checkState( | 
|  | dependency.getAspects().equals(AspectCollection.EMPTY), | 
|  | "Dependency with null Configuration cannot have aspects"); | 
|  | } | 
|  | return dependency; | 
|  | } | 
|  |  | 
|  | // Added to enable copy, below. Should not be accessible to other classes. | 
|  | protected abstract Label getLabel(); | 
|  |  | 
|  | @Nullable | 
|  | protected abstract BuildConfigurationValue getConfiguration(); | 
|  |  | 
|  | protected abstract AspectCollection getAspects(); | 
|  |  | 
|  | protected abstract ImmutableList<String> getTransitionKeys(); | 
|  |  | 
|  | /** Returns a copy of this Builder, with the values the same. */ | 
|  | public Builder copy() { | 
|  | return Dependency.builder() | 
|  | .setLabel(getLabel()) | 
|  | .setConfiguration(getConfiguration()) | 
|  | .setAspects(getAspects()) | 
|  | .setTransitionKeys(getTransitionKeys()); | 
|  | } | 
|  | } | 
|  |  | 
|  | /** Returns a new {@link Builder} to create {@link Dependency} instances. */ | 
|  | public static Builder builder() { | 
|  | return new AutoValue_Dependency.Builder() | 
|  | .setAspects(AspectCollection.EMPTY) | 
|  | .setTransitionKeys(ImmutableList.of()); | 
|  | } | 
|  |  | 
|  | /** Returns the label of the target this dependency points to. */ | 
|  | public abstract Label getLabel(); | 
|  |  | 
|  | /** Returns the explicit configuration intended for this dependency. */ | 
|  | @Nullable | 
|  | public abstract BuildConfigurationValue getConfiguration(); | 
|  |  | 
|  | /** | 
|  | * Returns the set of aspects which should be evaluated and combined with the configured target | 
|  | * pointed to by this dependency. | 
|  | * | 
|  | * @see #getAspectConfiguration(AspectDescriptor) | 
|  | */ | 
|  | public abstract AspectCollection getAspects(); | 
|  |  | 
|  | /** | 
|  | * Returns the keys of a configuration transition, if any exist, associated with this dependency. | 
|  | * See {@link ConfigurationTransition#apply} for more details. Normally, this returns an empty | 
|  | * list, when there was no configuration transition in effect, or one with a single entry, when | 
|  | * there was a specific configuration transition result that led to this. It may also return a | 
|  | * list with multiple entries if the dependency has a null configuration, yet the outgoing edge | 
|  | * has a split transition. In such cases all transition keys returned by the transition are tagged | 
|  | * to the dependency. | 
|  | */ | 
|  | public abstract ImmutableList<String> getTransitionKeys(); | 
|  |  | 
|  | /** | 
|  | * Returns the execution platform {@link Label} that this dependency should use as an override for | 
|  | * toolchain resolution. | 
|  | */ | 
|  | @Nullable | 
|  | public abstract Label getExecutionPlatformLabel(); | 
|  |  | 
|  | /** Returns the ConfiguredTargetKey needed to fetch this dependency. */ | 
|  | public ConfiguredTargetKey getConfiguredTargetKey() { | 
|  | ConfiguredTargetKey.Builder configuredTargetKeyBuilder = | 
|  | ConfiguredTargetKey.builder().setLabel(getLabel()).setConfiguration(getConfiguration()); | 
|  | if (getExecutionPlatformLabel() != null) { | 
|  | configuredTargetKeyBuilder.setExecutionPlatformLabel(getExecutionPlatformLabel()); | 
|  | } | 
|  | return configuredTargetKeyBuilder.build(); | 
|  | } | 
|  | } |