Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 1 | // Copyright 2017 The Bazel Authors. All rights reserved. |
| 2 | // |
| 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. |
| 14 | |
| 15 | package com.google.devtools.build.lib.skyframe; |
| 16 | |
Fabian Meumertzheim | 49af3d3 | 2023-08-15 09:29:05 -0700 | [diff] [blame] | 17 | import static com.google.common.collect.ImmutableSet.toImmutableSet; |
| 18 | |
salma-samy | 64554a3 | 2023-07-18 04:42:43 -0700 | [diff] [blame] | 19 | import com.google.common.collect.ImmutableMap; |
emilyguo | 21b0ba0 | 2022-03-16 17:07:40 -0700 | [diff] [blame] | 20 | import com.google.devtools.build.lib.bugreport.BugReport; |
Googler | de9d1f5 | 2023-11-06 09:28:56 -0800 | [diff] [blame] | 21 | import com.google.devtools.build.lib.skyframe.serialization.VisibleForSerialization; |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 22 | import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; |
| 23 | import com.google.devtools.build.skyframe.AbstractSkyKey; |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.skyframe.SkyFunction; |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 25 | import com.google.devtools.build.skyframe.SkyFunctionName; |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 26 | import com.google.devtools.build.skyframe.SkyKey; |
| 27 | import com.google.devtools.build.skyframe.SkyValue; |
Googler | 1831905 | 2022-10-14 14:27:35 -0700 | [diff] [blame] | 28 | import com.google.devtools.build.skyframe.SkyframeLookupResult; |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 29 | import java.util.Map; |
Fabian Meumertzheim | ced7998 | 2024-05-24 16:00:49 -0700 | [diff] [blame] | 30 | import java.util.Optional; |
Fabian Meumertzheim | 49af3d3 | 2023-08-15 09:29:05 -0700 | [diff] [blame] | 31 | import java.util.Set; |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 32 | import javax.annotation.Nullable; |
| 33 | |
| 34 | /** |
| 35 | * Skyframe function that provides the effective value for a client environment variable. This will |
| 36 | * either be the value coming from the default client environment, or the value coming from the |
| 37 | * --action_env flag, if the variable's value is explicitly set. |
| 38 | */ |
| 39 | public final class ActionEnvironmentFunction implements SkyFunction { |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 40 | @Nullable |
| 41 | @Override |
| 42 | public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { |
| 43 | Map<String, String> actionEnv = PrecomputedValue.ACTION_ENV.get(env); |
| 44 | String key = (String) skyKey.argument(); |
| 45 | if (actionEnv.containsKey(key) && actionEnv.get(key) != null) { |
| 46 | return new ClientEnvironmentValue(actionEnv.get(key)); |
| 47 | } |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 48 | return env.getValue(ClientEnvironmentFunction.key(key)); |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 49 | } |
| 50 | |
salma-samy | 64554a3 | 2023-07-18 04:42:43 -0700 | [diff] [blame] | 51 | /** Returns the SkyKey to invoke this function for the environment variable {@code variable}. */ |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 52 | public static Key key(String variable) { |
| 53 | return Key.create(variable); |
| 54 | } |
| 55 | |
Googler | de9d1f5 | 2023-11-06 09:28:56 -0800 | [diff] [blame] | 56 | @VisibleForSerialization |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 57 | @AutoCodec |
| 58 | static class Key extends AbstractSkyKey<String> { |
Googler | 1a5c316 | 2023-03-16 10:46:51 -0700 | [diff] [blame] | 59 | private static final SkyKeyInterner<Key> interner = SkyKey.newInterner(); |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 60 | |
| 61 | private Key(String arg) { |
| 62 | super(arg); |
| 63 | } |
| 64 | |
Googler | 0e9b146 | 2024-01-29 08:29:26 -0800 | [diff] [blame] | 65 | private static Key create(String arg) { |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 66 | return interner.intern(new Key(arg)); |
| 67 | } |
| 68 | |
Googler | 0e9b146 | 2024-01-29 08:29:26 -0800 | [diff] [blame] | 69 | @VisibleForSerialization |
| 70 | @AutoCodec.Interner |
| 71 | static Key intern(Key key) { |
| 72 | return interner.intern(key); |
| 73 | } |
| 74 | |
janakr | 5fb2a48 | 2018-03-02 17:48:57 -0800 | [diff] [blame] | 75 | @Override |
| 76 | public SkyFunctionName functionName() { |
| 77 | return SkyFunctions.ACTION_ENVIRONMENT_VARIABLE; |
| 78 | } |
Googler | 1a5c316 | 2023-03-16 10:46:51 -0700 | [diff] [blame] | 79 | |
| 80 | @Override |
| 81 | public SkyKeyInterner<Key> getSkyKeyInterner() { |
| 82 | return interner; |
| 83 | } |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | /** |
| 87 | * Returns a map of environment variable key => values, getting them from Skyframe. Returns null |
| 88 | * if and only if some dependencies from Skyframe still need to be resolved. |
| 89 | */ |
emilyguo | 21b0ba0 | 2022-03-16 17:07:40 -0700 | [diff] [blame] | 90 | @Nullable |
Fabian Meumertzheim | ced7998 | 2024-05-24 16:00:49 -0700 | [diff] [blame] | 91 | public static ImmutableMap<String, Optional<String>> getEnvironmentView( |
| 92 | Environment env, Set<String> keys) throws InterruptedException { |
Fabian Meumertzheim | 49af3d3 | 2023-08-15 09:29:05 -0700 | [diff] [blame] | 93 | var skyframeKeys = keys.stream().map(ActionEnvironmentFunction::key).collect(toImmutableSet()); |
Googler | 1831905 | 2022-10-14 14:27:35 -0700 | [diff] [blame] | 94 | SkyframeLookupResult values = env.getValuesAndExceptions(skyframeKeys); |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 95 | if (env.valuesMissing()) { |
| 96 | return null; |
| 97 | } |
salma-samy | 64554a3 | 2023-07-18 04:42:43 -0700 | [diff] [blame] | 98 | |
Fabian Meumertzheim | ced7998 | 2024-05-24 16:00:49 -0700 | [diff] [blame] | 99 | ImmutableMap.Builder<String, Optional<String>> result = |
| 100 | ImmutableMap.builderWithExpectedSize(skyframeKeys.size()); |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 101 | for (SkyKey key : skyframeKeys) { |
Googler | 1831905 | 2022-10-14 14:27:35 -0700 | [diff] [blame] | 102 | ClientEnvironmentValue value = (ClientEnvironmentValue) values.get(key); |
emilyguo | 21b0ba0 | 2022-03-16 17:07:40 -0700 | [diff] [blame] | 103 | if (value == null) { |
| 104 | BugReport.sendBugReport( |
| 105 | new IllegalStateException( |
| 106 | "ClientEnvironmentValue " + key + " was missing, this should never happen")); |
| 107 | return null; |
| 108 | } |
Fabian Meumertzheim | ced7998 | 2024-05-24 16:00:49 -0700 | [diff] [blame] | 109 | result.put(key.argument().toString(), Optional.ofNullable(value.getValue())); |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 110 | } |
salma-samy | 64554a3 | 2023-07-18 04:42:43 -0700 | [diff] [blame] | 111 | return result.buildOrThrow(); |
Damien Martin-Guillerez | 777f3af | 2017-02-08 17:22:02 +0000 | [diff] [blame] | 112 | } |
| 113 | } |