Exemple #1
0
class TestMsvcStaticLinker(CrossPlatformTestCase):
    def __init__(self, *args, **kwargs):
        super().__init__(clear_variables=True, *args, **kwargs)

    def setUp(self):
        with mock.patch('bfg9000.shell.which', mock_which):
            self.linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'],
                                      True, 'version').linker('static_library')

    def test_call(self):
        self.assertEqual(self.linker(['in'], 'out'),
                         [self.linker, 'in', '/OUT:out'])
        self.assertEqual(self.linker(['in'], 'out', flags=['flags']),
                         [self.linker, 'flags', 'in', '/OUT:out'])

    def test_output_file(self):
        fmt = self.env.target_platform.object_format
        self.assertEqual(
            self.linker.output_file('lib', AttrDict(input_langs=['c++'])),
            StaticLibrary(Path('lib.lib'), fmt, ['c++'])
        )

    def test_can_link(self):
        fmt = self.env.target_platform.object_format
        self.assertTrue(self.linker.can_link(fmt, ['c', 'c++']))
        self.assertTrue(self.linker.can_link(fmt, ['goofy']))
        self.assertFalse(self.linker.can_link('goofy', ['c']))

    def test_flags_empty(self):
        self.assertEqual(self.linker.flags(opts.option_list()), [])

    def test_flags_string(self):
        self.assertEqual(self.linker.flags(opts.option_list('-v')), ['-v'])

    def test_flags_invalid(self):
        with self.assertRaises(TypeError):
            self.linker.flags(opts.option_list(123))

    def test_parse_flags(self):
        self.assertEqual(self.linker.parse_flags([]), {'extra': []})
        self.assertEqual(self.linker.parse_flags(['/foo', 'bar']),
                         {'extra': ['/foo', 'bar']})
