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(SharedLibrary(lib, 'native')))), [lib]) self.assertEqual( self.linker.lib_flags(opts.option_list( opts.lib(SharedLibrary(lib, 'native'))), mode='pkg-config'), ['-lfoo']) self.assertEqual( self.linker.lib_flags( opts.option_list( opts.lib(WholeArchive(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(WholeArchive(StaticLibrary(lib, 'native'))))) with self.assertRaises(TypeError): self.linker.lib_flags( opts.option_list(opts.lib(Framework('cocoa'))))
def setUp(self): self.env = make_env() 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 setUp(self): with mock.patch('bfg9000.shell.which', mock_which), \ mock.patch('bfg9000.shell.execute', mock_execute): self.builder = MsvcBuilder(self.env, known_langs['c++'], ['cl'], True, 'version') self.packages = self.builder.packages self.compiler = self.builder.compiler self.linker = self.builder.linker('executable') self.env.tool('pkg_config')
class TestMsvcPackageResolver(CrossPlatformTestCase): def __init__(self, *args, **kwargs): CrossPlatformTestCase.__init__(self, clear_variables=True, *args, **kwargs) def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.packages = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').packages def test_header_not_found(self): with mock.patch('bfg9000.tools.msvc.exists', return_value=False): with self.assertRaises(PackageResolutionError): self.packages.header('foo.hpp') def test_header_relpath(self): with self.assertRaises(ValueError): self.packages.header('foo.hpp', [Path('dir', Root.srcdir)]) def test_library_not_found(self): with mock.patch('bfg9000.tools.msvc.exists', return_value=False): with self.assertRaises(PackageResolutionError): self.packages.library('foo') def test_library_relpath(self): with self.assertRaises(ValueError): p = Path('dir', Root.srcdir) self.packages.library('foo', search_dirs=[p])
class TestMsvcStaticLinker(unittest.TestCase): def setUp(self): self.env = make_env() with mock.patch('bfg9000.shell.which', mock_which): self.linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').linker('static_library') 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))
class TestMsvcSharedLinker(TestMsvcLinker): def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').linker('shared_library') def test_call(self): extra = self.linker._always_flags self.assertEqual(self.linker(['in'], ['out', 'imp']), [self.linker] + extra + ['in', '/OUT:out', '/IMPLIB:imp']) self.assertEqual(self.linker(['in'], ['out', 'imp'], flags=['flags']), [self.linker] + extra + ['flags', 'in', '/OUT:out', '/IMPLIB:imp']) self.assertEqual(self.linker(['in'], ['out', 'imp'], ['lib']), [self.linker] + extra + ['in', 'lib', '/OUT:out', '/IMPLIB:imp']) self.assertEqual( self.linker(['in'], ['out', 'imp'], ['lib'], ['flags']), [self.linker] + extra + ['flags', 'in', 'lib', '/OUT:out', '/IMPLIB:imp']) def test_output_file(self): fmt = self.env.target_platform.object_format ext = self.env.target_platform.shared_library_ext out = file_types.DllBinary(Path('lib' + ext), fmt, 'c++', Path('lib.lib'), Path('lib.exp')) self.assertEqual(self.linker.output_file('lib', None), [out, out.import_lib, out.export_file])
def test_properties(self): with mock.patch('bfg9000.shell.which', mock_which): cc = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version') self.assertEqual(cc.flavor, 'msvc') self.assertEqual(cc.compiler.flavor, 'msvc') self.assertEqual(cc.pch_compiler.flavor, 'msvc') self.assertEqual(cc.linker('executable').flavor, 'msvc') self.assertEqual(cc.linker('shared_library').flavor, 'msvc') self.assertEqual(cc.linker('static_library').flavor, 'msvc') self.assertEqual(cc.family, 'native') self.assertEqual(cc.auto_link, True) self.assertEqual(cc.can_dual_link, False) self.assertEqual(cc.compiler.num_outputs, 'all') self.assertEqual(cc.pch_compiler.num_outputs, 2) self.assertEqual(cc.linker('executable').num_outputs, 'all') self.assertEqual(cc.linker('shared_library').num_outputs, 2) self.assertEqual(cc.compiler.deps_flavor, 'msvc') self.assertEqual(cc.pch_compiler.deps_flavor, 'msvc') self.assertEqual(cc.compiler.needs_libs, False) self.assertEqual(cc.pch_compiler.needs_libs, False) self.assertEqual(cc.compiler.accepts_pch, True) self.assertEqual(cc.pch_compiler.accepts_pch, False) self.assertRaises(KeyError, lambda: cc.linker('unknown'))
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']})
def test_clang(self): def mock_execute(args, **kwargs): if '--version' in args: return 'clang version 10.0.0' version = 'OVERVIEW: clang LLVM compiler' with mock.patch('bfg9000.shell.which', mock_which), \ mock.patch('bfg9000.shell.execute', mock_execute): cc = MsvcBuilder(self.env, known_langs['c++'], ['cl'], True, version) self.assertEqual(cc.brand, 'clang') self.assertEqual(cc.compiler.brand, 'clang') self.assertEqual(cc.pch_compiler.brand, 'clang') self.assertEqual(cc.linker('executable').brand, 'clang') self.assertEqual(cc.linker('shared_library').brand, 'clang') self.assertEqual(cc.version, Version('10.0.0')) self.assertEqual(cc.compiler.version, Version('10.0.0')) self.assertEqual(cc.pch_compiler.version, Version('10.0.0')) self.assertEqual(cc.linker('executable').version, Version('10.0.0')) self.assertEqual(cc.linker('shared_library').version, Version('10.0.0'))
class TestMsvcPchCompiler(TestMsvcCompiler): def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.compiler = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').pch_compiler def test_call(self): extra = self.compiler._always_flags self.assertEqual(self.compiler('in', ['out_pch', 'out']), [self.compiler] + extra + ['/c', 'in', '/Foout', '/Fpout_pch']) self.assertEqual( self.compiler('in', ['out_pch', 'out'], flags=['flags']), [self.compiler] + extra + ['flags', '/c', 'in', '/Foout', '/Fpout_pch'] ) self.assertEqual( self.compiler('in', ['out_pch', 'out'], 'out.d'), [self.compiler] + extra + ['/showIncludes', '/c', 'in', '/Foout', '/Fpout_pch'] ) self.assertEqual( self.compiler('in', ['out_pch', 'out'], 'out.d', ['flags']), [self.compiler] + extra + ['flags', '/showIncludes', '/c', 'in', '/Foout', '/Fpout_pch'] ) def test_default_name(self): hdr = HeaderFile(Path('file.hpp', Root.srcdir), 'c++') self.assertEqual(self.compiler.default_name(hdr, None), 'file.hpp') def test_output_file(self): fmt = self.env.target_platform.object_format out = MsvcPrecompiledHeader( Path('hdr.pch'), Path('src.obj'), 'hdr.h', fmt, 'c++' ) self.assertEqual(self.compiler.output_file('hdr.h', AttrDict( pch_source=SourceFile(Path('src.c'), 'c') )), [out, out.object_file])
def test_unknown_brand(self): version = 'unknown' with mock.patch('bfg9000.shell.which', mock_which): cc = MsvcBuilder(self.env, known_langs['c++'], ['c++'], version) self.assertEqual(cc.brand, 'unknown') self.assertEqual(cc.compiler.brand, 'unknown') self.assertEqual(cc.pch_compiler.brand, 'unknown') self.assertEqual(cc.linker('executable').brand, 'unknown') self.assertEqual(cc.linker('shared_library').brand, 'unknown') self.assertEqual(cc.version, None) self.assertEqual(cc.compiler.version, None) self.assertEqual(cc.pch_compiler.version, None) self.assertEqual(cc.linker('executable').version, None) self.assertEqual(cc.linker('shared_library').version, None)
def test_msvc(self): version = ('Microsoft (R) C/C++ Optimizing Compiler Version ' + '19.12.25831 for x86') with mock.patch('bfg9000.shell.which', mock_which): cc = MsvcBuilder(self.env, known_langs['c++'], ['cl'], version) self.assertEqual(cc.brand, 'msvc') self.assertEqual(cc.compiler.brand, 'msvc') self.assertEqual(cc.pch_compiler.brand, 'msvc') self.assertEqual(cc.linker('executable').brand, 'msvc') self.assertEqual(cc.linker('shared_library').brand, 'msvc') self.assertEqual(cc.version, Version('19.12.25831')) self.assertEqual(cc.compiler.version, Version('19.12.25831')) self.assertEqual(cc.pch_compiler.version, Version('19.12.25831')) self.assertEqual( cc.linker('executable').version, Version('19.12.25831')) self.assertEqual( cc.linker('shared_library').version, Version('19.12.25831'))
def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.compiler = MsvcBuilder(self.env, known_langs['c++'], ['cl'], True, 'version').pch_compiler
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'}})
def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.linker = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').linker('static_library')
def _get_linker(self, lang): version = ('Microsoft (R) C/C++ Optimizing Compiler Version ' + '19.12.25831 for x86') with mock.patch('bfg9000.shell.which', mock_which): # noqa return MsvcBuilder(self.env, known_langs[lang], ['cl'], version).linker('shared_library')
class TestMsvcPackageResolver(CrossPlatformTestCase): def __init__(self, *args, **kwargs): super().__init__(clear_variables=True, *args, **kwargs) def setUp(self): with mock.patch('bfg9000.shell.which', mock_which), \ mock.patch('bfg9000.shell.execute', mock_execute): self.builder = MsvcBuilder(self.env, known_langs['c++'], ['cl'], True, 'version') self.packages = self.builder.packages self.compiler = self.builder.compiler self.linker = self.builder.linker('executable') self.env.tool('pkg_config') def check_package(self, pkg): self.assertEqual(pkg.name, 'foo') self.assertEqual(pkg.compile_options(self.compiler), option_list( '/DMACRO', opts.include_dir(HeaderDirectory(Path('/path'))) )) self.assertEqual(pkg.link_options(self.linker), option_list( '/DEBUG', opts.lib_dir(Directory(Path('/path'))), opts.lib_literal('foo.lib'), (opts.rpath_dir(Path('/path')) if self.platform_name == 'linux' else None) )) def test_lang(self): self.assertEqual(self.packages.lang, 'c++') def test_resolve_pkg_config(self): usage = {'type': 'pkg_config', 'pcnames': ['foo'], 'pkg_config_path': ['/path/to/include']} with mock.patch('bfg9000.shell.execute', mock_execute_pkgconf), \ mock.patch('bfg9000.tools.msvc.exists', return_value=True), \ mock.patch('bfg9000.tools.mopack.get_usage', return_value=usage), \ mock.patch('bfg9000.log.info'): pkg = self.packages.resolve('foo', None, SpecifierSet(), PackageKind.any) self.check_package(pkg) def test_resolve_path(self): usage = {'type': 'path', 'generated': True, 'auto_link': False, 'pcnames': ['foo'], 'pkg_config_path': '/path/to/pkgconfig'} with mock.patch('bfg9000.shell.execute', mock_execute_pkgconf), \ mock.patch('bfg9000.tools.msvc.exists', return_value=True), \ mock.patch('bfg9000.tools.mopack.get_usage', return_value=usage), \ mock.patch('bfg9000.log.info'): pkg = self.packages.resolve('foo', None, SpecifierSet(), PackageKind.any) self.check_package(pkg) def test_resolve_path_auto_link(self): usage = {'type': 'path', 'generated': True, 'auto_link': True, 'pcnames': ['foo'], 'pkg_config_path': '/path/to/pkgconfig'} with mock.patch('bfg9000.shell.execute', mock_execute_pkgconf), \ mock.patch('bfg9000.tools.msvc.exists', return_value=True), \ mock.patch('bfg9000.tools.mopack.get_usage', return_value=usage), \ mock.patch('bfg9000.log.info'): pkg = self.packages.resolve('foo', None, SpecifierSet(), PackageKind.any) self.check_package(pkg)
def setUp(self): with mock.patch('bfg9000.shell.which', mock_which): self.packages = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').packages
class TestMsvcLinker(unittest.TestCase): def setUp(self): self.env = make_env() 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_flags_empty(self): self.assertEqual(self.linker.flags(opts.option_list()), []) def test_flags_lib_dir(self): libdir = Path('/path/to/lib') lib = 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')))), ['/LIBPATH:' + libdir]) # Static library self.assertEqual( self.linker.flags( opts.option_list( opts.lib(file_types.StaticLibrary(lib, 'native')))), ['/LIBPATH:' + libdir]) # 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_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 = Path('/path/to/lib/foo.lib') self.assertEqual( self.linker.lib_flags( opts.option_list( opts.lib(file_types.SharedLibrary(lib, 'native')))), [lib.basename()]) 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.basename()]) 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')), [])
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})
class TestMsvcCompiler(unittest.TestCase): def setUp(self): self.env = make_env() with mock.patch('bfg9000.shell.which', mock_which): self.compiler = MsvcBuilder(self.env, known_langs['c++'], ['cl'], 'version').compiler def test_flags_empty(self): self.assertEqual(self.compiler.flags(opts.option_list()), []) def test_flags_include_dir(self): p = Path('/path/to/include') self.assertEqual( self.compiler.flags( opts.option_list( opts.include_dir(file_types.HeaderDirectory(p)))), ['/I' + p]) self.assertEqual( self.compiler.flags(opts.option_list( opts.include_dir(file_types.HeaderDirectory(p))), mode='pkg-config'), ['-I' + p]) def test_flags_define(self): self.assertEqual( self.compiler.flags(opts.option_list(opts.define('NAME'))), ['/DNAME']) 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']) 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']) def test_flags_include_pch(self): p = Path('/path/to/header.hpp') self.assertEqual( self.compiler.flags( opts.option_list( opts.pch( file_types.MsvcPrecompiledHeader( p, None, 'header', 'native')))), ['/Yuheader']) def test_flags_string(self): self.assertEqual(self.compiler.flags(opts.option_list('-v')), ['-v']) def test_flags_invalid(self): with self.assertRaises(TypeError): self.compiler.flags(opts.option_list(123))