summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-01-07 00:01:55 +0000
committerEric Fiselier <eric@efcs.ca>2017-01-07 00:01:55 +0000
commitafd7cc87ce65d8763ca249798f4f8acbeede67d9 (patch)
tree7e121f43aea91b9fd0f7cdc0c60bc5b24e3c46d2
parentbab7b41d2e159fdd36d020dc9889ce30ef77141a (diff)
downloadlibcxx-afd7cc87ce65d8763ca249798f4f8acbeede67d9.tar.gz
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. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@291309 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--test/libcxx/test/config.py56
-rw-r--r--test/libcxx/test/executor.py25
-rw-r--r--test/libcxx/test/format.py5
3 files changed, 63 insertions, 23 deletions
diff --git a/test/libcxx/test/config.py b/test/libcxx/test/config.py
index 7043b8a01..c8771999d 100644
--- a/test/libcxx/test/config.py
+++ b/test/libcxx/test/config.py
@@ -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'])
diff --git a/test/libcxx/test/executor.py b/test/libcxx/test/executor.py
index ee4288fb0..250186cec 100644
--- a/test/libcxx/test/executor.py
+++ b/test/libcxx/test/executor.py
@@ -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.
diff --git a/test/libcxx/test/format.py b/test/libcxx/test/format.py
index ee6ab82c6..cbd96f340 100644
--- a/test/libcxx/test/format.py
+++ b/test/libcxx/test/format.py
@@ -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():