blob: 9edebb8735a69e4aebaa5394e5c1987924c067c0 [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;
lberki86266232018-04-11 00:33:42 -070021import com.google.devtools.build.lib.actions.ActionEnvironment;
Greg Estren531fc042015-05-26 22:37:44 +000022import com.google.devtools.build.lib.analysis.BlazeDirectories;
Greg Estren00049432015-08-25 16:43:47 +000023import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
Greg Estren531fc042015-05-26 22:37:44 +000024import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
mjhalupka5d7fa7b2018-03-22 13:37:38 -070025import com.google.devtools.build.lib.analysis.config.BuildOptions;
Greg Estren531fc042015-05-26 22:37:44 +000026import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
Greg Estren00049432015-08-25 16:43:47 +000027import com.google.devtools.build.lib.packages.RuleClassProvider;
Greg Estren531fc042015-05-26 22:37:44 +000028import com.google.devtools.build.skyframe.SkyFunction;
29import com.google.devtools.build.skyframe.SkyFunctionException;
30import com.google.devtools.build.skyframe.SkyKey;
31import com.google.devtools.build.skyframe.SkyValue;
32import com.google.devtools.build.skyframe.ValueOrException;
Greg Estren531fc042015-05-26 22:37:44 +000033import 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;
gregce490b0952017-07-06 18:44:38 -040043 private final ConfiguredRuleClassProvider ruleClassProvider;
mjhalupka5d7fa7b2018-03-22 13:37:38 -070044 private final BuildOptions defaultBuildOptions;
Greg Estren531fc042015-05-26 22:37:44 +000045
mjhalupka5d7fa7b2018-03-22 13:37:38 -070046 public BuildConfigurationFunction(
47 BlazeDirectories directories,
48 RuleClassProvider ruleClassProvider,
49 BuildOptions defaultBuildOptions) {
Greg Estren531fc042015-05-26 22:37:44 +000050 this.directories = directories;
gregce490b0952017-07-06 18:44:38 -040051 this.ruleClassProvider = (ConfiguredRuleClassProvider) ruleClassProvider;
mjhalupka5d7fa7b2018-03-22 13:37:38 -070052 this.defaultBuildOptions = defaultBuildOptions;
Greg Estren531fc042015-05-26 22:37:44 +000053 }
54
55 @Override
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000056 public SkyValue compute(SkyKey skyKey, Environment env)
57 throws InterruptedException, BuildConfigurationFunctionException {
kchodorow85ae1902017-04-22 15:07:22 -040058 WorkspaceNameValue workspaceNameValue = (WorkspaceNameValue) env
59 .getValue(WorkspaceNameValue.key());
60 if (workspaceNameValue == null) {
61 return null;
62 }
63
Greg Estren531fc042015-05-26 22:37:44 +000064 BuildConfigurationValue.Key key = (BuildConfigurationValue.Key) skyKey.argument();
65 Set<Fragment> fragments;
66 try {
67 fragments = getConfigurationFragments(key, env);
68 } catch (InvalidConfigurationException e) {
69 throw new BuildConfigurationFunctionException(e);
70 }
71 if (fragments == null) {
72 return null;
73 }
74
75 ClassToInstanceMap<Fragment> fragmentsMap = MutableClassToInstanceMap.create();
76 for (Fragment fragment : fragments) {
77 fragmentsMap.put(fragment.getClass(), fragment);
78 }
79
mjhalupka5d7fa7b2018-03-22 13:37:38 -070080 BuildOptions options = defaultBuildOptions.applyDiff(key.getOptionsDiff());
lberki86266232018-04-11 00:33:42 -070081 ActionEnvironment actionEnvironment =
82 ruleClassProvider.getActionEnvironmentProvider().getActionEnvironment(options);
mjhalupka5d7fa7b2018-03-22 13:37:38 -070083
gregce490b0952017-07-06 18:44:38 -040084 BuildConfiguration config =
85 new BuildConfiguration(
lberki406199f2018-04-09 03:16:19 -070086 directories,
87 fragmentsMap,
88 options,
89 key.getOptionsDiff(),
90 ruleClassProvider.getReservedActionMnemonics(),
lberki86266232018-04-11 00:33:42 -070091 actionEnvironment,
lberki406199f2018-04-09 03:16:19 -070092 workspaceNameValue.getName());
Greg Estren00049432015-08-25 16:43:47 +000093 return new BuildConfigurationValue(config);
Greg Estren531fc042015-05-26 22:37:44 +000094 }
95
96 private Set<Fragment> getConfigurationFragments(BuildConfigurationValue.Key key, Environment env)
Janak Ramakrishnan3c0adb22016-08-15 21:54:55 +000097 throws InvalidConfigurationException, InterruptedException {
Greg Estren00049432015-08-25 16:43:47 +000098
Greg Estren531fc042015-05-26 22:37:44 +000099 // Get SkyKeys for the fragments we need to load.
100 Set<SkyKey> fragmentKeys = new LinkedHashSet<>();
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700101 BuildOptions options = defaultBuildOptions.applyDiff(key.getOptionsDiff());
Greg Estren531fc042015-05-26 22:37:44 +0000102 for (Class<? extends BuildConfiguration.Fragment> fragmentClass : key.getFragments()) {
mjhalupka5d7fa7b2018-03-22 13:37:38 -0700103 fragmentKeys.add(ConfigurationFragmentValue.key(options, fragmentClass, ruleClassProvider));
Greg Estren531fc042015-05-26 22:37:44 +0000104 }
105
106 // Load them as Skyframe deps.
107 Map<SkyKey, ValueOrException<InvalidConfigurationException>> fragmentDeps =
108 env.getValuesOrThrow(fragmentKeys, InvalidConfigurationException.class);
109 if (env.valuesMissing()) {
110 return null;
111 }
112
113 // Collect and return the results.
114 ImmutableSet.Builder<Fragment> fragments = ImmutableSet.builder();
115 for (ValueOrException<InvalidConfigurationException> value : fragmentDeps.values()) {
Greg Estren00049432015-08-25 16:43:47 +0000116 BuildConfiguration.Fragment fragment =
117 ((ConfigurationFragmentValue) value.get()).getFragment();
118 if (fragment != null) {
119 fragments.add(fragment);
120 }
Greg Estren531fc042015-05-26 22:37:44 +0000121 }
122 return fragments.build();
123 }
124
125 @Override
126 public String extractTag(SkyKey skyKey) {
127 return null;
128 }
129
130 private static final class BuildConfigurationFunctionException extends SkyFunctionException {
131 public BuildConfigurationFunctionException(InvalidConfigurationException e) {
132 super(e, Transience.PERSISTENT);
133 }
134 }
135}