Exemple #2
0
class TestMsvcCompiler(CrossPlatformTestCase):
    def __init__(self, *args, **kwargs):
        super().__init__(clear_variables=True, *args, **kwargs)

    def setUp(self):
        with mock.patch('bfg9000.shell.which', mock_which):
            self.compiler = MsvcBuilder(self.env, known_langs['c++'], ['cl'],
                                        True, 'version').compiler

    def test_call(self):
        extra = self.compiler._always_flags
        self.assertEqual(self.compiler('in', 'out'),
                         [self.compiler] + extra + ['/c', 'in', '/Foout'])
        self.assertEqual(self.compiler('in', 'out',
                                       flags=['flags']), [self.compiler] +
                         extra + ['flags', '/c', 'in', '/Foout'])

        self.assertEqual(self.compiler('in', 'out', 'out.d'), [self.compiler] +
                         extra + ['/showIncludes', '/c', 'in', '/Foout'])
        self.assertEqual(self.compiler('in', 'out', 'out.d',
                                       ['flags']), [self.compiler] + extra +
                         ['flags', '/showIncludes', '/c', 'in', '/Foout'])

    def test_default_name(self):
        src = SourceFile(Path('file.cpp', Root.srcdir), 'c++')
        self.assertEqual(self.compiler.default_name(src, None), 'file')

    def test_output_file(self):
        fmt = self.env.target_platform.object_format
        self.assertEqual(self.compiler.output_file('file', None),
                         ObjectFile(Path('file.obj'), fmt, 'c++'))

    def test_flags_empty(self):
        self.assertEqual(self.compiler.flags(opts.option_list()), ['/MD'])

    def test_flags_include_dir(self):
        p = self.Path('/path/to/include')
        self.assertEqual(
            self.compiler.flags(
                opts.option_list(opts.include_dir(HeaderDirectory(p)))),
            ['/I' + p, '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(
                opts.include_dir(HeaderDirectory(p))),
                                mode='pkg-config'), ['-I' + p])

    def test_flags_define(self):
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.define('NAME'))),
            ['/DNAME', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.define('NAME')),
                                mode='pkg-config'), ['-DNAME'])

        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.define('NAME',
                                                             'value'))),
            ['/DNAME=value', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.define('NAME', 'value')),
                                mode='pkg-config'), ['-DNAME=value'])

    def test_flags_std(self):
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.std('c++14'))),
            ['/std:c++14', '/MD'])

    def test_flags_static(self):
        self.assertEqual(self.compiler.flags(opts.option_list(opts.static())),
                         ['/MT'])

        self.assertEqual(
            self.compiler.flags(
                opts.option_list(),
                opts.option_list(opts.static()),
            ), ['/MT'])

    def test_flags_debug(self):
        self.assertEqual(self.compiler.flags(opts.option_list(opts.debug())),
                         ['/Zi', '/MDd'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.debug(), opts.static())),
            ['/Zi', '/MTd'])

        self.assertEqual(
            self.compiler.flags(
                opts.option_list(),
                opts.option_list(opts.debug()),
            ), ['/MDd'])
        self.assertEqual(
            self.compiler.flags(
                opts.option_list(opts.static()),
                opts.option_list(opts.debug()),
            ), ['/MTd'])

    def test_flags_warning(self):
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.warning('disable'))),
            ['/w', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.warning('all'))),
            ['/W3', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.warning('extra'))),
            ['/W4', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.warning('error'))),
            ['/WX', '/MD'])

        self.assertEqual(
            self.compiler.flags(
                opts.option_list(opts.warning('all', 'extra', 'error'))),
            ['/W3', '/W4', '/WX', '/MD'])

        with self.assertRaises(ValueError):
            self.compiler.flags(opts.option_list(opts.warning('unknown')))

    def test_flags_optimize(self):
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.optimize('disable'))),
            ['/Od', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.optimize('size'))),
            ['/O1', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.optimize('speed'))),
            ['/O2', '/MD'])
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.optimize('linktime'))),
            ['/GL', '/MD'])

        self.assertEqual(
            self.compiler.flags(
                opts.option_list(opts.optimize('speed', 'linktime'))),
            ['/O2', '/GL', '/MD'])

    def test_flags_include_pch(self):
        p = self.Path('/path/to/header.hpp')
        self.assertEqual(
            self.compiler.flags(
                opts.option_list(
                    opts.pch(
                        MsvcPrecompiledHeader(p, p, 'header', 'native',
                                              'c++')))), ['/Yuheader', '/MD'])

    def test_flags_sanitize(self):
        self.assertEqual(
            self.compiler.flags(opts.option_list(opts.sanitize())),
            ['/RTC1', '/MD'])

    def test_flags_string(self):
        self.assertEqual(self.compiler.flags(opts.option_list('-v')),
                         ['-v', '/MD'])

    def test_flags_invalid(self):
        with self.assertRaises(TypeError):
            self.compiler.flags(opts.option_list(123))

    def test_parse_flags(self):
        default = {
            'debug': None,
            'defines': [],
            'extra': [],
            'includes': [],
            'nologo': None,
            'pch': {
                'create': None,
                'use': None
            },
            'runtime': None,
            'warnings': {
                'as_error': None,
                'level': None
            }
        }

        def assertFlags(flags, extra={}):
            self.assertEqual(self.compiler.parse_flags(flags),
                             merge_dicts(default, extra))

        assertFlags([])
        assertFlags(['/un', 'known'], {'extra': ['/un', 'known']})
        assertFlags(['/nologo'], {'nologo': True})
        assertFlags(['/Dfoo'], {'defines': ['foo']})
        assertFlags(['/Idir'], {'includes': ['dir']})

        assertFlags(['/Z7'], {'debug': 'old'})
        assertFlags(['/Zi'], {'debug': 'pdb'})
        assertFlags(['/ZI'], {'debug': 'edit'})

        assertFlags(['/W0'], {'warnings': {'level': '0'}})
        assertFlags(['/Wall'], {'warnings': {'level': 'all'}})
        assertFlags(['/WX'], {'warnings': {'as_error': True}})
        assertFlags(['/WX-'], {'warnings': {'as_error': False}})
        assertFlags(['/w'], {'warnings': {'level': '0'}})

        assertFlags(['/Yufoo'], {'pch': {'use': 'foo'}})
        assertFlags(['/Ycfoo'], {'pch': {'create': 'foo'}})
