Fix linking of DLL's on Windows
On Windows the runtime search path for DLL's is the same as PATH. This patch changes the test suite to add the libc++ build directory to the runtime PATH. llvm-svn: 291309
This commit is contained in:
parent
d92e7f9f74
commit
93619335df
|
@ -67,7 +67,8 @@ class Configuration(object):
|
|||
self.cxx_library_root = None
|
||||
self.cxx_runtime_root = None
|
||||
self.abi_library_root = None
|
||||
self.env = {}
|
||||
self.link_shared = self.get_lit_bool('enable_shared', default=True)
|
||||
self.exec_env = {}
|
||||
self.use_target = False
|
||||
self.use_system_cxx_lib = False
|
||||
self.use_clang_verify = False
|
||||
|
@ -146,7 +147,7 @@ class Configuration(object):
|
|||
# Print as list to prevent "set([...])" from being printed.
|
||||
self.lit_config.note('Using available_features: %s' %
|
||||
list(self.config.available_features))
|
||||
self.lit_config.note('Using environment: %r' % self.env)
|
||||
self.lit_config.note('Using environment: %r' % self.exec_env)
|
||||
|
||||
def get_test_format(self):
|
||||
return LibcxxTestFormat(
|
||||
|
@ -154,7 +155,7 @@ class Configuration(object):
|
|||
self.use_clang_verify,
|
||||
self.execute_external,
|
||||
self.executor,
|
||||
exec_env=self.env)
|
||||
exec_env=self.exec_env)
|
||||
|
||||
def configure_executor(self):
|
||||
exec_str = self.get_lit_conf('executor', "None")
|
||||
|
@ -207,6 +208,11 @@ class Configuration(object):
|
|||
self.config.available_features.add('%s-%s' % (cxx_type, maj_v))
|
||||
self.config.available_features.add('%s-%s.%s' % (
|
||||
cxx_type, maj_v, min_v))
|
||||
self.cxx.compile_env = dict(os.environ)
|
||||
# 'CCACHE_CPP2' prevents ccache from stripping comments while
|
||||
# preprocessing. This is required to prevent stripping of '-verify'
|
||||
# comments.
|
||||
self.cxx.compile_env['CCACHE_CPP2'] = '1'
|
||||
|
||||
def _configure_clang_cl(self, clang_path):
|
||||
assert self.cxx_is_clang_cl
|
||||
|
@ -555,7 +561,7 @@ class Configuration(object):
|
|||
if not os.path.isdir(dynamic_env):
|
||||
os.makedirs(dynamic_env)
|
||||
self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT="%s"' % dynamic_env]
|
||||
self.env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
|
||||
self.exec_env['LIBCXX_FILESYSTEM_DYNAMIC_TEST_ROOT'] = ("%s" % dynamic_env)
|
||||
|
||||
dynamic_helper = os.path.join(self.libcxx_src_root, 'test', 'support',
|
||||
'filesystem_dynamic_test_helper.py')
|
||||
|
@ -577,7 +583,7 @@ class Configuration(object):
|
|||
self.cxx.link_flags += ['-nodefaultlibs']
|
||||
# FIXME: Handle MSVCRT as part of the ABI library handling.
|
||||
if self.is_windows:
|
||||
self.cxx.link_flags += ['-nostdlib', '-lmsvcrtd']
|
||||
self.cxx.link_flags += ['-nostdlib']
|
||||
self.configure_link_flags_cxx_library()
|
||||
self.configure_link_flags_abi_library()
|
||||
self.configure_extra_library_flags()
|
||||
|
@ -602,8 +608,14 @@ class Configuration(object):
|
|||
if not self.use_system_cxx_lib:
|
||||
if self.cxx_library_root:
|
||||
self.cxx.link_flags += ['-L' + self.cxx_library_root]
|
||||
if self.cxx_runtime_root and not self.is_windows:
|
||||
self.cxx.link_flags += ['-Wl,-rpath,' + self.cxx_runtime_root]
|
||||
if self.is_windows and self.link_shared:
|
||||
self.add_path(self.cxx.compile_env, self.cxx_library_root)
|
||||
if self.cxx_runtime_root:
|
||||
if not self.is_windows:
|
||||
self.cxx.link_flags += ['-Wl,-rpath,' +
|
||||
self.cxx_runtime_root]
|
||||
elif self.is_windows and self.link_shared:
|
||||
self.add_path(self.exec_env, self.cxx_runtime_root)
|
||||
|
||||
def configure_link_flags_abi_library_path(self):
|
||||
# Configure ABI library paths.
|
||||
|
@ -612,14 +624,15 @@ class Configuration(object):
|
|||
self.cxx.link_flags += ['-L' + self.abi_library_root]
|
||||
if not self.is_windows:
|
||||
self.cxx.link_flags += ['-Wl,-rpath,' + self.abi_library_root]
|
||||
else:
|
||||
self.add_path(self.exec_env, self.abi_library_root)
|
||||
|
||||
def configure_link_flags_cxx_library(self):
|
||||
libcxx_experimental = self.get_lit_bool('enable_experimental', default=False)
|
||||
if libcxx_experimental:
|
||||
self.config.available_features.add('c++experimental')
|
||||
self.cxx.link_flags += ['-lc++experimental']
|
||||
libcxx_shared = self.get_lit_bool('enable_shared', default=True)
|
||||
if libcxx_shared:
|
||||
if self.link_shared:
|
||||
self.cxx.link_flags += ['-lc++']
|
||||
else:
|
||||
cxx_library_root = self.get_lit_conf('cxx_library_root')
|
||||
|
@ -654,7 +667,8 @@ class Configuration(object):
|
|||
elif cxx_abi == 'libcxxrt':
|
||||
self.cxx.link_flags += ['-lcxxrt']
|
||||
elif cxx_abi == 'none' or cxx_abi == 'default':
|
||||
pass
|
||||
if self.is_windows:
|
||||
self.cxx.link_flags += ['-lmsvcrtd']
|
||||
else:
|
||||
self.lit_config.fatal(
|
||||
'C++ ABI setting %s unsupported for tests' % cxx_abi)
|
||||
|
@ -746,7 +760,7 @@ class Configuration(object):
|
|||
self.cxx.flags += ['-fsanitize=undefined',
|
||||
'-fno-sanitize=vptr,function,float-divide-by-zero',
|
||||
'-fno-sanitize-recover=all']
|
||||
self.env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
|
||||
self.exec_env['UBSAN_OPTIONS'] = 'print_stacktrace=1'
|
||||
self.config.available_features.add('ubsan')
|
||||
|
||||
# Setup the sanitizer compile flags
|
||||
|
@ -754,10 +768,10 @@ class Configuration(object):
|
|||
if san == 'Address' or san == 'Address;Undefined' or san == 'Undefined;Address':
|
||||
self.cxx.flags += ['-fsanitize=address']
|
||||
if llvm_symbolizer is not None:
|
||||
self.env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
||||
self.exec_env['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
||||
# FIXME: Turn ODR violation back on after PR28391 is resolved
|
||||
# https://llvm.org/bugs/show_bug.cgi?id=28391
|
||||
self.env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
|
||||
self.exec_env['ASAN_OPTIONS'] = 'detect_odr_violation=0'
|
||||
self.config.available_features.add('asan')
|
||||
self.config.available_features.add('sanitizer-new-delete')
|
||||
self.cxx.compile_flags += ['-O1']
|
||||
|
@ -769,7 +783,7 @@ class Configuration(object):
|
|||
self.cxx.compile_flags += [
|
||||
'-fsanitize-memory-track-origins']
|
||||
if llvm_symbolizer is not None:
|
||||
self.env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
||||
self.exec_env['MSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
|
||||
self.config.available_features.add('msan')
|
||||
self.config.available_features.add('sanitizer-new-delete')
|
||||
self.cxx.compile_flags += ['-O1']
|
||||
|
@ -855,8 +869,8 @@ class Configuration(object):
|
|||
sub.append(('%link', link_str))
|
||||
sub.append(('%build', build_str))
|
||||
# Configure exec prefix substitutions.
|
||||
exec_env_str = 'env ' if len(self.env) != 0 else ''
|
||||
for k, v in self.env.items():
|
||||
exec_env_str = 'env ' if len(self.exec_env) != 0 else ''
|
||||
for k, v in self.exec_env.items():
|
||||
exec_env_str += ' %s=%s' % (k, v)
|
||||
# Configure run env substitution.
|
||||
exec_str = exec_env_str
|
||||
|
@ -898,4 +912,12 @@ class Configuration(object):
|
|||
"inferred target_triple as: %r" % self.config.target_triple)
|
||||
|
||||
def configure_env(self):
|
||||
self.target_info.configure_env(self.env)
|
||||
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 self.is_windows else ':'
|
||||
dest_env['PATH'] = '%s%s%s' % (new_path, split_char,
|
||||
dest_env['PATH'])
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#
|
||||
#===----------------------------------------------------------------------===##
|
||||
|
||||
import platform
|
||||
import os
|
||||
|
||||
from libcxx.test import tracing
|
||||
|
@ -34,6 +35,7 @@ class Executor(object):
|
|||
class LocalExecutor(Executor):
|
||||
def __init__(self):
|
||||
super(LocalExecutor, self).__init__()
|
||||
self.is_windows = platform.system() == 'Windows'
|
||||
|
||||
def run(self, exe_path, cmd=None, work_dir='.', file_deps=None, env=None):
|
||||
cmd = cmd or [exe_path]
|
||||
|
@ -43,9 +45,30 @@ class LocalExecutor(Executor):
|
|||
env_cmd += ['%s=%s' % (k, v) for k, v in env.items()]
|
||||
if work_dir == '.':
|
||||
work_dir = os.getcwd()
|
||||
out, err, rc = executeCommand(env_cmd + cmd, cwd=work_dir)
|
||||
if not self.is_windows:
|
||||
out, err, rc = executeCommand(env_cmd + cmd, cwd=work_dir)
|
||||
else:
|
||||
out, err, rc = executeCommand(cmd, cwd=work_dir,
|
||||
env=self._build_windows_env(env))
|
||||
return (env_cmd + cmd, out, err, rc)
|
||||
|
||||
def _build_windows_env(self, exec_env):
|
||||
# FIXME: Finding Windows DLL's at runtime requires modifying the
|
||||
# PATH environment variables. However we don't want to print out
|
||||
# the entire PATH as part of the diagnostic for every failing test.
|
||||
# Therefore this hack builds a new executable environment that
|
||||
# merges the current environment and the supplied environment while
|
||||
# still only printing the supplied environment in diagnostics.
|
||||
if not self.is_windows or exec_env is None:
|
||||
return None
|
||||
new_env = dict(os.environ)
|
||||
for key, value in exec_env.items():
|
||||
if key == 'PATH':
|
||||
assert value.strip() != '' and "expected non-empty path"
|
||||
new_env['PATH'] = "%s;%s" % (value, os.environ['PATH'])
|
||||
else:
|
||||
new_env[key] = value
|
||||
return new_env
|
||||
|
||||
class PrefixExecutor(Executor):
|
||||
"""Prefix an executor with some other command wrapper.
|
||||
|
|
|
@ -41,11 +41,6 @@ class LibcxxTestFormat(object):
|
|||
self.execute_external = execute_external
|
||||
self.executor = executor
|
||||
self.exec_env = dict(exec_env)
|
||||
self.cxx.compile_env = dict(os.environ)
|
||||
# 'CCACHE_CPP2' prevents ccache from stripping comments while
|
||||
# preprocessing. This is required to prevent stripping of '-verify'
|
||||
# comments.
|
||||
self.cxx.compile_env['CCACHE_CPP2'] = '1'
|
||||
|
||||
@staticmethod
|
||||
def _make_custom_parsers():
|
||||
|
|
Loading…
Reference in New Issue