From 777f3afea4195e094d45bdfc317b236146117ff7 Mon Sep 17 00:00:00 2001 From: Damien Martin-Guillerez Date: Wed, 8 Feb 2017 17:22:02 +0000 Subject: Introduce a Skyframe function: ActionEnvironmentFunction ActionEnvironmentFunction returns the list of environment variable with the one overwritten by --action_env being replaced. This let other Skyframe function declares dependency to any value of the environment and being influenced by the --action_env flag. This will be used to declare dependency of remote repositories on environment variables (step 3 of https://bazel.build/designs/2016/10/18/repository-invalidation.html) -- Change-Id: I1ed3fb6f48e8e17d4d64c903fccecb6ed7596350 Reviewed-on: https://cr.bazel.build/7974 PiperOrigin-RevId: 146918603 MOS_MIGRATED_REVID=146918603 --- .../build/lib/runtime/CommandEnvironment.java | 4 +- .../lib/skyframe/ActionEnvironmentFunction.java | 78 ++++++++++++++++++++++ .../build/lib/skyframe/PrecomputedValue.java | 3 + .../devtools/build/lib/skyframe/SkyFunctions.java | 2 + .../build/lib/skyframe/SkyframeExecutor.java | 15 +++++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/google/devtools/build/lib/skyframe/ActionEnvironmentFunction.java (limited to 'src/main') diff --git a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java index 29bf5a53c7..3590138b5c 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/CommandEnvironment.java @@ -477,9 +477,7 @@ public final class CommandEnvironment { getWorkingDirectory(), defaultsPackageContents, getCommandId(), - // TODO(bazel-team): this optimization disallows rule-specified additional dependencies - // on the client environment! - getWhitelistedClientEnv(), + clientEnv, timestampGranularityMonitor, options); } diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionEnvironmentFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionEnvironmentFunction.java new file mode 100644 index 0000000000..ea4cde03df --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionEnvironmentFunction.java @@ -0,0 +1,78 @@ +// Copyright 2017 The Bazel Authors. 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.skyframe; + +import com.google.common.collect.ImmutableList; +import com.google.devtools.build.skyframe.SkyFunction; +import com.google.devtools.build.skyframe.SkyKey; +import com.google.devtools.build.skyframe.SkyValue; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * Skyframe function that provides the effective value for a client environment variable. This will + * either be the value coming from the default client environment, or the value coming from the + * --action_env flag, if the variable's value is explicitly set. + */ +public final class ActionEnvironmentFunction implements SkyFunction { + + @Nullable + @Override + public String extractTag(SkyKey skyKey) { + return null; + } + + @Nullable + @Override + public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException { + Map actionEnv = PrecomputedValue.ACTION_ENV.get(env); + String key = (String) skyKey.argument(); + if (actionEnv.containsKey(key) && actionEnv.get(key) != null) { + return new ClientEnvironmentValue(actionEnv.get(key)); + } + return env.getValue(SkyKey.create(SkyFunctions.CLIENT_ENVIRONMENT_VARIABLE, key)); + } + + /** @return the SkyKey to invoke this function for the environment variable {@code variable}. */ + public static SkyKey key(String variable) { + return SkyKey.create(SkyFunctions.ACTION_ENVIRONMENT_VARIABLE, variable); + } + + /** + * Returns a map of environment variable key => values, getting them from Skyframe. Returns null + * if and only if some dependencies from Skyframe still need to be resolved. + */ + public static Map getEnvironmentView(Environment env, Iterable keys) + throws InterruptedException { + ImmutableList.Builder skyframeKeysBuilder = ImmutableList.builder(); + for (String key : keys) { + skyframeKeysBuilder.add(key(key)); + } + ImmutableList skyframeKeys = skyframeKeysBuilder.build(); + Map values = env.getValues(skyframeKeys); + if (env.valuesMissing()) { + return null; + } + // To return the initial order and support null values, we use a LinkedHashMap. + LinkedHashMap result = new LinkedHashMap<>(); + for (SkyKey key : skyframeKeys) { + ClientEnvironmentValue value = (ClientEnvironmentValue) values.get(key); + result.put(key.argument().toString(), value.getValue()); + } + return Collections.unmodifiableMap(result); + } +} diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java index 05b9277789..a53475a7ff 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/PrecomputedValue.java @@ -83,6 +83,9 @@ public final class PrecomputedValue implements SkyValue { static final Precomputed BUILD_ID = new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "build_id")); + static final Precomputed> ACTION_ENV = + new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "action_env")); + static final Precomputed WORKSPACE_STATUS_KEY = new Precomputed<>(SkyKey.create(SkyFunctions.PRECOMPUTED, "workspace_status_action")); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java index 3e138adaff..476e313a8a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyFunctions.java @@ -24,6 +24,8 @@ public final class SkyFunctions { public static final SkyFunctionName PRECOMPUTED = SkyFunctionName.create("PRECOMPUTED"); public static final SkyFunctionName CLIENT_ENVIRONMENT_VARIABLE = SkyFunctionName.create("CLIENT_ENVIRONMENT_VARIABLE"); + public static final SkyFunctionName ACTION_ENVIRONMENT_VARIABLE = + SkyFunctionName.create("ACTION_ENVIRONMENT_VARIABLE"); public static final SkyFunctionName FILE_STATE = SkyFunctionName.create("FILE_STATE"); public static final SkyFunctionName DIRECTORY_LISTING_STATE = SkyFunctionName.create("DIRECTORY_LISTING_STATE"); diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 06017becd6..25c087de7a 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java @@ -146,10 +146,13 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; @@ -350,6 +353,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { ImmutableMap.Builder map = ImmutableMap.builder(); map.put(SkyFunctions.PRECOMPUTED, new PrecomputedFunction()); map.put(SkyFunctions.CLIENT_ENVIRONMENT_VARIABLE, new ClientEnvironmentFunction(clientEnv)); + map.put(SkyFunctions.ACTION_ENVIRONMENT_VARIABLE, new ActionEnvironmentFunction()); map.put(SkyFunctions.FILE_STATE, new FileStateFunction(tsgm, externalFilesHelper)); map.put(SkyFunctions.DIRECTORY_LISTING_STATE, new DirectoryListingStateFunction(externalFilesHelper)); @@ -940,6 +944,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { String defaultsPackageContents, UUID commandId, Map clientEnv, + Map actionEnv, TimestampGranularityMonitor tsgm) { Preconditions.checkNotNull(pkgLocator); Preconditions.checkNotNull(tsgm); @@ -948,6 +953,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { this.tsgm.set(tsgm); maybeInjectPrecomputedValuesForAnalysis(); setCommandId(commandId); + PrecomputedValue.ACTION_ENV.set(injectable(), actionEnv); this.clientEnv.set(clientEnv); setBlacklistedPackagePrefixesFile(getBlacklistedPackagePrefixesFile()); setShowLoadingProgress(packageCacheOptions.showLoadingProgress); @@ -1699,6 +1705,14 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { TimestampGranularityMonitor tsgm, OptionsClassProvider options) throws InterruptedException, AbruptExitException { + // ImmutableMap does not support null values, so use a LinkedHashMap instead. + LinkedHashMap actionEnvironment = new LinkedHashMap<>(); + BuildConfiguration.Options opt = options.getOptions(BuildConfiguration.Options.class); + if (opt != null) { + for (Entry v : opt.actionEnvironment) { + actionEnvironment.put(v.getKey(), v.getValue()); + } + } preparePackageLoading( createPackageLocator( eventHandler, @@ -1710,6 +1724,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory { defaultsPackageContents, commandId, clientEnv, + Collections.unmodifiableMap(actionEnvironment), tsgm); setDeletedPackages(packageCacheOptions.getDeletedPackages()); -- cgit v1.2.3