Bug 1270446 - Make it easier to derive compiler results. r=chmanchester

This commit is contained in:
Mike Hommey 2016-04-22 16:48:14 +09:00
Родитель 645ca5540c
Коммит 4af7d047e9
3 изменённых файлов: 193 добавлений и 106 удалений

Просмотреть файл

@ -15,7 +15,10 @@ from common import BaseConfigureTest
from mozbuild.configure.util import Version
from mozbuild.util import memoize
from mozpack import path as mozpath
from test_toolchain_helpers import FakeCompiler
from test_toolchain_helpers import (
FakeCompiler,
CompilerResult,
)
DEFAULT_C99 = {
@ -157,11 +160,8 @@ class BaseToolchainTest(BaseConfigureTest):
- `results` is a dict associating result variable names from
toolchain.configure (c_compiler, cxx_compiler, host_c_compiler,
host_cxx_compiler) with a result.
The result can either be an error string, or a dict with the
following items: flags, version, type, compiler, wrapper. (wrapper
can be omitted when it's empty). Those items correspond to the
attributes of the object returned by toolchain.configure checks
and will be compared to them.
The result can either be an error string, or a CompilerResult
corresponding to the object returned by toolchain.configure checks.
When the results for host_c_compiler are identical to c_compiler,
they can be omitted. Likewise for host_cxx_compiler vs.
cxx_compiler.
@ -182,16 +182,12 @@ class BaseToolchainTest(BaseConfigureTest):
result = results.get(var[5:], {})
else:
result = {}
if isinstance(result, dict):
result = dict(result)
result.setdefault('wrapper', [])
result['compiler'] = mozpath.abspath(result['compiler'])
try:
self.out.truncate(0)
compiler = sandbox._value_for(sandbox[var])
# Add var on both ends to make it clear which of the
# variables is failing the test when that happens.
self.assertEquals((var, compiler.__dict__), (var, result))
self.assertEquals((var, compiler), (var, result))
except SystemExit:
self.assertEquals((var, result),
(var, self.out.getvalue().strip()))
@ -216,49 +212,49 @@ class LinuxToolchainTest(BaseToolchainTest):
GCC_4_7_RESULT = ('Only GCC 4.8 or newer is supported '
'(found version 4.7.3).')
GXX_4_7_RESULT = GCC_4_7_RESULT
GCC_4_9_RESULT = {
'flags': ['-std=gnu99'],
'version': '4.9.3',
'type': 'gcc',
'compiler': '/usr/bin/gcc',
}
GXX_4_9_RESULT = {
'flags': ['-std=gnu++11'],
'version': '4.9.3',
'type': 'gcc',
'compiler': '/usr/bin/g++',
}
GCC_5_RESULT = {
'flags': ['-std=gnu99'],
'version': '5.2.1',
'type': 'gcc',
'compiler': '/usr/bin/gcc-5',
}
GXX_5_RESULT = {
'flags': ['-std=gnu++11'],
'version': '5.2.1',
'type': 'gcc',
'compiler': '/usr/bin/g++-5',
}
CLANG_3_3_RESULT = {
'flags': [],
'version': '3.3.0',
'type': 'clang',
'compiler': '/usr/bin/clang-3.3',
}
GCC_4_9_RESULT = CompilerResult(
flags=['-std=gnu99'],
version='4.9.3',
type='gcc',
compiler='/usr/bin/gcc',
)
GXX_4_9_RESULT = CompilerResult(
flags=['-std=gnu++11'],
version='4.9.3',
type='gcc',
compiler='/usr/bin/g++',
)
GCC_5_RESULT = CompilerResult(
flags=['-std=gnu99'],
version='5.2.1',
type='gcc',
compiler='/usr/bin/gcc-5',
)
GXX_5_RESULT = CompilerResult(
flags=['-std=gnu++11'],
version='5.2.1',
type='gcc',
compiler='/usr/bin/g++-5',
)
CLANG_3_3_RESULT = CompilerResult(
flags=[],
version='3.3.0',
type='clang',
compiler='/usr/bin/clang-3.3',
)
CLANGXX_3_3_RESULT = 'Only clang/llvm 3.4 or newer is supported.'
CLANG_3_6_RESULT = {
'flags': ['-std=gnu99'],
'version': '3.6.2',
'type': 'clang',
'compiler': '/usr/bin/clang',
}
CLANGXX_3_6_RESULT = {
'flags': ['-std=gnu++11'],
'version': '3.6.2',
'type': 'clang',
'compiler': '/usr/bin/clang++',
}
CLANG_3_6_RESULT = CompilerResult(
flags=['-std=gnu99'],
version='3.6.2',
type='clang',
compiler='/usr/bin/clang',
)
CLANGXX_3_6_RESULT = CompilerResult(
flags=['-std=gnu++11'],
version='3.6.2',
type='clang',
compiler='/usr/bin/clang++',
)
def test_gcc(self):
# We'll try gcc and clang, and find gcc first.
@ -374,13 +370,13 @@ class LinuxToolchainTest(BaseToolchainTest):
def test_guess_cxx_clang(self):
# When CXX is not set, we guess it from CC.
clang_3_6_result = dict(self.CLANG_3_6_RESULT)
clang_3_6_result['compiler'] = '/usr/bin/clang-3.6'
clangxx_3_6_result = dict(self.CLANGXX_3_6_RESULT)
clangxx_3_6_result['compiler'] = '/usr/bin/clang++-3.6'
self.do_toolchain_test(self.PATHS, {
'c_compiler': clang_3_6_result,
'cxx_compiler': clangxx_3_6_result,
'c_compiler': self.CLANG_3_6_RESULT + {
'compiler': '/usr/bin/clang-3.6',
},
'cxx_compiler': self.CLANGXX_3_6_RESULT + {
'compiler': '/usr/bin/clang++-3.6',
},
}, environ={
'CC': 'clang-3.6',
})
@ -412,13 +408,13 @@ class LinuxToolchainTest(BaseToolchainTest):
'/opt/clang/bin/clang': CLANG_3_6,
'/opt/clang/bin/clang++': CLANGXX_3_6,
})
absolute_clang = dict(self.CLANG_3_6_RESULT)
absolute_clang['compiler'] = '/opt/clang/bin/clang'
absolute_clangxx = dict(self.CLANGXX_3_6_RESULT)
absolute_clangxx['compiler'] = '/opt/clang/bin/clang++'
result = {
'c_compiler': absolute_clang,
'cxx_compiler': absolute_clangxx,
'c_compiler': self.CLANG_3_6_RESULT + {
'compiler': '/opt/clang/bin/clang',
},
'cxx_compiler': self.CLANGXX_3_6_RESULT + {
'compiler': '/opt/clang/bin/clang++'
},
}
self.do_toolchain_test(paths, result, environ={
'CC': '/opt/clang/bin/clang',
@ -435,13 +431,13 @@ class LinuxToolchainTest(BaseToolchainTest):
'/usr/bin/afl-clang-fast': CLANG_3_6,
'/usr/bin/afl-clang-fast++': CLANGXX_3_6,
})
afl_clang_result = dict(self.CLANG_3_6_RESULT)
afl_clang_result['compiler'] = '/usr/bin/afl-clang-fast'
afl_clangxx_result = dict(self.CLANGXX_3_6_RESULT)
afl_clangxx_result['compiler'] = '/usr/bin/afl-clang-fast++'
self.do_toolchain_test(paths, {
'c_compiler': afl_clang_result,
'cxx_compiler': afl_clangxx_result,
'c_compiler': self.CLANG_3_6_RESULT + {
'compiler': '/usr/bin/afl-clang-fast',
},
'cxx_compiler': self.CLANGXX_3_6_RESULT + {
'compiler': '/usr/bin/afl-clang-fast++',
},
}, environ={
'CC': 'afl-clang-fast',
'CXX': 'afl-clang-fast++',
@ -546,36 +542,36 @@ class WindowsToolchainTest(BaseToolchainTest):
'You must install Visual C++ 2013 Update 3, Visual C++ 2015 Update 1, '
'or newer in order to build.\n'
'See https://developer.mozilla.org/en/Windows_Build_Prerequisites')
VS_2013u3_RESULT = {
'flags': [],
'version': '18.00.30723',
'type': 'msvc',
'compiler': '/opt/VS_2013u3/bin/cl',
}
VS_2013u3_RESULT = CompilerResult(
flags=[],
version='18.00.30723',
type='msvc',
compiler='/opt/VS_2013u3/bin/cl',
)
VS_2015_RESULT = (
'This version (19.00.23026) of the MSVC compiler is not supported.\n'
'You must install Visual C++ 2013 Update 3, Visual C++ 2015 Update 1, '
'or newer in order to build.\n'
'See https://developer.mozilla.org/en/Windows_Build_Prerequisites')
VS_2015u1_RESULT = {
'flags': [],
'version': '19.00.23506',
'type': 'msvc',
'compiler': '/usr/bin/cl',
}
CLANG_CL_3_9_RESULT = {
'flags': ['-Xclang', '-std=gnu99',
'-fms-compatibility-version=18.00.30723', '-fallback'],
'version': '18.00.30723',
'type': 'clang-cl',
'compiler': '/usr/bin/clang-cl',
}
CLANGXX_CL_3_9_RESULT = {
'flags': ['-fms-compatibility-version=18.00.30723', '-fallback'],
'version': '18.00.30723',
'type': 'clang-cl',
'compiler': '/usr/bin/clang-cl',
}
VS_2015u1_RESULT = CompilerResult(
flags=[],
version='19.00.23506',
type='msvc',
compiler='/usr/bin/cl',
)
CLANG_CL_3_9_RESULT = CompilerResult(
flags=['-Xclang', '-std=gnu99',
'-fms-compatibility-version=18.00.30723', '-fallback'],
version='18.00.30723',
type='clang-cl',
compiler='/usr/bin/clang-cl',
)
CLANGXX_CL_3_9_RESULT = CompilerResult(
flags=['-fms-compatibility-version=18.00.30723', '-fallback'],
version='18.00.30723',
type='clang-cl',
compiler='/usr/bin/clang-cl',
)
CLANG_3_3_RESULT = LinuxToolchainTest.CLANG_3_3_RESULT
CLANGXX_3_3_RESULT = LinuxToolchainTest.CLANGXX_3_3_RESULT
CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT
@ -677,15 +673,13 @@ class CrossCompileToolchainTest(BaseToolchainTest):
'/usr/bin/arm-linux-gnu-g++-5': GXX_5,
}
PATHS.update(LinuxToolchainTest.PATHS)
ARM_GCC_4_9_RESULT = dict(LinuxToolchainTest.GCC_4_9_RESULT)
ARM_GCC_4_9_RESULT['compiler'] = '/usr/bin/arm-linux-gnu-gcc'
ARM_GXX_4_9_RESULT = dict(LinuxToolchainTest.GXX_4_9_RESULT)
ARM_GXX_4_9_RESULT['compiler'] = '/usr/bin/arm-linux-gnu-g++'
ARM_GCC_4_7_RESULT = LinuxToolchainTest.GXX_4_7_RESULT
ARM_GCC_5_RESULT = dict(LinuxToolchainTest.GCC_5_RESULT)
ARM_GCC_5_RESULT['compiler'] = '/usr/bin/arm-linux-gnu-gcc-5'
ARM_GXX_5_RESULT = dict(LinuxToolchainTest.GXX_5_RESULT)
ARM_GXX_5_RESULT['compiler'] = '/usr/bin/arm-linux-gnu-g++-5'
ARM_GCC_5_RESULT = LinuxToolchainTest.GCC_5_RESULT + {
'compiler': '/usr/bin/arm-linux-gnu-gcc-5',
}
ARM_GXX_5_RESULT = LinuxToolchainTest.GXX_5_RESULT + {
'compiler': '/usr/bin/arm-linux-gnu-g++-5',
}
CLANG_3_6_RESULT = LinuxToolchainTest.CLANG_3_6_RESULT
CLANGXX_3_6_RESULT = LinuxToolchainTest.CLANGXX_3_6_RESULT
GCC_4_9_RESULT = LinuxToolchainTest.GCC_4_9_RESULT
@ -693,8 +687,12 @@ class CrossCompileToolchainTest(BaseToolchainTest):
def test_cross_gcc(self):
self.do_toolchain_test(self.PATHS, {
'c_compiler': self.ARM_GCC_4_9_RESULT,
'cxx_compiler': self.ARM_GXX_4_9_RESULT,
'c_compiler': self.GCC_4_9_RESULT + {
'compiler': '/usr/bin/arm-linux-gnu-gcc',
},
'cxx_compiler': self.GXX_4_9_RESULT + {
'compiler': '/usr/bin/arm-linux-gnu-g++',
},
'host_c_compiler': self.GCC_4_9_RESULT,
'host_cxx_compiler': self.GXX_4_9_RESULT,
}, args=['--target=arm-unknown-linux-gnu'])

