Damien Martin-Guillerez | f88f4d8 | 2015-09-25 13:56:55 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 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.runtime; |
| 16 | |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 17 | import static com.google.devtools.build.lib.profiler.AutoProfiler.profiled; |
| 18 | |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 19 | import com.google.common.annotations.VisibleForTesting; |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 20 | import com.google.common.collect.ImmutableList; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 21 | import com.google.common.collect.ImmutableSet; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 22 | import com.google.common.eventbus.EventBus; |
Ulf Adams | d5500a2 | 2016-11-16 09:54:55 +0000 | [diff] [blame] | 23 | import com.google.devtools.build.lib.actions.ActionInput; |
Ulf Adams | 5b9009b | 2015-09-24 09:52:53 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.actions.PackageRootResolver; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 25 | import com.google.devtools.build.lib.actions.cache.ActionCache; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 26 | import com.google.devtools.build.lib.analysis.BlazeDirectories; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 27 | import com.google.devtools.build.lib.analysis.BuildView; |
Ulf Adams | 5b9009b | 2015-09-24 09:52:53 +0000 | [diff] [blame] | 28 | import com.google.devtools.build.lib.analysis.SkyframePackageRootResolver; |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 29 | import com.google.devtools.build.lib.analysis.config.BuildConfiguration; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 30 | import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection; |
| 31 | import com.google.devtools.build.lib.analysis.config.BuildOptions; |
| 32 | import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 33 | import com.google.devtools.build.lib.cmdline.Label; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 34 | import com.google.devtools.build.lib.events.Reporter; |
Philipp Wollermann | 49c20aa | 2016-08-25 12:59:52 +0000 | [diff] [blame] | 35 | import com.google.devtools.build.lib.exec.ActionInputPrefetcher; |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 36 | import com.google.devtools.build.lib.exec.OutputService; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 37 | import com.google.devtools.build.lib.packages.NoSuchThingException; |
| 38 | import com.google.devtools.build.lib.packages.Target; |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 39 | import com.google.devtools.build.lib.pkgcache.PackageCacheOptions; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 40 | import com.google.devtools.build.lib.pkgcache.PackageManager; |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 41 | import com.google.devtools.build.lib.pkgcache.TargetPatternEvaluator; |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 42 | import com.google.devtools.build.lib.profiler.AutoProfiler; |
| 43 | import com.google.devtools.build.lib.profiler.ProfilerTask; |
Ulf Adams | 3d67e00 | 2016-03-29 16:23:01 +0000 | [diff] [blame] | 44 | import com.google.devtools.build.lib.skyframe.SkyframeBuildView; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 45 | import com.google.devtools.build.lib.skyframe.SkyframeExecutor; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 46 | import com.google.devtools.build.lib.util.AbruptExitException; |
| 47 | import com.google.devtools.build.lib.util.ExitCode; |
Mark Schaller | 6df8179 | 2015-12-10 18:47:47 +0000 | [diff] [blame] | 48 | import com.google.devtools.build.lib.util.Preconditions; |
Ulf Adams | c73051c6 | 2016-03-23 09:18:13 +0000 | [diff] [blame] | 49 | import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor; |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 50 | import com.google.devtools.build.lib.vfs.FileSystemUtils; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 51 | import com.google.devtools.build.lib.vfs.Path; |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 52 | import com.google.devtools.build.lib.vfs.PathFragment; |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 53 | import com.google.devtools.common.options.OptionPriority; |
Ulf Adams | de14ade | 2016-10-14 14:20:31 +0000 | [diff] [blame] | 54 | import com.google.devtools.common.options.OptionsClassProvider; |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 55 | import com.google.devtools.common.options.OptionsParser; |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 56 | import com.google.devtools.common.options.OptionsParsingException; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 57 | import com.google.devtools.common.options.OptionsProvider; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 58 | import java.io.IOException; |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 59 | import java.util.Collection; |
| 60 | import java.util.Collections; |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 61 | import java.util.List; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 62 | import java.util.Map; |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 63 | import java.util.Set; |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 64 | import java.util.TreeMap; |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 65 | import java.util.TreeSet; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 66 | import java.util.UUID; |
Ulf Adams | 88f643c | 2015-09-17 10:55:52 +0000 | [diff] [blame] | 67 | import java.util.concurrent.atomic.AtomicReference; |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 68 | import javax.annotation.Nullable; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 69 | |
| 70 | /** |
| 71 | * Encapsulates the state needed for a single command. The environment is dropped when the current |
| 72 | * command is done and all corresponding objects are garbage collected. |
| 73 | */ |
| 74 | public final class CommandEnvironment { |
| 75 | private final BlazeRuntime runtime; |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 76 | private final BlazeWorkspace workspace; |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 77 | private final BlazeDirectories directories; |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 78 | |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 79 | private UUID commandId; // Unique identifier for the command being run |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 80 | private final Reporter reporter; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 81 | private final EventBus eventBus; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 82 | private final BlazeModule.ModuleEnvironment blazeModuleEnvironment; |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 83 | private final Map<String, String> clientEnv = new TreeMap<>(); |
| 84 | private final Set<String> visibleClientEnv = new TreeSet<>(); |
Ulf Adams | c73051c6 | 2016-03-23 09:18:13 +0000 | [diff] [blame] | 85 | private final TimestampGranularityMonitor timestampGranularityMonitor; |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 86 | private final Thread commandThread; |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 87 | |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 88 | private String[] crashData; |
| 89 | |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 90 | private PathFragment relativeWorkingDirectory = PathFragment.EMPTY_FRAGMENT; |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 91 | private long commandStartTime; |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 92 | private OutputService outputService; |
Ulf Adams | d5500a2 | 2016-11-16 09:54:55 +0000 | [diff] [blame] | 93 | private ActionInputPrefetcher actionInputPrefetcher; |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 94 | private Path workingDirectory; |
Ulf Adams | 47cb916 | 2015-09-18 08:12:30 +0000 | [diff] [blame] | 95 | |
Ulf Adams | 3877ebd | 2016-11-15 10:22:59 +0000 | [diff] [blame] | 96 | private String commandName; |
| 97 | private OptionsProvider options; |
Ulf Adams | a0e3af4 | 2016-10-31 16:52:48 +0000 | [diff] [blame] | 98 | |
Ulf Adams | 88f643c | 2015-09-17 10:55:52 +0000 | [diff] [blame] | 99 | private AtomicReference<AbruptExitException> pendingException = new AtomicReference<>(); |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 100 | |
| 101 | private class BlazeModuleEnvironment implements BlazeModule.ModuleEnvironment { |
| 102 | @Override |
Ulf Adams | ae90bc9 | 2015-09-18 09:18:58 +0000 | [diff] [blame] | 103 | public Path getFileFromWorkspace(Label label) |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 104 | throws NoSuchThingException, InterruptedException, IOException { |
| 105 | Target target = getPackageManager().getTarget(reporter, label); |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 106 | return (outputService != null) |
| 107 | ? outputService.stageTool(target) |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 108 | : target.getPackage().getPackageDirectory().getRelative(target.getName()); |
| 109 | } |
| 110 | |
| 111 | @Override |
| 112 | public void exit(AbruptExitException exception) { |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 113 | Preconditions.checkNotNull(exception); |
| 114 | Preconditions.checkNotNull(exception.getExitCode()); |
| 115 | if (pendingException.compareAndSet(null, exception)) { |
| 116 | // There was no exception, so we're the first one to ask for an exit. Interrupt the command. |
| 117 | commandThread.interrupt(); |
| 118 | } |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 119 | } |
| 120 | } |
| 121 | |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 122 | /** |
| 123 | * Creates a new command environment which can be used for executing commands for the given |
| 124 | * runtime in the given workspace, which will publish events on the given eventBus. The |
| 125 | * commandThread passed is interrupted when a module requests an early exit. |
| 126 | */ |
| 127 | CommandEnvironment( |
| 128 | BlazeRuntime runtime, BlazeWorkspace workspace, EventBus eventBus, Thread commandThread) { |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 129 | this.runtime = runtime; |
Ulf Adams | 69cc003 | 2016-03-30 13:52:25 +0000 | [diff] [blame] | 130 | this.workspace = workspace; |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 131 | this.directories = workspace.getDirectories(); |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 132 | this.commandId = null; // Will be set once we get the client environment |
Ulf Adams | 39b18ca | 2015-11-02 08:45:26 +0000 | [diff] [blame] | 133 | this.reporter = new Reporter(); |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 134 | this.eventBus = eventBus; |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 135 | this.commandThread = commandThread; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 136 | this.blazeModuleEnvironment = new BlazeModuleEnvironment(); |
Ulf Adams | c73051c6 | 2016-03-23 09:18:13 +0000 | [diff] [blame] | 137 | this.timestampGranularityMonitor = new TimestampGranularityMonitor(runtime.getClock()); |
| 138 | // Record the command's starting time again, for use by |
| 139 | // TimestampGranularityMonitor.waitForTimestampGranularity(). |
| 140 | // This should be done as close as possible to the start of |
| 141 | // the command's execution. |
| 142 | timestampGranularityMonitor.setCommandStartTime(); |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 143 | |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 144 | // TODO(ulfjack): We don't call beforeCommand() in tests, but rely on workingDirectory being set |
| 145 | // in setupPackageCache(). This leads to NPE if we don't set it here. |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 146 | this.workingDirectory = directories.getWorkspace(); |
Ulf Adams | 69cc003 | 2016-03-30 13:52:25 +0000 | [diff] [blame] | 147 | |
| 148 | workspace.getSkyframeExecutor().setEventBus(eventBus); |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | public BlazeRuntime getRuntime() { |
| 152 | return runtime; |
| 153 | } |
| 154 | |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 155 | public BlazeWorkspace getBlazeWorkspace() { |
| 156 | return workspace; |
| 157 | } |
| 158 | |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 159 | public BlazeDirectories getDirectories() { |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 160 | return directories; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 161 | } |
| 162 | |
| 163 | /** |
| 164 | * Returns the reporter for events. |
| 165 | */ |
| 166 | public Reporter getReporter() { |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 167 | return reporter; |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 168 | } |
| 169 | |
| 170 | public EventBus getEventBus() { |
| 171 | return eventBus; |
| 172 | } |
| 173 | |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 174 | public BlazeModule.ModuleEnvironment getBlazeModuleEnvironment() { |
| 175 | return blazeModuleEnvironment; |
| 176 | } |
| 177 | |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 178 | /** |
| 179 | * Return an unmodifiable view of the blaze client's environment when it invoked the current |
| 180 | * command. |
| 181 | */ |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 182 | public Map<String, String> getClientEnv() { |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 183 | return Collections.unmodifiableMap(clientEnv); |
| 184 | } |
| 185 | |
Ulf Adams | 3877ebd | 2016-11-15 10:22:59 +0000 | [diff] [blame] | 186 | public String getCommandName() { |
| 187 | return commandName; |
| 188 | } |
| 189 | |
| 190 | public OptionsProvider getOptions() { |
Ulf Adams | a0e3af4 | 2016-10-31 16:52:48 +0000 | [diff] [blame] | 191 | return options; |
| 192 | } |
| 193 | |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 194 | /** |
Klaus Aehlig | b8d0902 | 2016-09-20 13:39:08 +0000 | [diff] [blame] | 195 | * Return an ordered version of the client environment restricted to those variables whitelisted |
| 196 | * by the command-line options to be inheritable by actions. |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 197 | */ |
Klaus Aehlig | b8d0902 | 2016-09-20 13:39:08 +0000 | [diff] [blame] | 198 | public Map<String, String> getWhitelistedClientEnv() { |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 199 | Map<String, String> visibleEnv = new TreeMap<>(); |
| 200 | for (String var : visibleClientEnv) { |
| 201 | String value = clientEnv.get(var); |
| 202 | if (value != null) { |
| 203 | visibleEnv.put(var, value); |
| 204 | } |
| 205 | } |
| 206 | return Collections.unmodifiableMap(visibleEnv); |
| 207 | } |
| 208 | |
Ulf Adams | 8d2e60d | 2015-09-17 08:11:24 +0000 | [diff] [blame] | 209 | @VisibleForTesting |
| 210 | void updateClientEnv(List<Map.Entry<String, String>> clientEnvList, boolean ignoreClientEnv) { |
| 211 | Preconditions.checkState(clientEnv.isEmpty()); |
| 212 | |
| 213 | Collection<Map.Entry<String, String>> env = |
| 214 | ignoreClientEnv ? System.getenv().entrySet() : clientEnvList; |
| 215 | for (Map.Entry<String, String> entry : env) { |
| 216 | clientEnv.put(entry.getKey(), entry.getValue()); |
| 217 | } |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 218 | // Try to set the clientId from the client environment. |
| 219 | if (commandId == null) { |
| 220 | String uuidString = clientEnv.get("BAZEL_INTERNAL_INVOCATION_ID"); |
| 221 | if (uuidString != null) { |
| 222 | try { |
| 223 | commandId = UUID.fromString(uuidString); |
| 224 | } catch (IllegalArgumentException e) { |
| 225 | // String was malformed, so we will resort to generating a random UUID |
| 226 | } |
| 227 | } |
| 228 | } |
| 229 | if (commandId == null) { |
| 230 | // We have been provided with the client environment, but it didn't contain |
| 231 | // the invocation id; hence generate our own. |
| 232 | commandId = UUID.randomUUID(); |
| 233 | } |
| 234 | setCommandIdInCrashData(); |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 235 | } |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 236 | |
Ulf Adams | c73051c6 | 2016-03-23 09:18:13 +0000 | [diff] [blame] | 237 | public TimestampGranularityMonitor getTimestampGranularityMonitor() { |
| 238 | return timestampGranularityMonitor; |
| 239 | } |
| 240 | |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 241 | public PackageManager getPackageManager() { |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 242 | return getSkyframeExecutor().getPackageManager(); |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 243 | } |
| 244 | |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 245 | public PathFragment getRelativeWorkingDirectory() { |
| 246 | return relativeWorkingDirectory; |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 247 | } |
| 248 | |
| 249 | /** |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 250 | * Creates and returns a new target pattern parser. |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 251 | */ |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 252 | public TargetPatternEvaluator newTargetPatternEvaluator() { |
| 253 | TargetPatternEvaluator result = getPackageManager().newTargetPatternEvaluator(); |
| 254 | result.updateOffset(relativeWorkingDirectory); |
| 255 | return result; |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 256 | } |
| 257 | |
Ulf Adams | 5b9009b | 2015-09-24 09:52:53 +0000 | [diff] [blame] | 258 | public PackageRootResolver getPackageRootResolver() { |
| 259 | return new SkyframePackageRootResolver(getSkyframeExecutor(), reporter); |
| 260 | } |
| 261 | |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 262 | /** |
| 263 | * Returns the UUID that Blaze uses to identify everything logged from the current build command. |
| 264 | * It's also used to invalidate Skyframe nodes that are specific to a certain invocation, such as |
| 265 | * the build info. |
| 266 | */ |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 267 | public UUID getCommandId() { |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 268 | if (commandId == null) { |
| 269 | // The commandId should not be requested before the beforeCommand is executed, as the |
| 270 | // commandId might be set through the client environment. However, to simplify testing, |
| 271 | // we set the id value before we throw the exception. |
| 272 | commandId = UUID.randomUUID(); |
| 273 | throw new IllegalArgumentException("Build Id requested before client environment provided"); |
| 274 | } |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 275 | return commandId; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 276 | } |
| 277 | |
| 278 | public SkyframeExecutor getSkyframeExecutor() { |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 279 | return workspace.getSkyframeExecutor(); |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 280 | } |
| 281 | |
Ulf Adams | 3d67e00 | 2016-03-29 16:23:01 +0000 | [diff] [blame] | 282 | public SkyframeBuildView getSkyframeBuildView() { |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 283 | return getSkyframeExecutor().getSkyframeBuildView(); |
Ulf Adams | 3d67e00 | 2016-03-29 16:23:01 +0000 | [diff] [blame] | 284 | } |
| 285 | |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 286 | /** |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 287 | * Returns the working directory of the server. |
| 288 | * |
| 289 | * <p>This is often the first entry on the {@code --package_path}, but not always. |
| 290 | * Callers should certainly not make this assumption. The Path returned may be null. |
| 291 | */ |
| 292 | public Path getWorkspace() { |
| 293 | return getDirectories().getWorkspace(); |
| 294 | } |
| 295 | |
| 296 | public String getWorkspaceName() { |
| 297 | Path workspace = getDirectories().getWorkspace(); |
| 298 | if (workspace == null) { |
| 299 | return ""; |
| 300 | } |
| 301 | return workspace.getBaseName(); |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * Returns if the client passed a valid workspace to be used for the build. |
| 306 | */ |
| 307 | public boolean inWorkspace() { |
| 308 | return getDirectories().inWorkspace(); |
| 309 | } |
| 310 | |
| 311 | /** |
| 312 | * Returns the output base directory associated with this Blaze server |
| 313 | * process. This is the base directory for shared Blaze state as well as tool |
| 314 | * and strategy specific subdirectories. |
| 315 | */ |
| 316 | public Path getOutputBase() { |
| 317 | return getDirectories().getOutputBase(); |
| 318 | } |
| 319 | |
| 320 | /** |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 321 | * Returns the execution root directory associated with this Blaze server |
| 322 | * process. This is where all input and output files visible to the actual |
| 323 | * build reside. |
| 324 | */ |
| 325 | public Path getExecRoot() { |
| 326 | return getDirectories().getExecRoot(); |
| 327 | } |
| 328 | |
| 329 | /** |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 330 | * Returns the working directory of the {@code blaze} client process. |
| 331 | * |
| 332 | * <p>This may be equal to {@code BlazeRuntime#getWorkspace()}, or beneath it. |
| 333 | * |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 334 | * @see #getWorkspace() |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 335 | */ |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 336 | public Path getWorkingDirectory() { |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 337 | return workingDirectory; |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 338 | } |
| 339 | |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 340 | /** |
| 341 | * @return the OutputService in use, or null if none. |
| 342 | */ |
| 343 | public OutputService getOutputService() { |
| 344 | return outputService; |
| 345 | } |
| 346 | |
Ulf Adams | d5500a2 | 2016-11-16 09:54:55 +0000 | [diff] [blame] | 347 | public ActionInputPrefetcher getActionInputPrefetcher() { |
| 348 | return actionInputPrefetcher == null ? ActionInputPrefetcher.NONE : actionInputPrefetcher; |
Philipp Wollermann | 49c20aa | 2016-08-25 12:59:52 +0000 | [diff] [blame] | 349 | } |
| 350 | |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 351 | public ActionCache getPersistentActionCache() throws IOException { |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 352 | return workspace.getPersistentActionCache(reporter); |
| 353 | } |
| 354 | |
| 355 | /** |
Janak Ramakrishnan | 5e94673 | 2016-11-17 17:01:46 +0000 | [diff] [blame^] | 356 | * An array of String values useful if Blaze crashes. For now, just returns the build id as soon |
| 357 | * as it is determined. |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 358 | */ |
Janak Ramakrishnan | 5e94673 | 2016-11-17 17:01:46 +0000 | [diff] [blame^] | 359 | String[] getCrashData() { |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 360 | if (crashData == null) { |
| 361 | String buildId; |
| 362 | if (commandId == null) { |
| 363 | buildId = " (build id not set yet)"; |
| 364 | } else { |
| 365 | buildId = commandId + " (build id)"; |
| 366 | } |
Janak Ramakrishnan | 5e94673 | 2016-11-17 17:01:46 +0000 | [diff] [blame^] | 367 | crashData = new String[] {buildId}; |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 368 | } |
| 369 | return crashData; |
| 370 | } |
| 371 | |
| 372 | private void setCommandIdInCrashData() { |
| 373 | // Update the command id in the crash data, if it is already generated |
| 374 | if (crashData != null && crashData.length >= 2) { |
| 375 | crashData[1] = getCommandId() + " (build id)"; |
| 376 | } |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 377 | } |
| 378 | |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 379 | /** |
| 380 | * This method only exists for the benefit of InfoCommand, which needs to construct a {@link |
| 381 | * BuildConfigurationCollection} without running a full loading phase. Don't add any more clients; |
| 382 | * instead, we should change info so that it doesn't need the configuration. |
| 383 | */ |
| 384 | public BuildConfigurationCollection getConfigurations(OptionsProvider optionsProvider) |
| 385 | throws InvalidConfigurationException, InterruptedException { |
| 386 | BuildOptions buildOptions = runtime.createBuildOptions(optionsProvider); |
| 387 | boolean keepGoing = optionsProvider.getOptions(BuildView.Options.class).keepGoing; |
Ulf Adams | e5aaacf | 2015-09-24 12:40:30 +0000 | [diff] [blame] | 388 | return getSkyframeExecutor().createConfigurations(reporter, runtime.getConfigurationFactory(), |
Ulf Adams | f069d45b | 2016-04-15 07:54:24 +0000 | [diff] [blame] | 389 | buildOptions, ImmutableSet.<String>of(), keepGoing); |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 390 | } |
| 391 | |
| 392 | /** |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 393 | * Prevents any further interruption of this command by modules, and returns the final exit code |
| 394 | * from modules, or null if no modules requested an abrupt exit. |
| 395 | * |
| 396 | * <p>Always returns the same value on subsequent calls. |
| 397 | */ |
| 398 | @Nullable |
| 399 | private ExitCode finalizeExitCode() { |
| 400 | // Set the pending exception so that further calls to exit(AbruptExitException) don't lead to |
| 401 | // unwanted thread interrupts. |
| 402 | if (pendingException.compareAndSet(null, new AbruptExitException(null))) { |
| 403 | return null; |
| 404 | } |
| 405 | if (Thread.currentThread() == commandThread) { |
| 406 | // We may have interrupted the thread in the process, so clear the interrupted bit. |
| 407 | // Whether the command was interrupted or not, it's about to be over, so don't interrupt later |
| 408 | // things happening on this thread. |
| 409 | Thread.interrupted(); |
| 410 | } |
| 411 | // Extract the exit code (it can be null if someone has already called finalizeExitCode()). |
| 412 | return getPendingExitCode(); |
| 413 | } |
| 414 | |
| 415 | /** |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 416 | * Hook method called by the BlazeCommandDispatcher right before the dispatch |
| 417 | * of each command ends (while its outcome can still be modified). |
| 418 | */ |
| 419 | ExitCode precompleteCommand(ExitCode originalExit) { |
| 420 | eventBus.post(new CommandPrecompleteEvent(originalExit)); |
| 421 | // If Blaze did not suffer an infrastructure failure, check for errors in modules. |
| 422 | ExitCode exitCode = originalExit; |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 423 | ExitCode newExitCode = finalizeExitCode(); |
| 424 | if (!originalExit.isInfrastructureFailure() && newExitCode != null) { |
| 425 | exitCode = newExitCode; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 426 | } |
| 427 | return exitCode; |
| 428 | } |
| 429 | |
| 430 | /** |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 431 | * Returns the current exit code requested by modules, or null if no exit has been requested. |
| 432 | */ |
| 433 | @Nullable |
| 434 | public ExitCode getPendingExitCode() { |
| 435 | AbruptExitException exception = getPendingException(); |
| 436 | return exception == null ? null : exception.getExitCode(); |
| 437 | } |
| 438 | |
| 439 | /** |
| 440 | * Retrieves the exception currently queued by a Blaze module. |
| 441 | * |
| 442 | * <p>Prefer getPendingExitCode or throwPendingException where appropriate. |
| 443 | */ |
| 444 | public AbruptExitException getPendingException() { |
| 445 | return pendingException.get(); |
| 446 | } |
| 447 | |
| 448 | /** |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 449 | * Throws the exception currently queued by a Blaze module. |
| 450 | * |
| 451 | * <p>This should be called as often as is practical so that errors are reported as soon as |
| 452 | * possible. Ideally, we'd not need this, but the event bus swallows exceptions so we raise |
| 453 | * the exception this way. |
| 454 | */ |
| 455 | public void throwPendingException() throws AbruptExitException { |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 456 | AbruptExitException exception = getPendingException(); |
Ulf Adams | 88f643c | 2015-09-17 10:55:52 +0000 | [diff] [blame] | 457 | if (exception != null) { |
Michael Staib | 6e5e8fb | 2016-10-04 21:26:37 +0000 | [diff] [blame] | 458 | if (Thread.currentThread() == commandThread) { |
| 459 | // Throwing this exception counts as the requested interruption. Clear the interrupted bit. |
| 460 | Thread.interrupted(); |
| 461 | } |
Ulf Adams | 88f643c | 2015-09-17 10:55:52 +0000 | [diff] [blame] | 462 | throw exception; |
Ulf Adams | ca2d8d2 | 2015-09-16 13:00:45 +0000 | [diff] [blame] | 463 | } |
Ulf Adams | 8061302 | 2015-09-16 09:11:33 +0000 | [diff] [blame] | 464 | } |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 465 | |
| 466 | /** |
| 467 | * Initializes the package cache using the given options, and syncs the package cache. Also |
| 468 | * injects a defaults package using the options for the {@link BuildConfiguration}. |
| 469 | * |
| 470 | * @see DefaultsPackage |
| 471 | */ |
Ulf Adams | de14ade | 2016-10-14 14:20:31 +0000 | [diff] [blame] | 472 | public void setupPackageCache(OptionsClassProvider options, |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 473 | String defaultsPackageContents) throws InterruptedException, AbruptExitException { |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 474 | SkyframeExecutor skyframeExecutor = getSkyframeExecutor(); |
| 475 | if (!skyframeExecutor.hasIncrementalState()) { |
| 476 | skyframeExecutor.resetEvaluator(); |
| 477 | } |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 478 | skyframeExecutor.sync( |
| 479 | reporter, |
Ulf Adams | de14ade | 2016-10-14 14:20:31 +0000 | [diff] [blame] | 480 | options.getOptions(PackageCacheOptions.class), |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 481 | getOutputBase(), |
| 482 | getWorkingDirectory(), |
| 483 | defaultsPackageContents, |
| 484 | getCommandId(), |
| 485 | // TODO(bazel-team): this optimization disallows rule-specified additional dependencies |
| 486 | // on the client environment! |
Klaus Aehlig | b8d0902 | 2016-09-20 13:39:08 +0000 | [diff] [blame] | 487 | getWhitelistedClientEnv(), |
Ulf Adams | de14ade | 2016-10-14 14:20:31 +0000 | [diff] [blame] | 488 | timestampGranularityMonitor, |
| 489 | options); |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 490 | } |
| 491 | |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 492 | public void recordLastExecutionTime() { |
Ulf Adams | ab43b97 | 2016-03-30 12:23:50 +0000 | [diff] [blame] | 493 | workspace.recordLastExecutionTime(getCommandStartTime()); |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 494 | } |
| 495 | |
| 496 | public void recordCommandStartTime(long commandStartTime) { |
| 497 | this.commandStartTime = commandStartTime; |
| 498 | } |
| 499 | |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 500 | public long getCommandStartTime() { |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 501 | return commandStartTime; |
Ulf Adams | 3815b4c | 2015-09-18 07:34:13 +0000 | [diff] [blame] | 502 | } |
Ulf Adams | 47cb916 | 2015-09-18 08:12:30 +0000 | [diff] [blame] | 503 | |
Ulf Adams | c585530 | 2015-10-20 08:46:38 +0000 | [diff] [blame] | 504 | void setWorkingDirectory(Path workingDirectory) { |
| 505 | this.workingDirectory = workingDirectory; |
| 506 | } |
| 507 | |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 508 | /** |
| 509 | * Hook method called by the BlazeCommandDispatcher prior to the dispatch of |
| 510 | * each command. |
| 511 | * |
| 512 | * @param options The CommonCommandOptions used by every command. |
| 513 | * @throws AbruptExitException if this command is unsuitable to be run as specified |
| 514 | */ |
| 515 | void beforeCommand(Command command, OptionsParser optionsParser, |
Lukacs Berki | 2896dc0 | 2016-07-07 07:55:04 +0000 | [diff] [blame] | 516 | CommonCommandOptions options, long execStartTimeNanos, long waitTimeInMs) |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 517 | throws AbruptExitException { |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 518 | commandStartTime -= options.startupTime; |
Ulf Adams | de14ade | 2016-10-14 14:20:31 +0000 | [diff] [blame] | 519 | if (runtime.getStartupOptionsProvider().getOptions(BlazeServerStartupOptions.class).watchFS) { |
| 520 | try { |
| 521 | // TODO(ulfjack): Get rid of the startup option and drop this code. |
| 522 | optionsParser.parse("--watchfs"); |
| 523 | } catch (OptionsParsingException e) { |
| 524 | // This should never happen. |
| 525 | throw new IllegalStateException(e); |
| 526 | } |
| 527 | } |
Ulf Adams | 3877ebd | 2016-11-15 10:22:59 +0000 | [diff] [blame] | 528 | this.commandName = command.name(); |
Ulf Adams | a0e3af4 | 2016-10-31 16:52:48 +0000 | [diff] [blame] | 529 | this.options = optionsParser; |
Ulf Adams | b514610 | 2015-10-20 08:57:26 +0000 | [diff] [blame] | 530 | |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 531 | eventBus.post(new GotOptionsEvent(runtime.getStartupOptionsProvider(), optionsParser)); |
| 532 | throwPendingException(); |
| 533 | |
| 534 | outputService = null; |
| 535 | BlazeModule outputModule = null; |
Philipp Wollermann | 49c20aa | 2016-08-25 12:59:52 +0000 | [diff] [blame] | 536 | ImmutableList.Builder<ActionInputPrefetcher> prefetchersBuilder = ImmutableList.builder(); |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 537 | for (BlazeModule module : runtime.getBlazeModules()) { |
| 538 | OutputService moduleService = module.getOutputService(); |
| 539 | if (moduleService != null) { |
| 540 | if (outputService != null) { |
| 541 | throw new IllegalStateException(String.format( |
| 542 | "More than one module (%s and %s) returns an output service", |
| 543 | module.getClass(), outputModule.getClass())); |
| 544 | } |
| 545 | outputService = moduleService; |
| 546 | outputModule = module; |
| 547 | } |
Philipp Wollermann | 49c20aa | 2016-08-25 12:59:52 +0000 | [diff] [blame] | 548 | |
| 549 | ActionInputPrefetcher actionInputPrefetcher = module.getPrefetcher(); |
| 550 | if (actionInputPrefetcher != null) { |
| 551 | prefetchersBuilder.add(actionInputPrefetcher); |
| 552 | } |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 553 | } |
Ulf Adams | d5500a2 | 2016-11-16 09:54:55 +0000 | [diff] [blame] | 554 | final ImmutableList<ActionInputPrefetcher> actionInputPrefetchers = prefetchersBuilder.build(); |
| 555 | actionInputPrefetcher = |
| 556 | new ActionInputPrefetcher() { |
| 557 | @Override |
| 558 | public void prefetchFile(ActionInput input) { |
| 559 | for (ActionInputPrefetcher prefetcher : actionInputPrefetchers) { |
| 560 | prefetcher.prefetchFile(input); |
| 561 | } |
| 562 | } |
| 563 | }; |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 564 | |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 565 | SkyframeExecutor skyframeExecutor = getSkyframeExecutor(); |
Eric Fellheimer | f3b43af | 2015-11-13 19:51:20 +0000 | [diff] [blame] | 566 | skyframeExecutor.setOutputService(outputService); |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 567 | |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 568 | // Ensure that the working directory will be under the workspace directory. |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 569 | Path workspace = getWorkspace(); |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 570 | Path workingDirectory; |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 571 | if (inWorkspace()) { |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 572 | workingDirectory = workspace.getRelative(options.clientCwd); |
| 573 | } else { |
Ulf Adams | 94b72db | 2016-03-30 11:58:37 +0000 | [diff] [blame] | 574 | workspace = FileSystemUtils.getWorkingDirectory(getDirectories().getFileSystem()); |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 575 | workingDirectory = workspace; |
| 576 | } |
Ulf Adams | 08663e6 | 2016-02-12 09:59:22 +0000 | [diff] [blame] | 577 | this.relativeWorkingDirectory = workingDirectory.relativeTo(workspace); |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 578 | this.workingDirectory = workingDirectory; |
| 579 | |
| 580 | updateClientEnv(options.clientEnv, options.ignoreClientEnv); |
| 581 | |
| 582 | // Fail fast in the case where a Blaze command forgets to install the package path correctly. |
| 583 | skyframeExecutor.setActive(false); |
| 584 | // Let skyframe figure out if it needs to store graph edges for this build. |
| 585 | skyframeExecutor.decideKeepIncrementalState( |
| 586 | runtime.getStartupOptionsProvider().getOptions(BlazeServerStartupOptions.class).batch, |
| 587 | optionsParser.getOptions(BuildView.Options.class)); |
| 588 | |
| 589 | // Start the performance and memory profilers. |
| 590 | runtime.beforeCommand(this, options, execStartTimeNanos); |
| 591 | |
| 592 | if (command.builds()) { |
| 593 | Map<String, String> testEnv = new TreeMap<>(); |
| 594 | for (Map.Entry<String, String> entry : |
| 595 | optionsParser.getOptions(BuildConfiguration.Options.class).testEnvironment) { |
| 596 | testEnv.put(entry.getKey(), entry.getValue()); |
| 597 | } |
| 598 | |
Klaus Aehlig | 6f33a1c | 2016-09-13 16:46:10 +0000 | [diff] [blame] | 599 | // Compute the set of environment variables that are whitelisted on the commandline |
| 600 | // for inheritence. |
| 601 | for (Map.Entry<String, String> entry : |
| 602 | optionsParser.getOptions(BuildConfiguration.Options.class).actionEnvironment) { |
| 603 | if (entry.getValue() == null) { |
| 604 | visibleClientEnv.add(entry.getKey()); |
| 605 | } else { |
| 606 | visibleClientEnv.remove(entry.getKey()); |
| 607 | } |
| 608 | } |
| 609 | |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 610 | try { |
| 611 | for (Map.Entry<String, String> entry : testEnv.entrySet()) { |
| 612 | if (entry.getValue() == null) { |
| 613 | String clientValue = clientEnv.get(entry.getKey()); |
| 614 | if (clientValue != null) { |
| 615 | optionsParser.parse(OptionPriority.SOFTWARE_REQUIREMENT, |
| 616 | "test environment variable from client environment", |
| 617 | ImmutableList.of( |
| 618 | "--test_env=" + entry.getKey() + "=" + clientEnv.get(entry.getKey()))); |
| 619 | } |
| 620 | } |
| 621 | } |
| 622 | } catch (OptionsParsingException e) { |
| 623 | throw new IllegalStateException(e); |
| 624 | } |
| 625 | } |
Ulf Adams | 50e7db6 | 2015-10-20 09:14:16 +0000 | [diff] [blame] | 626 | |
Lukacs Berki | 2896dc0 | 2016-07-07 07:55:04 +0000 | [diff] [blame] | 627 | eventBus.post(new CommandStartEvent( |
Klaus Aehlig | 88a590a | 2016-08-12 08:56:30 +0000 | [diff] [blame] | 628 | command.name(), getCommandId(), getClientEnv(), workingDirectory, getDirectories(), |
Lukacs Berki | 2896dc0 | 2016-07-07 07:55:04 +0000 | [diff] [blame] | 629 | waitTimeInMs + options.waitTime)); |
Ulf Adams | ebf1b2e | 2015-09-29 11:06:53 +0000 | [diff] [blame] | 630 | } |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 631 | |
Nathan Harmata | dd61520 | 2016-04-29 22:17:00 +0000 | [diff] [blame] | 632 | /** Returns the name of the file system we are writing output to. */ |
| 633 | public String determineOutputFileSystem() { |
| 634 | // If we have a fancy OutputService, this may be different between consecutive Blaze commands |
| 635 | // and so we need to compute it freshly. Otherwise, we can used the immutable value that's |
| 636 | // precomputed by our BlazeWorkspace. |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 637 | if (getOutputService() != null) { |
Nathan Harmata | dd61520 | 2016-04-29 22:17:00 +0000 | [diff] [blame] | 638 | try (AutoProfiler p = profiled("Finding output file system", ProfilerTask.INFO)) { |
| 639 | return getOutputService().getFilesSystemName(); |
| 640 | } |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 641 | } |
Nathan Harmata | dd61520 | 2016-04-29 22:17:00 +0000 | [diff] [blame] | 642 | return workspace.getOutputBaseFilesystemTypeName(); |
Ulf Adams | 706b7f2 | 2015-10-20 09:06:45 +0000 | [diff] [blame] | 643 | } |
Ulf Adams | 633f539 | 2015-09-15 11:13:08 +0000 | [diff] [blame] | 644 | } |