forked from OSchip/llvm-project
[lit] Implement 'env' in the internal shell
The MSys 2 version of 'env' cannot be used to set 'TZ' in the environment due to some portability hacks in the process spawning compatibility layer[1]. This affects test/Object/archive-toc.test, which tries to set TZ in the environment. Other than that, this saves a subprocess invocation of a small unix utility, which is makes the tests faster. The internal shell does not support shell variable expansion, so this idiom in the ASan tests isn't supported yet: RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:opt=1 ... [1] https://github.com/Alexpux/MSYS2-packages/issues/294 Differential Revision: http://reviews.llvm.org/D11350 llvm-svn: 242696
This commit is contained in:
parent
1aa4567712
commit
edd9b6ef36
|
@ -31,7 +31,7 @@ class ShellEnvironment(object):
|
||||||
|
|
||||||
def __init__(self, cwd, env):
|
def __init__(self, cwd, env):
|
||||||
self.cwd = cwd
|
self.cwd = cwd
|
||||||
self.env = env
|
self.env = dict(env)
|
||||||
|
|
||||||
def executeShCmd(cmd, shenv, results):
|
def executeShCmd(cmd, shenv, results):
|
||||||
if isinstance(cmd, ShUtil.Seq):
|
if isinstance(cmd, ShUtil.Seq):
|
||||||
|
@ -62,14 +62,18 @@ def executeShCmd(cmd, shenv, results):
|
||||||
|
|
||||||
# Handle shell builtins first.
|
# Handle shell builtins first.
|
||||||
if cmd.commands[0].args[0] == 'cd':
|
if cmd.commands[0].args[0] == 'cd':
|
||||||
# Update the cwd in the environment.
|
if len(cmd.commands) != 1:
|
||||||
|
raise ValueError("'cd' cannot be part of a pipeline")
|
||||||
if len(cmd.commands[0].args) != 2:
|
if len(cmd.commands[0].args) != 2:
|
||||||
raise ValueError('cd supports only one argument')
|
raise ValueError("'cd' supports only one argument")
|
||||||
newdir = cmd.commands[0].args[1]
|
newdir = cmd.commands[0].args[1]
|
||||||
|
# Update the cwd in the parent environment.
|
||||||
if os.path.isabs(newdir):
|
if os.path.isabs(newdir):
|
||||||
shenv.cwd = newdir
|
shenv.cwd = newdir
|
||||||
else:
|
else:
|
||||||
shenv.cwd = os.path.join(shenv.cwd, newdir)
|
shenv.cwd = os.path.join(shenv.cwd, newdir)
|
||||||
|
# The cd builtin always succeeds. If the directory does not exist, the
|
||||||
|
# following Popen calls will fail instead.
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
procs = []
|
procs = []
|
||||||
|
@ -81,6 +85,23 @@ def executeShCmd(cmd, shenv, results):
|
||||||
# output. This is null until we have seen some output using
|
# output. This is null until we have seen some output using
|
||||||
# stderr.
|
# stderr.
|
||||||
for i,j in enumerate(cmd.commands):
|
for i,j in enumerate(cmd.commands):
|
||||||
|
# Reference the global environment by default.
|
||||||
|
cmd_shenv = shenv
|
||||||
|
if j.args[0] == 'env':
|
||||||
|
# Create a copy of the global environment and modify it for this one
|
||||||
|
# command. There might be multiple envs in a pipeline:
|
||||||
|
# env FOO=1 llc < %s | env BAR=2 llvm-mc | FileCheck %s
|
||||||
|
cmd_shenv = ShellEnvironment(shenv.cwd, shenv.env)
|
||||||
|
arg_idx = 1
|
||||||
|
for arg_idx, arg in enumerate(j.args[1:]):
|
||||||
|
# Partition the string into KEY=VALUE.
|
||||||
|
key, eq, val = arg.partition('=')
|
||||||
|
# Stop if there was no equals.
|
||||||
|
if eq == '':
|
||||||
|
break
|
||||||
|
cmd_shenv.env[key] = val
|
||||||
|
j.args = j.args[arg_idx+1:]
|
||||||
|
|
||||||
# Apply the redirections, we use (N,) as a sentinel to indicate stdin,
|
# Apply the redirections, we use (N,) as a sentinel to indicate stdin,
|
||||||
# stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
|
# stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
|
||||||
# from a file are represented with a list [file, mode, file-object]
|
# from a file are represented with a list [file, mode, file-object]
|
||||||
|
@ -126,7 +147,7 @@ def executeShCmd(cmd, shenv, results):
|
||||||
r[2] = tempfile.TemporaryFile(mode=r[1])
|
r[2] = tempfile.TemporaryFile(mode=r[1])
|
||||||
else:
|
else:
|
||||||
# Make sure relative paths are relative to the cwd.
|
# Make sure relative paths are relative to the cwd.
|
||||||
redir_filename = os.path.join(shenv.cwd, r[0])
|
redir_filename = os.path.join(cmd_shenv.cwd, r[0])
|
||||||
r[2] = open(redir_filename, r[1])
|
r[2] = open(redir_filename, r[1])
|
||||||
# Workaround a Win32 and/or subprocess bug when appending.
|
# Workaround a Win32 and/or subprocess bug when appending.
|
||||||
#
|
#
|
||||||
|
@ -157,7 +178,7 @@ def executeShCmd(cmd, shenv, results):
|
||||||
|
|
||||||
# Resolve the executable path ourselves.
|
# Resolve the executable path ourselves.
|
||||||
args = list(j.args)
|
args = list(j.args)
|
||||||
executable = lit.util.which(args[0], shenv.env['PATH'])
|
executable = lit.util.which(args[0], cmd_shenv.env['PATH'])
|
||||||
if not executable:
|
if not executable:
|
||||||
raise InternalShellError(j, '%r: command not found' % j.args[0])
|
raise InternalShellError(j, '%r: command not found' % j.args[0])
|
||||||
|
|
||||||
|
@ -171,12 +192,12 @@ def executeShCmd(cmd, shenv, results):
|
||||||
args[i] = f.name
|
args[i] = f.name
|
||||||
|
|
||||||
try:
|
try:
|
||||||
procs.append(subprocess.Popen(args, cwd=shenv.cwd,
|
procs.append(subprocess.Popen(args, cwd=cmd_shenv.cwd,
|
||||||
executable = executable,
|
executable = executable,
|
||||||
stdin = stdin,
|
stdin = stdin,
|
||||||
stdout = stdout,
|
stdout = stdout,
|
||||||
stderr = stderr,
|
stderr = stderr,
|
||||||
env = shenv.env,
|
env = cmd_shenv.env,
|
||||||
close_fds = kUseCloseFDs))
|
close_fds = kUseCloseFDs))
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise InternalShellError(j, 'Could not create process due to {}'.format(e))
|
raise InternalShellError(j, 'Could not create process due to {}'.format(e))
|
||||||
|
|
Loading…
Reference in New Issue