Просмотреть файл

@ -4,6 +4,7 @@
from __future__ import absolute_import, print_function, unicode_literals
import copy
import re
import types
import unittest
@ -18,6 +19,8 @@ from mozunit import (
)
from mozbuild.preprocessor import Preprocessor
from mozbuild.util import ReadOnlyNamespace
from mozpack import path as mozpath
class CompilerPreprocessor(Preprocessor):
@ -325,5 +328,88 @@ class TestFakeCompiler(unittest.TestCase):
})
class CompilerResult(ReadOnlyNamespace):
'''Helper of convenience to manipulate toolchain results in unit tests
When adding a dict, the result is a new CompilerResult with the values
from the dict replacing those from the CompilerResult, except for `flags`,
where the value from the dict extends the `flags` in `self`.
'''
def __init__(self, wrapper=None, compiler='', version='', type='',
flags=None):
if flags is None:
flags = []
if wrapper is None:
wrapper = []
super(CompilerResult, self).__init__(
flags=flags,
version=version,
type=type,
compiler=mozpath.abspath(compiler),
wrapper=wrapper,
)
def __add__(self, other):
assert isinstance(other, dict)
result = copy.deepcopy(self.__dict__)
for k, v in other.iteritems():
if k == 'flags':
result.setdefault(k, []).extend(v)
else:
result[k] = v
return CompilerResult(**result)
class TestCompilerResult(unittest.TestCase):
def test_compiler_result(self):
result = CompilerResult()
self.assertEquals(result.__dict__, {
'wrapper': [],
'compiler': mozpath.abspath(''),
'version': '',
'type': '',
'flags': [],
})
result = CompilerResult(
compiler='/usr/bin/gcc',
version='4.2.1',
type='gcc',
flags=['-std=gnu99'],
)
self.assertEquals(result.__dict__, {
'wrapper': [],
'compiler': mozpath.abspath('/usr/bin/gcc'),
'version': '4.2.1',
'type': 'gcc',
'flags': ['-std=gnu99'],
})
result2 = result + {'flags': ['-m32']}
self.assertEquals(result2.__dict__, {
'wrapper': [],
'compiler': mozpath.abspath('/usr/bin/gcc'),
'version': '4.2.1',
'type': 'gcc',
'flags': ['-std=gnu99', '-m32'],
})
# Original flags are untouched.
self.assertEquals(result.flags, ['-std=gnu99'])
result3 = result + {
'compiler': '/usr/bin/gcc-4.7',
'version': '4.7.3',
'flags': ['-m32'],
}
self.assertEquals(result3.__dict__, {
'wrapper': [],
'compiler': mozpath.abspath('/usr/bin/gcc-4.7'),
'version': '4.7.3',
'type': 'gcc',
'flags': ['-std=gnu99', '-m32'],
})
if __name__ == '__main__':
main()

Просмотреть файл

@ -106,6 +106,9 @@ class ReadOnlyNamespace(object):
def __eq__(self, other):
return self is other or self.__dict__ == other.__dict__
def __repr__(self):
return '<%s %r>' % (self.__class__.__name__, self.__dict__)
class ReadOnlyDict(dict):
"""A read-only dictionary."""