Adjust libc++ test infastructure to fully support modules

This patch overhalls the libc++ test format/configuration in order to fully support modules. By "fully support" I mean get almost all of the tests passing. The main hurdle for doing this is handling tests that `#define _LIBCPP_FOO` macros to test a different configuration. This patch deals with these tests in the following ways:

1. For tests that define single `_LIBCPP_ABI_FOO` macros have been annotated with `// MODULES_DEFINES: _LIBCPP_ABI_FOO`. This allows the test suite to define the macro on the command line so it uses a different set of modules.
2. Tests for libc++'s debug mode (which define custom `_LIBCPP_ASSERT`) are automatically detected by the test suite and are compiled and run with modules disabled.

This patch also cleans up how the `CXXCompiler` helper class handles enabling/disabling language features.

NOTE: This patch uses `LIT` features which were only committed to LLVM today. If this patch breaks running the libc++ tests you probably need to update LLVM.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@288728 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-12-05 23:16:07 +00:00
parent c6d8e8a9cc
commit bca6de0e4e
37 changed files with 207 additions and 140 deletions

View File

@@ -7,6 +7,7 @@
#
#===----------------------------------------------------------------------===##
import platform
import os
import lit.util
import libcxx.util
@@ -19,16 +20,47 @@ class CXXCompiler(object):
CM_Link = 3
def __init__(self, path, flags=None, compile_flags=None, link_flags=None,
use_ccache=False):
warning_flags=None, modules_flags=None, use_modules=False,
use_ccache=False, use_warnings=False, compile_env=None,
cxx_type=None, cxx_version=None):
self.path = path
self.flags = list(flags or [])
self.compile_flags = list(compile_flags or [])
self.warning_flags = []
self.warning_flags = list(warning_flags or [])
self.link_flags = list(link_flags or [])
self.modules_flags = list(modules_flags or [])
self.use_modules = use_modules
assert not use_modules or modules_flags is not None
self.use_ccache = use_ccache
self.type = None
self.version = None
self._initTypeAndVersion()
self.use_warnings = use_warnings
if compile_env is not None:
self.compile_env = dict(compile_env)
else:
self.compile_env = None
self.type = cxx_type
self.version = cxx_version
if self.type is None or self.version is None:
self._initTypeAndVersion()
def copy(self):
new_cxx = CXXCompiler(
self.path, flags=self.flags, compile_flags=self.compile_flags,
link_flags=self.link_flags, warning_flags=self.warning_flags,
modules_flags=self.modules_flags, use_modules=self.use_modules,
use_ccache=self.use_ccache, use_warnings=self.use_warnings,
compile_env=self.compile_env, cxx_type=self.type,
cxx_version=self.version)
return new_cxx
def useModules(self, value=True):
self.use_modules = value
assert not self.use_modules or self.modules_flags is not None
def useCCache(self, value=True):
self.use_ccache = value
def useWarnings(self, value=True):
self.use_warnings = value
def _initTypeAndVersion(self):
# Get compiler type and version
@@ -54,10 +86,9 @@ class CXXCompiler(object):
self.version = (major_ver, minor_ver, patchlevel)
def _basicCmd(self, source_files, out, mode=CM_Default, flags=[],
input_is_cxx=False,
enable_warnings=True, disable_ccache=False):
input_is_cxx=False):
cmd = []
if self.use_ccache and not disable_ccache \
if self.use_ccache \
and not mode == self.CM_Link \
and not mode == self.CM_PreProcess:
cmd += ['ccache']
@@ -77,68 +108,64 @@ class CXXCompiler(object):
elif mode == self.CM_Compile:
cmd += ['-c']
cmd += self.flags
if self.use_modules:
cmd += self.modules_flags
if mode != self.CM_Link:
cmd += self.compile_flags
if enable_warnings:
if self.use_warnings:
cmd += self.warning_flags
if mode != self.CM_PreProcess and mode != self.CM_Compile:
cmd += self.link_flags
cmd += flags
return cmd
def _getWarningFlags(self, enable_warnings=True):
return self.warning_flags if enable_warnings else []
def _getWarningFlags(self):
return self.warning_flags if self.use_warnings else []
def preprocessCmd(self, source_files, out=None, flags=[],
enable_warnings=True):
def preprocessCmd(self, source_files, out=None, flags=[]):
return self._basicCmd(source_files, out, flags=flags,
mode=self.CM_PreProcess,
enable_warnings=enable_warnings,
input_is_cxx=True)
def compileCmd(self, source_files, out=None, flags=[],
disable_ccache=False, enable_warnings=True):
def compileCmd(self, source_files, out=None, flags=[]):
return self._basicCmd(source_files, out, flags=flags,
mode=self.CM_Compile,
input_is_cxx=True,
enable_warnings=enable_warnings,
disable_ccache=disable_ccache) + ['-c']
input_is_cxx=True) + ['-c']
def linkCmd(self, source_files, out=None, flags=[]):
return self._basicCmd(source_files, out, mode=self.CM_Link)
def compileLinkCmd(self, source_files, out=None, flags=[],
enable_warnings=True):
return self._basicCmd(source_files, out, flags=flags,
enable_warnings=enable_warnings)
mode=self.CM_Link)
def preprocess(self, source_files, out=None, flags=[], env=None, cwd=None):
def compileLinkCmd(self, source_files, out=None, flags=[]):
return self._basicCmd(source_files, out, flags=flags)
def preprocess(self, source_files, out=None, flags=[], cwd=None):
cmd = self.preprocessCmd(source_files, out, flags)
out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd)
out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env,
cwd=cwd)
return cmd, out, err, rc
def compile(self, source_files, out=None, flags=[], env=None, cwd=None,
disable_ccache=False, enable_warnings=True):
cmd = self.compileCmd(source_files, out, flags,
disable_ccache=disable_ccache,
enable_warnings=enable_warnings)
out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd)
def compile(self, source_files, out=None, flags=[], cwd=None):
cmd = self.compileCmd(source_files, out, flags)
out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env,
cwd=cwd)
return cmd, out, err, rc
def link(self, source_files, out=None, flags=[], env=None, cwd=None):
def link(self, source_files, out=None, flags=[], cwd=None):
cmd = self.linkCmd(source_files, out, flags)
out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd)
out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env,
cwd=cwd)
return cmd, out, err, rc
def compileLink(self, source_files, out=None, flags=[], env=None,
def compileLink(self, source_files, out=None, flags=[],
cwd=None):
cmd = self.compileLinkCmd(source_files, out, flags)
out, err, rc = lit.util.executeCommand(cmd, env=env, cwd=cwd)
out, err, rc = lit.util.executeCommand(cmd, env=self.compile_env,
cwd=cwd)
return cmd, out, err, rc
def compileLinkTwoSteps(self, source_file, out=None, object_file=None,
flags=[], env=None, cwd=None,
disable_ccache=False):
flags=[], cwd=None):
if not isinstance(source_file, str):
raise TypeError('This function only accepts a single input file')
if object_file is None:
@@ -149,22 +176,20 @@ class CXXCompiler(object):
with_fn = lambda: libcxx.util.nullContext(object_file)
with with_fn() as object_file:
cc_cmd, cc_stdout, cc_stderr, rc = self.compile(
source_file, object_file, flags=flags, env=env, cwd=cwd,
disable_ccache=disable_ccache)
source_file, object_file, flags=flags, cwd=cwd)
if rc != 0:
return cc_cmd, cc_stdout, cc_stderr, rc
link_cmd, link_stdout, link_stderr, rc = self.link(
object_file, out=out, flags=flags, env=env, cwd=cwd)
object_file, out=out, flags=flags, cwd=cwd)
return (cc_cmd + ['&&'] + link_cmd, cc_stdout + link_stdout,
cc_stderr + link_stderr, rc)
def dumpMacros(self, source_files=None, flags=[], env=None, cwd=None):
def dumpMacros(self, source_files=None, flags=[], cwd=None):
if source_files is None:
source_files = os.devnull
flags = ['-dM'] + flags
cmd, out, err, rc = self.preprocess(source_files, flags=flags, env=env,
cwd=cwd)
cmd, out, err, rc = self.preprocess(source_files, flags=flags, cwd=cwd)
if rc != 0:
return None
parsed_macros = {}
@@ -215,11 +240,11 @@ class CXXCompiler(object):
else:
return False
def addWarningFlagIfSupported(self, flag):
def hasWarningFlag(self, flag):
"""
addWarningFlagIfSupported - Add a warning flag if the compiler
supports it. Unlike addCompileFlagIfSupported, this function detects
when "-Wno-<warning>" flags are unsupported. If flag is a
hasWarningFlag - Test if the compiler supports a given warning flag.
Unlike addCompileFlagIfSupported, this function detects when
"-Wno-<warning>" flags are unsupported. If flag is a
"-Wno-<warning>" GCC will not emit an unknown option diagnostic unless
another error is triggered during compilation.
"""
@@ -230,7 +255,10 @@ class CXXCompiler(object):
return True
return False
flags = ['-Werror', flag]
cmd = self.compileCmd('-', os.devnull, flags, enable_warnings=False)
old_use_warnings = self.use_warnings
self.useWarnings(False)
cmd = self.compileCmd('-', os.devnull, flags)
self.useWarnings(True)
# Remove '-v' because it will cause the command line invocation
# to be printed as part of the error output.
# TODO(EricWF): Are there other flags we need to worry about?
@@ -240,5 +268,10 @@ class CXXCompiler(object):
assert rc != 0
if flag in err:
return False
self.warning_flags += [flag]
return True
def addWarningFlagIfSupported(self, flag):
if self.hasWarningFlag(flag):
self.warning_flags += [flag]
return True
return False