blob: a25c3ac201deb55a7b7fd3d960713ba4fcab200e [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Greg Estren531fc042015-05-26 22:37:44 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.skyframe;
15
16import static com.google.devtools.build.lib.analysis.config.BuildConfiguration.Fragment;
17
18import com.google.common.collect.ClassToInstanceMap;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.MutableClassToInstanceMap;
21import com.google.devtools.build.lib.analysis.BlazeDirectories;
Greg Estren00049432015-08-25 16:43:47 +000022import com.google.devtools.build.lib.analysis.ConfigurationCollectionFactory;
23import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
Greg Estren531fc042015-05-26 22:37:44 +000024import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
25import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
Greg Estren00049432015-08-25 16:43:47 +000026import com.google.devtools.build.lib.packages.RuleClassProvider;
Greg Estren531fc042015-05-26 22:37:44 +000027import com.google.devtools.build.skyframe.SkyFunction;
28import com.google.devtools.build.skyframe.SkyFunctionException;
29import com.google.devtools.build.skyframe.SkyKey;
30import com.google.devtools.build.skyframe.SkyValue;
31import com.google.devtools.build.skyframe.ValueOrException;
32
33import java.util.LinkedHashSet;
34import java.util.Map;
35import java.util.Set;
36
37/**
38 * A builder for {@link BuildConfigurationValue} instances.
39 */
40public class BuildConfigurationFunction implements SkyFunction {
41
42 private final BlazeDirectories directories;
Greg Estrenbbe821e2015-11-11 19:57:37 +000043 private final RuleClassProvider ruleClassProvider;
Greg Estren00049432015-08-25 16:43:47 +000044 private final ConfigurationCollectionFactory collectionFactory;
Greg Estren531fc042015-05-26 22:37:44 +000045
Greg Estren00049432015-08-25 16:43:47 +000046 public BuildConfigurationFunction(BlazeDirectories directories,
47 RuleClassProvider ruleClassProvider) {
Greg Estren531fc042015-05-26 22:37:44 +000048 this.directories = directories;
Greg Estrenbbe821e2015-11-11 19:57:37 +000049 this.ruleClassProvider = ruleClassProvider;
Greg Estren00049432015-08-25 16:43:47 +000050 collectionFactory =
51 ((ConfiguredRuleClassProvider) ruleClassProvider).getConfigurationCollectionFactory();
Greg Estren531fc042015-05-26 22:37:44 +000052 }
53
54 @Override
Ulf Adams25f03d82016-01-25 10:31:46 +000055 public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
Greg Estren531fc042015-05-26 22:37:44 +000056 BuildConfigurationValue.Key key = (BuildConfigurationValue.Key) skyKey.argument();
57 Set<Fragment> fragments;
58 try {
59 fragments = getConfigurationFragments(key, env);
60 } catch (InvalidConfigurationException e) {
61 throw new BuildConfigurationFunctionException(e);
62 }
63 if (fragments == null) {
64 return null;
65 }
66
67 ClassToInstanceMap<Fragment> fragmentsMap = MutableClassToInstanceMap.create();
68 for (Fragment fragment : fragments) {
69 fragmentsMap.put(fragment.getClass(), fragment);
70 }
71
Greg Estren00049432015-08-25 16:43:47 +000072 BuildConfiguration config = new BuildConfiguration(directories, fragmentsMap,
73 key.getBuildOptions(), !key.actionsEnabled());
74 // Unlike static configurations, dynamic configurations don't need to embed transition logic
75 // within the configuration itself. However we still use this interface to provide a mapping
76 // between Transition types (e.g. HOST) and the dynamic transitions that apply those
77 // transitions. Once static configurations are cleaned out we won't need this interface
78 // any more (all the centralized logic that maintains the transition logic can be distributed
79 // to the actual rule code that uses it).
80 config.setConfigurationTransitions(collectionFactory.getDynamicTransitionLogic(config));
81
82 return new BuildConfigurationValue(config);
Greg Estren531fc042015-05-26 22:37:44 +000083 }
84
85 private Set<Fragment> getConfigurationFragments(BuildConfigurationValue.Key key, Environment env)
86 throws InvalidConfigurationException {
Greg Estren00049432015-08-25 16:43:47 +000087
Greg Estren531fc042015-05-26 22:37:44 +000088 // Get SkyKeys for the fragments we need to load.
89 Set<SkyKey> fragmentKeys = new LinkedHashSet<>();
90 for (Class<? extends BuildConfiguration.Fragment> fragmentClass : key.getFragments()) {
Greg Estrena0eccb72016-02-01 22:46:10 +000091 fragmentKeys.add(
92 ConfigurationFragmentValue.key(key.getBuildOptions(), fragmentClass, ruleClassProvider));
Greg Estren531fc042015-05-26 22:37:44 +000093 }
94
95 // Load them as Skyframe deps.
96 Map<SkyKey, ValueOrException<InvalidConfigurationException>> fragmentDeps =
97 env.getValuesOrThrow(fragmentKeys, InvalidConfigurationException.class);
98 if (env.valuesMissing()) {
99 return null;
100 }
101
102 // Collect and return the results.
103 ImmutableSet.Builder<Fragment> fragments = ImmutableSet.builder();
104 for (ValueOrException<InvalidConfigurationException> value : fragmentDeps.values()) {
Greg Estren00049432015-08-25 16:43:47 +0000105 BuildConfiguration.Fragment fragment =
106 ((ConfigurationFragmentValue) value.get()).getFragment();
107 if (fragment != null) {
108 fragments.add(fragment);
109 }
Greg Estren531fc042015-05-26 22:37:44 +0000110 }
111 return fragments.build();
112 }
113
114 @Override
115 public String extractTag(SkyKey skyKey) {
116 return null;
117 }
118
119 private static final class BuildConfigurationFunctionException extends SkyFunctionException {
120 public BuildConfigurationFunctionException(InvalidConfigurationException e) {
121 super(e, Transience.PERSISTENT);
122 }
123 }
124}