diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py --- a/libcxx/utils/libcxx/test/config.py +++ b/libcxx/utils/libcxx/test/config.py @@ -70,7 +70,7 @@ self.abi_library_root = None self.link_shared = self.get_lit_bool('enable_shared', default=True) self.debug_build = self.get_lit_bool('debug_build', default=False) - self.exec_env = dict(os.environ) + self.exec_env = dict() self.use_target = False self.use_system_cxx_lib = False self.use_clang_verify = False @@ -125,9 +125,9 @@ return 'lib' + name + '.a' def configure(self): + self.configure_target_info() self.configure_executor() self.configure_use_system_cxx_lib() - self.configure_target_info() self.configure_cxx() self.configure_triple() self.configure_deployment() @@ -200,6 +200,9 @@ te = LocalExecutor() if self.lit_config.useValgrind: te = ValgrindExecutor(self.lit_config.valgrindArgs, te) + + te.target_info = self.target_info + self.executor = te def configure_target_info(self): @@ -1202,9 +1205,4 @@ self.target_info.configure_env(self.exec_env) def add_path(self, dest_env, new_path): - if 'PATH' not in dest_env: - dest_env['PATH'] = new_path - else: - split_char = ';' if platform.system() == 'Windows' else ':' - dest_env['PATH'] = '%s%s%s' % (new_path, split_char, - dest_env['PATH']) + self.target_info.add_path(dest_env, new_path) diff --git a/libcxx/utils/libcxx/test/executor.py b/libcxx/utils/libcxx/test/executor.py --- a/libcxx/utils/libcxx/test/executor.py +++ b/libcxx/utils/libcxx/test/executor.py @@ -6,14 +6,17 @@ # #===----------------------------------------------------------------------===## -import platform import os +from pathlib import PurePosixPath + from libcxx.test import tracing from libcxx.util import executeCommand - class Executor(object): + def __init__(self): + self.target_info = None + def run(self, exe_path, cmd, local_cwd, file_deps=None, env=None): """Execute a command. Be very careful not to change shared state in this function. @@ -29,6 +32,20 @@ """ raise NotImplementedError + def _merge_environments(self, current_env, updated_env): + """Merges two execution environments. + + If both environments contain the PATH variables, they are also merged + using the proper separator. + """ + result_env = dict(current_env) + for k, v in updated_env.items(): + if k == 'PATH' and self.target_info: + self.target_info.add_path(result_env, v) + else: + result_env[k] = v + return result_env + class LocalExecutor(Executor): def __init__(self): @@ -39,6 +56,10 @@ cmd = cmd or [exe_path] if work_dir == '.': work_dir = os.getcwd() + + if env: + env = self._merge_environments(os.environ, env) + out, err, rc = executeCommand(cmd, cwd=work_dir, env=env) return (cmd, out, err, rc) @@ -88,6 +109,7 @@ class RemoteExecutor(Executor): def __init__(self): + super(RemoteExecutor, self).__init__() self.local_run = executeCommand def remote_temp_dir(self): @@ -120,7 +142,7 @@ target_cwd = None try: target_cwd = self.remote_temp_dir() - target_exe_path = os.path.join(target_cwd, 'libcxx_test.exe') + target_exe_path = str(PurePosixPath(target_cwd) / 'libcxx_test.exe') if cmd: # Replace exe_path with target_exe_path. cmd = [c if c != exe_path else target_exe_path for c in cmd] @@ -183,13 +205,28 @@ cmd = [scp, '-p', src, remote + ':' + dst] self.local_run(cmd) + def _env_command(self, env): + if not env: + return [] + + env_cmd = ['env'] + + for k, v in env.items(): + if k == 'PATH': + # Pick up the existing paths, so we don't lose any commands + if self.target_info and self.target_info.is_windows(): + env_cmd.append('PATH="%s;%PATH%"' % v) + else: + env_cmd.append('PATH="%s:$PATH"' % v) + else: + env_cmd.append('"%s"="%s"' % (k, v.replace('\\', '\\\\'))) + + return env_cmd + def _execute_command_remote(self, cmd, remote_work_dir='.', env=None): remote = self.user_prefix + self.host ssh_cmd = [self.ssh_command, '-oBatchMode=yes', remote] - if env: - env_cmd = ['env'] + ['%s="%s"' % (k, v) for k, v in env.items()] - else: - env_cmd = [] + env_cmd = self._env_command(env) remote_cmd = ' '.join(env_cmd + cmd) if remote_work_dir != '.': remote_cmd = 'cd ' + remote_work_dir + ' && ' + remote_cmd diff --git a/libcxx/utils/libcxx/test/target_info.py b/libcxx/utils/libcxx/test/target_info.py --- a/libcxx/utils/libcxx/test/target_info.py +++ b/libcxx/utils/libcxx/test/target_info.py @@ -37,6 +37,16 @@ def add_sanitizer_features(self, sanitizer_type, features): pass def use_lit_shell_default(self): return False + def add_path(self, dest_env, new_path): + if not new_path: + return + if 'PATH' not in dest_env: + dest_env['PATH'] = new_path + else: + split_char = ';' if self.is_windows() else ':' + dest_env['PATH'] = '%s%s%s' % (new_path, split_char, + dest_env['PATH']) + def test_locale(loc): assert loc is not None