diff options
Diffstat (limited to 'src/main/java/com/google/devtools')
4 files changed, 88 insertions, 3 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ExecException.java b/src/main/java/com/google/devtools/build/lib/actions/ExecException.java index 9592880b3a..9c81cc22a1 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/ExecException.java +++ b/src/main/java/com/google/devtools/build/lib/actions/ExecException.java @@ -54,6 +54,12 @@ public abstract class ExecException extends Exception { public ExecException(String message) { this(message, false); } + + public ExecException(Throwable cause) { + super(cause); + this.catastrophe = false; + this.timedOut = false; + } public ExecException(String message, Throwable cause, boolean catastrophe) { super(message + ": " + cause.getMessage(), cause); diff --git a/src/main/java/com/google/devtools/build/lib/actions/UserExecException.java b/src/main/java/com/google/devtools/build/lib/actions/UserExecException.java index 7de2a13c95..d79d6f582e 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/UserExecException.java +++ b/src/main/java/com/google/devtools/build/lib/actions/UserExecException.java @@ -23,6 +23,10 @@ public class UserExecException extends ExecException { public UserExecException(String message) { super(message); } + + public UserExecException(Throwable cause) { + super(cause); + } public UserExecException(String message, boolean timedOut) { super(message, false, timedOut); diff --git a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java index 3af0e97d6c..b420b47848 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java +++ b/src/main/java/com/google/devtools/build/lib/rules/objc/ObjcConfiguration.java @@ -49,8 +49,16 @@ public class ObjcConfiguration extends BuildConfiguration.Fragment { "-Os", "-DNDEBUG=1", "-Wno-unused-variable", "-Winit-self", "-Wno-extra"); private static final String XCODE_VERSION_ENV_NAME = "XCODE_VERSION_OVERRIDE"; - private static final String IOS_SDK_VERSION_ENV_NAME = "IOS_SDK_VERSION_OVERRIDE"; - private static final String APPLE_SDK_PLATFORM_ENV_NAME = "APPLE_SDK_PLATFORM"; + /** + * Environment variable name for the iOS SDK version. If unset, uses the system default of the + * host. + **/ + public static final String IOS_SDK_VERSION_ENV_NAME = "IOS_SDK_VERSION_OVERRIDE"; + /** + * Environment variable name for the apple SDK platform. This should be set for all actions that + * require an apple SDK. The valid values consist of {@link Platform} names. + **/ + public static final String APPLE_SDK_PLATFORM_ENV_NAME = "APPLE_SDK_PLATFORM"; private final String iosSdkVersion; private final String iosMinimumOs; diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java index 5a90260bf2..64d3cd15f4 100644 --- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java +++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java @@ -13,6 +13,7 @@ // limitations under the License. package com.google.devtools.build.lib.standalone; +import com.google.common.collect.ImmutableMap; import com.google.devtools.build.lib.actions.ActionExecutionContext; import com.google.devtools.build.lib.actions.ExecException; import com.google.devtools.build.lib.actions.ExecutionStrategy; @@ -21,9 +22,11 @@ import com.google.devtools.build.lib.actions.Spawn; import com.google.devtools.build.lib.actions.SpawnActionContext; import com.google.devtools.build.lib.actions.UserExecException; import com.google.devtools.build.lib.cmdline.Label; +import com.google.devtools.build.lib.rules.objc.ObjcConfiguration; import com.google.devtools.build.lib.shell.AbnormalTerminationException; import com.google.devtools.build.lib.shell.Command; import com.google.devtools.build.lib.shell.CommandException; +import com.google.devtools.build.lib.shell.CommandResult; import com.google.devtools.build.lib.shell.TerminationStatus; import com.google.devtools.build.lib.util.CommandFailureUtils; import com.google.devtools.build.lib.util.OS; @@ -32,6 +35,7 @@ import com.google.devtools.build.lib.util.io.FileOutErr; import com.google.devtools.build.lib.vfs.Path; import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -94,7 +98,8 @@ public class StandaloneSpawnStrategy implements SpawnActionContext { args.addAll(spawn.getArguments()); String cwd = executor.getExecRoot().getPathString(); - Command cmd = new Command(args.toArray(new String[]{}), spawn.getEnvironment(), new File(cwd)); + Command cmd = new Command(args.toArray(new String[]{}), + locallyDeterminedEnv(spawn.getEnvironment()), new File(cwd)); FileOutErr outErr = actionExecutionContext.getFileOutErr(); try { @@ -127,4 +132,66 @@ public class StandaloneSpawnStrategy implements SpawnActionContext { public boolean isRemotable(String mnemonic, boolean remotable) { return false; } + + /** + * Adds to the given environment all variables that are dependent on system state of the host + * machine. + * + * <p> Admittedly, hermeticity is "best effort" in such cases; these environment values + * should be as tied to configuration parameters as possible. + * + * <p>For example, underlying iOS toolchains require that SDKROOT resolve to an absolute + * system path, but, when selecting which SDK to resolve, the version number comes from + * build configuration. + * + * @return the new environment, comprised of the old environment plus any new variables + * @throws UserExecException if any variables dependent on system state could not be + * resolved + */ + private ImmutableMap<String, String> locallyDeterminedEnv(ImmutableMap<String, String> env) + throws UserExecException { + ImmutableMap.Builder<String, String> newEnvBuilder = ImmutableMap.builder(); + newEnvBuilder.putAll(env); + if (env.containsKey(ObjcConfiguration.IOS_SDK_VERSION_ENV_NAME)) { + // The Apple platform is needed to select the appropriate SDK. + if (!env.containsKey(ObjcConfiguration.APPLE_SDK_PLATFORM_ENV_NAME)) { + throw new UserExecException("Could not resolve apple platform for determining SDK"); + } + String iosSdkVersion = env.get(ObjcConfiguration.IOS_SDK_VERSION_ENV_NAME); + String appleSdkPlatform = env.get(ObjcConfiguration.APPLE_SDK_PLATFORM_ENV_NAME); + // TODO(bazel-team): Determine and set DEVELOPER_DIR. + addSdkRootEnv(newEnvBuilder, iosSdkVersion, appleSdkPlatform); + } + return newEnvBuilder.build(); + } + + private void addSdkRootEnv( + ImmutableMap.Builder<String, String> envBuilder, String iosSdkVersion, + String appleSdkPlatform) throws UserExecException { + // Sanity check, also presents a less cryptic error message. + if (OS.getCurrent() != OS.DARWIN) { + throw new UserExecException("Cannot locate iOS SDK on non-darwin operating system"); + } + + try { + // TODO(bazel-team): Propagate DEVELOPER_DIR for the xcrun call. + CommandResult xcrunResult = new Command(new String[] {"/usr/bin/xcrun", "--sdk", + String.format("%s%s", appleSdkPlatform.toLowerCase(), iosSdkVersion), + "--show-sdk-path"}).execute(); + + TerminationStatus xcrunStatus = xcrunResult.getTerminationStatus(); + if (!xcrunResult.getTerminationStatus().exited()) { + throw new UserExecException(String.format("xcrun failed.\n%s\nStderr: %s", + xcrunStatus.toString(), new String(xcrunResult.getStderr(), StandardCharsets.UTF_8))); + } + + envBuilder.put("SDKROOT", new String(xcrunResult.getStdout(), StandardCharsets.UTF_8)); + } catch (AbnormalTerminationException e) { + String message = String.format("%s : %s", + e.getResult().getTerminationStatus(), new String(e.getResult().getStderr())); + throw new UserExecException(message, e); + } catch (CommandException e) { + throw new UserExecException(e); + } + } } |