| // 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.BuildConfiguration; | |
| 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 com.google.devtools.build.lib.skyframe.ToolchainContextKey; | |
| 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(BuildConfiguration 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 {@link ToolchainContextKey} that this dependency should use for toolchain | |
| * resolution. | |
| */ | |
| @Nullable | |
| public abstract Builder setToolchainContextKey(ToolchainContextKey toolchainContextKey); | |
| // 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 BuildConfiguration 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 BuildConfiguration 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 configuration an aspect should be evaluated with. */ | |
| @Nullable | |
| public BuildConfiguration getAspectConfiguration(AspectDescriptor aspect) { | |
| return getConfiguration(); | |
| } | |
| /** | |
| * 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 {@link ToolchainContextKey} that this dependency should use for toolchain | |
| * resolution. | |
| */ | |
| @Nullable | |
| public abstract ToolchainContextKey getToolchainContextKey(); | |
| /** Returns the ConfiguredTargetKey needed to fetch this dependency. */ | |
| public ConfiguredTargetKey getConfiguredTargetKey() { | |
| ConfiguredTargetKey.Builder configuredTargetKeyBuilder = | |
| ConfiguredTargetKey.builder().setLabel(getLabel()).setConfiguration(getConfiguration()); | |
| if (getToolchainContextKey() != null) { | |
| configuredTargetKeyBuilder.setToolchainContextKey(getToolchainContextKey()); | |
| } | |
| return configuredTargetKeyBuilder.build(); | |
| } | |
| } |