Skip to content

Commit

Permalink
Add capability for PlatformInfo providers to inherit from another Pla…
Browse files Browse the repository at this point in the history
…tformInfo.

Part of work on #6218.

Closes #6465.

PiperOrigin-RevId: 218388951
  • Loading branch information
katre authored and Copybara-Service committed Oct 23, 2018
1 parent 9fe597d commit b6694bf
Show file tree
Hide file tree
Showing 8 changed files with 325 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,28 @@
@AutoCodec
public final class ConstraintCollection
implements ConstraintCollectionApi<ConstraintSettingInfo, ConstraintValueInfo> {
@Nullable private final ConstraintCollection parent;
private final ImmutableMap<ConstraintSettingInfo, ConstraintValueInfo> constraints;

ConstraintCollection(ImmutableList<ConstraintValueInfo> constraints) {
this(null, constraints);
}

ConstraintCollection(
@Nullable ConstraintCollection parent, ImmutableList<ConstraintValueInfo> constraints) {
this(
parent,
constraints.stream()
.collect(
ImmutableMap.toImmutableMap(ConstraintValueInfo::constraint, Function.identity())));
}

@AutoCodec.Instantiator
@VisibleForSerialization
ConstraintCollection(ImmutableMap<ConstraintSettingInfo, ConstraintValueInfo> constraints) {
ConstraintCollection(
@Nullable ConstraintCollection parent,
ImmutableMap<ConstraintSettingInfo, ConstraintValueInfo> constraints) {
this.parent = parent;
this.constraints = constraints;
}

Expand All @@ -66,18 +76,39 @@ private ConstraintSettingInfo convertKey(Object key, Location loc) throws EvalEx
return (ConstraintSettingInfo) key;
}

@Override
public boolean has(ConstraintSettingInfo constraint) {
// First, check locally.
if (constraints.containsKey(constraint)) {
return true;
}

// Then, check the parent, directly to ignore defaults.
if (parent != null && parent.constraints.containsKey(constraint)) {
return true;
}

return constraint.hasDefaultConstraintValue();
}

/**
* Returns the {@link ConstraintValueInfo} for the given {@link ConstraintSettingInfo}, or {@code
* null} if none exists.
*/
@Nullable
@Override
public ConstraintValueInfo get(ConstraintSettingInfo constraint) {
// First, check locally.
if (constraints.containsKey(constraint)) {
return constraints.get(constraint);
}

// Since this constraint isn't set, fall back to the default.
// Then, check the parent, directly to ignore defaults.
if (parent != null && parent.constraints.containsKey(constraint)) {
return parent.constraints.get(constraint);
}

// Finally, Since this constraint isn't set, fall back to the default.
return constraint.defaultConstraintValue();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,15 @@ public Label label() {
return label;
}

@Override
public boolean hasDefaultConstraintValue() {
return defaultConstraintValueLabel != null;
}

@Override
@Nullable
public ConstraintValueInfo defaultConstraintValue() {
if (defaultConstraintValueLabel == null) {
if (!hasDefaultConstraintValue()) {
return null;
}
return ConstraintValueInfo.create(this, defaultConstraintValueLabel);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static java.util.stream.Collectors.joining;

import com.google.common.base.Functions;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ListMultimap;
Expand All @@ -33,17 +34,27 @@
import com.google.devtools.build.lib.skylarkbuildapi.platform.PlatformInfoApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.StringUtilities;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.annotation.Nullable;

/** Provider for a platform, which is a group of constraints and values. */
@Immutable
@AutoCodec
public class PlatformInfo extends NativeInfo
implements PlatformInfoApi<ConstraintSettingInfo, ConstraintValueInfo> {

/**
* The literal key that will be used to copy the {@link #remoteExecutionProperties} from the
* parent {@link PlatformInfo} into a new {@link PlatformInfo}'s {@link
* #remoteExecutionProperties}.
*/
public static final String PARENT_REMOTE_EXECUTION_KEY = "{PARENT_REMOTE_EXECUTION_PROPERTIES}";

/** Name used in Skylark for accessing this provider. */
public static final String SKYLARK_NAME = "PlatformInfo";

Expand All @@ -66,7 +77,7 @@ public class PlatformInfo extends NativeInfo

this.label = label;
this.constraints = constraints;
this.remoteExecutionProperties = remoteExecutionProperties;
this.remoteExecutionProperties = Strings.nullToEmpty(remoteExecutionProperties);
}

@Override
Expand Down Expand Up @@ -103,11 +114,26 @@ public void addTo(Fingerprint fp) {

/** Builder class to facilitate creating valid {@link PlatformInfo} instances. */
public static class Builder {

private PlatformInfo parent = null;
private Label label;
private final List<ConstraintValueInfo> constraints = new ArrayList<>();
private String remoteExecutionProperties = "";
private String remoteExecutionProperties = null;
private Location location = Location.BUILTIN;

/**
* Sets the parent {@link PlatformInfo} that this platform inherits from. Constraint values set
* directly on this instance will be kept, but any other constraint settings will be found from
* the parent, if set.
*
* @param parent the platform that is the parent of this platform
* @return the {@link Builder} instance for method chaining
*/
public Builder setParent(PlatformInfo parent) {
this.parent = parent;
return this;
}

/**
* Sets the {@link Label} for this {@link PlatformInfo}.
*
Expand Down Expand Up @@ -150,7 +176,24 @@ public String getRemoteExecutionProperties() {
}

/**
* Sets the data being sent to a potential remote executor.
* Sets the data being sent to a potential remote executor. If there is a parent {@link
* PlatformInfo} set, the literal string "{PARENT_REMOTE_EXECUTION_PROPERTIES}" will be replaced
* by the {@link #remoteExecutionProperties} from that parent. Also if the parent is set, and
* this instance's {@link #remoteExecutionProperties} is blank or unset, the parent's will be
* used directly.
*
* <p>Specific examples:
*
* <ul>
* <li>parent.remoteExecutionProperties is unset: use the child's value
* <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is unset: use
* the parent's value
* <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is set, and
* does not contain {PARENT_REMOTE_EXECUTION_PROPERTIES}: use the child's value
* <li>parent.remoteExecutionProperties is set, child.remoteExecutionProperties is set, and
* does contain {PARENT_REMOTE_EXECUTION_PROPERTIES}: use the child's value, but
* substitute the parent's value for {PARENT_REMOTE_EXECUTION_PROPERTIES}
* </ul>
*
* @param properties the properties to be added
* @return the {@link Builder} instance for method chaining
Expand Down Expand Up @@ -178,11 +221,43 @@ public Builder setLocation(Location location) {
* constraint setting
*/
public PlatformInfo build() throws DuplicateConstraintException {
// Validate that there are no collisions in the directly set constraint values.
ImmutableList<ConstraintValueInfo> validatedConstraints = validateConstraints(constraints);
ConstraintCollection platformConstraints = new ConstraintCollection(validatedConstraints);

// Merge parent constraints and the validated constraints to a single set and create a
// collection.
ConstraintCollection platformConstraints =
new ConstraintCollection(parentConstraints(), validatedConstraints);

// Merge the remote execution properties.
String remoteExecutionProperties =
mergeRemoteExecutionProperties(parent, this.remoteExecutionProperties);
return new PlatformInfo(label, platformConstraints, remoteExecutionProperties, location);
}

@Nullable
private ConstraintCollection parentConstraints() {
if (parent == null) {
return null;
}
return parent.constraints();
}

private static String mergeRemoteExecutionProperties(
PlatformInfo parent, String remoteExecutionProperties) {
String parentRemoteExecutionProperties = "";
if (parent != null) {
parentRemoteExecutionProperties = parent.remoteExecutionProperties();
}

if (remoteExecutionProperties == null) {
return parentRemoteExecutionProperties;
}

return StringUtilities.replaceAllLiteral(
remoteExecutionProperties, PARENT_REMOTE_EXECUTION_KEY, parentRemoteExecutionProperties);
}

public static ImmutableList<ConstraintValueInfo> validateConstraints(
Iterable<ConstraintValueInfo> constraintValues) throws DuplicateConstraintException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,19 @@ public interface ConstraintCollectionApi<
enableOnlyWithFlag = FlagIdentifier.EXPERIMENTAL_PLATFORM_API)
@Nullable
ConstraintValueInfoT get(ConstraintSettingInfoT constraint);

@SkylarkCallable(
name = "has",
doc = "Returns whether the specific ConstraintSettingInfo is set.",
parameters = {
@Param(
name = "constraint",
type = ConstraintSettingInfoApi.class,
defaultValue = "None",
noneable = true,
named = true,
doc = "The constraint setting to check.")
},
enableOnlyWithFlag = FlagIdentifier.EXPERIMENTAL_PLATFORM_API)
boolean has(ConstraintSettingInfoT constraint);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,10 @@ public interface ConstraintSettingInfoApi extends StructApi {
enableOnlyWithFlag = FlagIdentifier.EXPERIMENTAL_PLATFORM_API)
@Nullable
ConstraintValueInfoApi defaultConstraintValue();

@SkylarkCallable(
name = "has_default_constraint_value",
doc = "Whether there is a default constraint_value for this setting.",
structField = true)
boolean hasDefaultConstraintValue();
}
Loading

0 comments on commit b6694bf

Please sign in to comment.