Exemple #3
0
class TestMsvcLinker(CrossPlatformTestCase):
    def __init__(self, *args, **kwargs):
        CrossPlatformTestCase.__init__(self,
                                       clear_variables=True,
                                       *args,
                                       **kwargs)

    def setUp(self):
        version = ('Microsoft (R) C/C++ Optimizing Compiler Version ' +
                   '19.12.25831 for x86')
        with mock.patch('bfg9000.shell.which', mock_which):
            self.linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'],
                                      version).linker('executable')

    def test_call(self):
        extra = self.linker._always_flags
        self.assertEqual(self.linker(['in'], 'out'),
                         [self.linker] + extra + ['in', '/OUT:out'])
        self.assertEqual(self.linker(['in'], 'out', flags=['flags']),
                         [self.linker] + extra + ['flags', 'in', '/OUT:out'])

        self.assertEqual(self.linker(['in'], 'out', ['lib']),
                         [self.linker] + extra + ['in', 'lib', '/OUT:out'])
        self.assertEqual(self.linker(['in'], 'out', ['lib'],
                                     ['flags']), [self.linker] + extra +
                         ['flags', 'in', 'lib', '/OUT:out'])

    def test_output_file(self):
        fmt = self.env.target_platform.object_format
        ext = self.env.target_platform.executable_ext
        self.assertEqual(self.linker.output_file('prog', None),
                         file_types.Executable(Path('prog' + ext), fmt, 'c++'))

    def test_flags_empty(self):
        self.assertEqual(self.linker.flags(opts.option_list()), [])

    def test_flags_lib_dir(self):
        libdir = self.Path('/path/to/lib')
        lib = self.Path('/path/to/lib/foo.so')

        # Lib dir
        self.assertEqual(
            self.linker.flags(
                opts.option_list(opts.lib_dir(file_types.Directory(libdir)))),
            ['/LIBPATH:' + libdir])
        self.assertEqual(
            self.linker.flags(opts.option_list(
                opts.lib_dir(file_types.Directory(libdir))),
                              mode='pkg-config'), ['-L' + libdir])

        # Shared library
        self.assertEqual(
            self.linker.flags(
                opts.option_list(
                    opts.lib(file_types.SharedLibrary(lib, 'native')))), [])

        # Static library
        self.assertEqual(
            self.linker.flags(
                opts.option_list(
                    opts.lib(file_types.StaticLibrary(lib, 'native')))), [])

        # Mixed
        self.assertEqual(
            self.linker.flags(
                opts.option_list(
                    opts.lib_dir(file_types.Directory(libdir)),
                    opts.lib(file_types.SharedLibrary(lib, 'native')))),
            ['/LIBPATH:' + libdir])

    def test_flags_module_def(self):
        path = self.Path('/path/to/module.def')
        self.assertEqual(
            self.linker.flags(
                opts.option_list(
                    opts.module_def(file_types.ModuleDefFile(path)))),
            ['/DEF:' + path])

    def test_flags_debug(self):
        self.assertEqual(self.linker.flags(opts.option_list(opts.debug())),
                         ['/DEBUG'])

    def test_flags_optimize(self):
        self.assertEqual(
            self.linker.flags(opts.option_list(opts.optimize('disable'))), [])
        self.assertEqual(
            self.linker.flags(opts.option_list(opts.optimize('size'))), [])
        self.assertEqual(
            self.linker.flags(opts.option_list(opts.optimize('speed'))), [])
        self.assertEqual(
            self.linker.flags(opts.option_list(opts.optimize('linktime'))),
            ['/LTCG'])

        self.assertEqual(
            self.linker.flags(
                opts.option_list(opts.optimize('speed', 'linktime'))),
            ['/LTCG'])

    def test_flags_string(self):
        self.assertEqual(self.linker.flags(opts.option_list('-v')), ['-v'])

    def test_flags_lib_literal(self):
        self.assertEqual(
            self.linker.flags(opts.option_list(opts.lib_literal('-lfoo'))), [])

    def test_flags_invalid(self):
        with self.assertRaises(TypeError):
            self.linker.flags(opts.option_list(123))

    def test_lib_flags_empty(self):
        self.assertEqual(self.linker.lib_flags(opts.option_list()), [])

    def test_lib_flags_lib(self):
        lib = self.Path('/path/to/lib/foo.lib')

        self.assertEqual(
            self.linker.lib_flags(
                opts.option_list(
                    opts.lib(file_types.SharedLibrary(lib, 'native')))), [lib])
        self.assertEqual(
            self.linker.lib_flags(opts.option_list(
                opts.lib(file_types.SharedLibrary(lib, 'native'))),
                                  mode='pkg-config'), ['-lfoo'])

        self.assertEqual(
            self.linker.lib_flags(
                opts.option_list(
                    opts.lib(
                        file_types.WholeArchive(
                            file_types.SharedLibrary(lib, 'native'))))),
            ['/WHOLEARCHIVE:' + lib])

        version = ('Microsoft (R) C/C++ Optimizing Compiler Version ' +
                   '18.00.25831 for x86')
        with mock.patch('bfg9000.shell.which', mock_which):
            linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'],
                                 version).linker('executable')
        with self.assertRaises(TypeError):
            linker.lib_flags(
                opts.option_list(
                    opts.lib(
                        file_types.WholeArchive(
                            file_types.StaticLibrary(lib, 'native')))))

        with self.assertRaises(TypeError):
            self.linker.lib_flags(
                opts.option_list(opts.lib(Framework('cocoa'))))

    def test_lib_flags_lib_literal(self):
        self.assertEqual(
            self.linker.lib_flags(opts.option_list(opts.lib_literal('/?'))),
            ['/?'])

    def test_lib_flags_ignored(self):
        self.assertEqual(self.linker.lib_flags(opts.option_list('-Lfoo')), [])

    def test_parse_flags(self):
        default = {
            'extra': [],
            'libs': [],
            'nologo': None,
        }

        def assertFlags(flags, libflags, extra={}):
            self.assertEqual(self.linker.parse_flags(flags, libflags),
                             merge_dicts(default, extra))

        assertFlags([], [])
        assertFlags(['/foo', 'bar'], ['/baz', 'quux'], {
            'libs': ['quux'],
            'extra': ['/foo', 'bar', '/baz']
        })
        assertFlags(['/nologo'], [], {'nologo': True})
        assertFlags([], ['/nologo'], {'nologo': True})
        assertFlags(['/nologo'], ['/nologo'], {'nologo': True})