aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
diff options
context:
space:
mode:
authorGravatar juliexxia <juliexxia@google.com>2018-03-23 14:51:43 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-23 14:52:55 -0700
commit64d4c652f9db83b0a5ae62f319cc442a2cb79400 (patch)
treeff6bf942c2810b1cd0b6a4774dfef19b121ea743 /src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
parent6dae259c43c0688a149865bd69bee177f633e10c (diff)
Create a new output formatter for cquery which output transition information in either a FULL or LITE version. Trigger new output with the new --transitions cquery flag in the new CqueryOptions class.
PiperOrigin-RevId: 190278664
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java75
1 files changed, 57 insertions, 18 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
index c4ce4e5ea3..d84db4ce32 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
@@ -21,12 +21,14 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.util.Fingerprint;
+import com.google.devtools.build.lib.util.OrderedSetMultimap;
import com.google.devtools.common.options.InvocationPolicyEnforcer;
import com.google.devtools.common.options.OptionDefinition;
import com.google.devtools.common.options.OptionsBase;
@@ -34,11 +36,13 @@ import com.google.devtools.common.options.OptionsClassProvider;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -344,16 +348,32 @@ public final class BuildOptions implements Cloneable, Serializable {
}
}
- /** Returns the difference between two BuildOptions in a {@link BuildOptions.OptionsDiff}. */
- public static OptionsDiff diff(BuildOptions first, BuildOptions second) {
+ /** Returns the difference between two BuildOptions in a new {@link BuildOptions.OptionsDiff}. */
+ public static OptionsDiff diff(@Nullable BuildOptions first, @Nullable BuildOptions second) {
+ return diff(new OptionsDiff(), first, second);
+ }
+
+ /**
+ * Returns the difference between two BuildOptions in a pre-existing {@link
+ * BuildOptions.OptionsDiff}.
+ *
+ * <p>In a single pass through this method, the method can only compare a single "first" {@link
+ * BuildOptions} and single "second" BuildOptions; but an OptionsDiff instance can store the diff
+ * between a single "first" BuildOptions and multiple "second" BuildOptions. Being able to
+ * maintain a single OptionsDiff over multiple calls to diff is useful for, for example,
+ * aggregating the difference between a single BuildOptions and the results of applying a {@link
+ * com.google.devtools.build.lib.analysis.config.transitions.SplitTransition}) to it.
+ */
+ public static OptionsDiff diff(
+ OptionsDiff diff, @Nullable BuildOptions first, @Nullable BuildOptions second) {
if (first == null || second == null) {
throw new IllegalArgumentException("Cannot diff null BuildOptions");
}
- OptionsDiff diff = new OptionsDiff();
if (first.equals(second)) {
return diff;
}
- // Check if either class has been trimmed of an options class that exists in the other.
+ // Check and report if either class has been trimmed of an options class that exists in the
+ // other.
ImmutableSet<Class<? extends FragmentOptions>> firstOptionClasses =
first.getOptions()
.stream()
@@ -405,7 +425,17 @@ public final class BuildOptions implements Cloneable, Serializable {
Collection<OptionDefinition> fields = diff.differingOptions.get(clazz);
HashMap<String, Object> valueMap = new HashMap<>(fields.size());
for (OptionDefinition optionDefinition : fields) {
- Object secondValue = diff.second.get(optionDefinition);
+ Object secondValue;
+ try {
+ secondValue = Iterables.getOnlyElement(diff.second.get(optionDefinition));
+ } catch (IllegalArgumentException e) {
+ // TODO(janakr): Currently this exception should never be thrown since diff is never
+ // constructed using the diff method that takes in a preexisting OptionsDiff. If this
+ // changes, add a test verifying this error catching works properly.
+ throw new IllegalStateException(
+ "OptionsDiffForReconstruction can only handle a single first BuildOptions and a "
+ + "single second BuildOptions and has encountered multiple second BuildOptions");
+ }
valueMap.put(optionDefinition.getField().getName(), secondValue);
}
differingOptions.put(clazz, valueMap);
@@ -419,14 +449,20 @@ public final class BuildOptions implements Cloneable, Serializable {
}
/**
- * A diff class for BuildOptions. Fields are meant to be populated and returned by
- * {@link BuildOptions#diff}
+ * A diff class for BuildOptions. Fields are meant to be populated and returned by {@link
+ * BuildOptions#diff}
*/
public static class OptionsDiff{
private final Multimap<Class<? extends FragmentOptions>, OptionDefinition> differingOptions =
ArrayListMultimap.create();
- private final Map<OptionDefinition, Object> first = new HashMap<>();
- private final Map<OptionDefinition, Object> second = new HashMap<>();
+ // The keyset for the {@link first} and {@link second} maps are identical and indicate which
+ // specific options differ between the first and second built options.
+ private final Map<OptionDefinition, Object> first = new LinkedHashMap<>();
+ // Since this class can be used to track the result of transitions, {@link second} is a multimap
+ // to be able to handle [@link SplitTransition}s.
+ private final Multimap<OptionDefinition, Object> second = OrderedSetMultimap.create();
+ // List of "extra" fragments for each BuildOption aka fragments that were trimmed off one
+ // BuildOption but not the other.
private final Set<Class<? extends FragmentOptions>> extraFirstFragments = new HashSet<>();
private final Set<FragmentOptions> extraSecondFragments = new HashSet<>();
@@ -452,7 +488,7 @@ public final class BuildOptions implements Cloneable, Serializable {
return first;
}
- public Map<OptionDefinition, Object> getSecond() {
+ public Multimap<OptionDefinition, Object> getSecond() {
return second;
}
@@ -480,17 +516,20 @@ public final class BuildOptions implements Cloneable, Serializable {
public String prettyPrint() {
StringBuilder toReturn = new StringBuilder();
- for (Map.Entry<OptionDefinition, Object> firstOption : first.entrySet()) {
- toReturn
- .append(firstOption.getKey().getOptionName())
- .append(":")
- .append(firstOption.getValue())
- .append(" -> ")
- .append(second.get(firstOption.getKey()))
- .append(System.lineSeparator());
+ for (String diff : getPrettyPrintList()) {
+ toReturn.append(diff).append(System.lineSeparator());
}
return toReturn.toString();
}
+
+ public List<String> getPrettyPrintList() {
+ List<String> toReturn = new ArrayList<>();
+ first.forEach(
+ (option, value) ->
+ toReturn.add(
+ option.getOptionName() + ":" + value + " -> " + second.get(option)));
+ return toReturn;
+ }
}
/**