aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
diff options
context:
space:
mode:
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.java254
1 files changed, 254 insertions, 0 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
new file mode 100644
index 0000000000..afe408f628
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildOptions.java
@@ -0,0 +1,254 @@
+// 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.config;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ListMultimap;
+import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.common.options.Options;
+import com.google.devtools.common.options.OptionsBase;
+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.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * This is a collection of command-line options from all configuration fragments. Contains
+ * a single instance for all FragmentOptions classes provided by Blaze language modules.
+ */
+public final class BuildOptions implements Cloneable, Serializable {
+ /**
+ * Creates a BuildOptions object with all options set to its default value.
+ */
+ public static BuildOptions createDefaults(Iterable<Class<? extends FragmentOptions>> options) {
+ Builder builder = builder();
+ for (Class<? extends FragmentOptions> optionsClass : options) {
+ builder.add(Options.getDefaults(optionsClass));
+ }
+ return builder.build();
+ }
+
+ /**
+ * This function creates a new BuildOptions instance for host.
+ *
+ * @param fallback if true, we have already tried the user specified hostCpu options
+ * and it didn't work, so now we try the default options instead.
+ */
+ public BuildOptions createHostOptions(boolean fallback) {
+ Builder builder = builder();
+ for (FragmentOptions options : fragmentOptionsMap.values()) {
+ builder.add(options.getHost(fallback));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Returns a list of potential split configuration transitions by calling {@link
+ * FragmentOptions#getPotentialSplitTransitions} on all the fragments.
+ */
+ public List<SplitTransition<BuildOptions>> getPotentialSplitTransitions() {
+ List<SplitTransition<BuildOptions>> result = new ArrayList<>();
+ for (FragmentOptions options : fragmentOptionsMap.values()) {
+ result.addAll(options.getPotentialSplitTransitions());
+ }
+ return result;
+ }
+
+ /**
+ * Creates an BuildOptions class by taking the option values from an options provider
+ * (eg. an OptionsParser).
+ */
+ public static BuildOptions of(List<Class<? extends FragmentOptions>> optionsList,
+ OptionsClassProvider provider) {
+ Builder builder = builder();
+ for (Class<? extends FragmentOptions> optionsClass : optionsList) {
+ builder.add(provider.getOptions(optionsClass));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Creates an BuildOptions class by taking the option values from command-line arguments
+ */
+ @VisibleForTesting
+ public static BuildOptions of(List<Class<? extends FragmentOptions>> optionsList, String... args)
+ throws OptionsParsingException {
+ Builder builder = builder();
+ OptionsParser parser = OptionsParser.newOptionsParser(
+ ImmutableList.<Class<? extends OptionsBase>>copyOf(optionsList));
+ parser.parse(args);
+ for (Class<? extends FragmentOptions> optionsClass : optionsList) {
+ builder.add(parser.getOptions(optionsClass));
+ }
+ return builder.build();
+ }
+
+ /**
+ * Returns the actual instance of a FragmentOptions class.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends FragmentOptions> T get(Class<T> optionsClass) {
+ FragmentOptions options = fragmentOptionsMap.get(optionsClass);
+ Preconditions.checkNotNull(options);
+ Preconditions.checkArgument(optionsClass.isAssignableFrom(options.getClass()));
+ return (T) options;
+ }
+
+ /**
+ * Returns a multimap of all labels that were specified as options, keyed by the name to be
+ * displayed to the user if something goes wrong. This should be the set of all labels
+ * mentioned in explicit command line options that are not already covered by the
+ * tools/defaults package (see the DefaultsPackage class), and nothing else.
+ */
+ public ListMultimap<String, Label> getAllLabels() {
+ ListMultimap<String, Label> labels = ArrayListMultimap.create();
+ for (FragmentOptions optionsBase : fragmentOptionsMap.values()) {
+ optionsBase.addAllLabels(labels);
+ }
+ return labels;
+ }
+
+ // It would be very convenient to use a Multimap here, but we cannot do that because we need to
+ // support defaults labels that have zero elements.
+ ImmutableMap<String, ImmutableSet<Label>> getDefaultsLabels() {
+ BuildConfiguration.Options opts = get(BuildConfiguration.Options.class);
+ Map<String, Set<Label>> collector = new TreeMap<>();
+ for (FragmentOptions fragment : fragmentOptionsMap.values()) {
+ for (Map.Entry<String, Set<Label>> entry : fragment.getDefaultsLabels(opts).entrySet()) {
+ if (!collector.containsKey(entry.getKey())) {
+ collector.put(entry.getKey(), new TreeSet<Label>());
+ }
+ collector.get(entry.getKey()).addAll(entry.getValue());
+ }
+ }
+
+ ImmutableMap.Builder<String, ImmutableSet<Label>> result = new ImmutableMap.Builder<>();
+ for (Map.Entry<String, Set<Label>> entry : collector.entrySet()) {
+ result.put(entry.getKey(), ImmutableSet.copyOf(entry.getValue()));
+ }
+
+ return result.build();
+ }
+
+ /**
+ * The cache key for the options collection. Recomputes cache key every time it's called.
+ */
+ public String computeCacheKey() {
+ StringBuilder keyBuilder = new StringBuilder();
+ for (FragmentOptions options : fragmentOptionsMap.values()) {
+ keyBuilder.append(options.cacheKey());
+ }
+ return keyBuilder.toString();
+ }
+
+ /**
+ * String representation of build options.
+ */
+ @Override
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (FragmentOptions options : fragmentOptionsMap.values()) {
+ stringBuilder.append(options.toString());
+ }
+ return stringBuilder.toString();
+ }
+
+ /**
+ * Returns the options contained in this collection.
+ */
+ public Iterable<FragmentOptions> getOptions() {
+ return fragmentOptionsMap.values();
+ }
+
+ /**
+ * Creates a copy of the BuildOptions object that contains copies of the FragmentOptions.
+ */
+ @Override
+ public BuildOptions clone() {
+ ImmutableMap.Builder<Class<? extends FragmentOptions>, FragmentOptions> builder =
+ ImmutableMap.builder();
+ for (Map.Entry<Class<? extends FragmentOptions>, FragmentOptions> entry :
+ fragmentOptionsMap.entrySet()) {
+ builder.put(entry.getKey(), entry.getValue().clone());
+ }
+ return new BuildOptions(builder.build());
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ return (this == other) || (other instanceof BuildOptions &&
+ fragmentOptionsMap.equals(((BuildOptions) other).fragmentOptionsMap));
+ }
+
+ @Override
+ public int hashCode() {
+ return fragmentOptionsMap.hashCode();
+ }
+
+ /**
+ * Maps options class definitions to FragmentOptions objects
+ */
+ private final ImmutableMap<Class<? extends FragmentOptions>, FragmentOptions> fragmentOptionsMap;
+
+ private BuildOptions(
+ ImmutableMap<Class<? extends FragmentOptions>, FragmentOptions> fragmentOptionsMap) {
+ this.fragmentOptionsMap = fragmentOptionsMap;
+ }
+
+ /**
+ * Creates a builder object for BuildOptions
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder class for BuildOptions.
+ */
+ public static class Builder {
+ /**
+ * Adds a new FragmentOptions instance to the builder. Overrides previous instances of the
+ * exact same subclass of FragmentOptions.
+ */
+ public <T extends FragmentOptions> Builder add(T options) {
+ builderMap.put(options.getClass(), options);
+ return this;
+ }
+
+ public BuildOptions build() {
+ return new BuildOptions(ImmutableMap.copyOf(builderMap));
+ }
+
+ private Map<Class<? extends FragmentOptions>, FragmentOptions> builderMap;
+
+ private Builder() {
+ builderMap = new HashMap<>();
+ }
+ }
+}