Пример #1
0
 def test_link_environment_variable_d(self):
     env = get_fake_env()
     comp = detect_d_compiler(env, MachineChoice.HOST)
     if comp.id == 'dmd':
         raise SkipTest(
             'meson cannot reliably make DMD use a different linker.')
     self._check_ld('lld-link', 'd', 'lld-link')
Пример #2
0
 def wrapped(*args, **kwargs):
     try:
         compiler_from_language(get_fake_env(), lang,
                                MachineChoice.HOST)
     except EnvironmentException:
         raise unittest.SkipTest(f'No {lang} compiler found.')
     return func(*args, **kwargs)
Пример #3
0
 def test_pefile_checksum(self):
     try:
         import pefile
     except ImportError:
         if is_ci():
             raise
         raise SkipTest('pefile module not found')
     testdir = os.path.join(self.common_test_dir, '6 linkshared')
     self.init(testdir, extra_args=['--buildtype=release'])
     self.build()
     # Test that binaries have a non-zero checksum
     env = get_fake_env()
     cc = detect_c_compiler(env, MachineChoice.HOST)
     cc_id = cc.get_id()
     ld_id = cc.get_linker_id()
     dll = glob(os.path.join(self.builddir, '*mycpplib.dll'))[0]
     exe = os.path.join(self.builddir, 'cppprog.exe')
     for f in (dll, exe):
         pe = pefile.PE(f)
         msg = f'PE file: {f!r}, compiler: {cc_id!r}, linker: {ld_id!r}'
         if cc_id == 'clang-cl':
             # Latest clang-cl tested (7.0) does not write checksums out
             self.assertFalse(pe.verify_checksum(), msg=msg)
         else:
             # Verify that a valid checksum was written by all other compilers
             self.assertTrue(pe.verify_checksum(), msg=msg)
Пример #4
0
 def test_qt5dependency_vscrt(self):
     '''
     Test that qt5 dependencies use the debug module suffix when b_vscrt is
     set to 'mdd'
     '''
     # Verify that the `b_vscrt` option is available
     env = get_fake_env()
     cc = detect_c_compiler(env, MachineChoice.HOST)
     if OptionKey('b_vscrt') not in cc.base_options:
         raise SkipTest('Compiler does not support setting the VS CRT')
     # Verify that qmake is for Qt5
     if not shutil.which('qmake-qt5'):
         if not shutil.which('qmake') and not is_ci():
             raise SkipTest('QMake not found')
         output = subprocess.getoutput('qmake --version')
         if 'Qt version 5' not in output and not is_ci():
             raise SkipTest('Qmake found, but it is not for Qt 5.')
     # Setup with /MDd
     testdir = os.path.join(self.framework_test_dir, '4 qt')
     self.init(testdir, extra_args=['-Db_vscrt=mdd'])
     # Verify that we're linking to the debug versions of Qt DLLs
     build_ninja = os.path.join(self.builddir, 'build.ninja')
     with open(build_ninja, encoding='utf-8') as f:
         contents = f.read()
         m = re.search('build qt5core.exe: cpp_LINKER.*Qt5Cored.lib',
                       contents)
     self.assertIsNotNone(m, msg=contents)
Пример #5
0
    def test_rc_depends_files(self):
        testdir = os.path.join(self.platform_test_dir, '5 resources')

        # resource compiler depfile generation is not yet implemented for msvc
        env = get_fake_env(testdir, self.builddir, self.prefix)
        depfile_works = detect_c_compiler(env,
                                          MachineChoice.HOST).get_id() not in {
                                              'msvc', 'clang-cl', 'intel-cl'
                                          }

        self.init(testdir)
        self.build()
        # Immediately rebuilding should not do anything
        self.assertBuildIsNoop()
        # Test compile_resources(depend_file:)
        # Changing mtime of sample.ico should rebuild prog
        self.utime(os.path.join(testdir, 'res', 'sample.ico'))
        self.assertRebuiltTarget('prog')
        # Test depfile generation by compile_resources
        # Changing mtime of resource.h should rebuild myres.rc and then prog
        if depfile_works:
            self.utime(os.path.join(testdir, 'inc', 'resource', 'resource.h'))
            self.assertRebuiltTarget('prog')
        self.wipe()

        if depfile_works:
            testdir = os.path.join(self.platform_test_dir,
                                   '12 resources with custom targets')
            self.init(testdir)
            self.build()
            # Immediately rebuilding should not do anything
            self.assertBuildIsNoop()
            # Changing mtime of resource.h should rebuild myres_1.rc and then prog_1
            self.utime(os.path.join(testdir, 'res', 'resource.h'))
            self.assertRebuiltTarget('prog_1')
Пример #6
0
 def wrapped(*args, **kwargs):
     env = get_fake_env()
     cc = detect_c_compiler(env, MachineChoice.HOST)
     key = OptionKey(feature)
     if key not in cc.base_options:
         raise unittest.SkipTest(
             f'{feature} not available with {cc.id}')
     return f(*args, **kwargs)
Пример #7
0
 def test_all_functions_defined_in_ast_interpreter(self):
     '''
     Ensure that the all functions defined in the Interpreter are also defined
     in the AstInterpreter (and vice versa).
     '''
     env = get_fake_env()
     interp = Interpreter(FakeBuild(env), mock=True)
     astint = AstInterpreter('.', '', '')
     self.assertEqual(set(interp.funcs.keys()), set(astint.funcs.keys()))
Пример #8
0
 def test_swift_compiler(self):
     wrapper = self.helper_create_binary_wrapper(
         'swiftc',
         version='Swift 1.2345',
         outfile='stderr',
         extra_args={'Xlinker': 'macosx_version. PROJECT:ld - 1.2.3'})
     env = get_fake_env()
     env.binaries.host.binaries['swift'] = [wrapper]
     compiler = detect_swift_compiler(env, MachineChoice.HOST)
     self.assertEqual(compiler.version, '1.2345')
Пример #9
0
 def helper_for_compiler(self, lang, cb, for_machine=MachineChoice.HOST):
     """Helper for generating tests for overriding compilers for langaugages
     with more than one implementation, such as C, C++, ObjC, ObjC++, and D.
     """
     env = get_fake_env()
     getter = lambda: compiler_from_language(env, lang, for_machine)
     cc = getter()
     binary, newid = cb(cc)
     env.binaries[for_machine].binaries[lang] = binary
     compiler = getter()
     self.assertEqual(compiler.id, newid)
Пример #10
0
 def test_vim_syntax_highlighting(self):
     '''
     Ensure that vim syntax highlighting files were updated for new
     functions in the global namespace in build files.
     '''
     env = get_fake_env()
     interp = Interpreter(FakeBuild(env), mock=True)
     with open('data/syntax-highlighting/vim/syntax/meson.vim', encoding='utf-8') as f:
         res = re.search(r'syn keyword mesonBuiltin(\s+\\\s\w+)+', f.read(), re.MULTILINE)
         defined = set([a.strip() for a in res.group().split('\\')][1:])
         self.assertEqual(defined, set(chain(interp.funcs.keys(), interp.builtin.keys())))
Пример #11
0
 def test_objc_cpp_detection(self):
     '''
     Test that when we can't detect objc or objcpp, we fail gracefully.
     '''
     env = get_fake_env()
     try:
         detect_objc_compiler(env, MachineChoice.HOST)
         detect_objcpp_compiler(env, MachineChoice.HOST)
     except EnvironmentException:
         code = "add_languages('objc')\nadd_languages('objcpp')"
         self.assertMesonRaises(code, "Unknown compiler")
         return
     raise unittest.SkipTest("objc and objcpp found, can't test detection failure")
Пример #12
0
    def _single_implementation_compiler(self, lang: str, binary: str,
                                        version_str: str,
                                        version: str) -> None:
        """Helper for languages with a single (supported) implementation.

        Builds a wrapper around the compiler to override the version.
        """
        wrapper = self.helper_create_binary_wrapper(binary,
                                                    version=version_str)
        env = get_fake_env()
        env.binaries.host.binaries[lang] = [wrapper]
        compiler = compiler_from_language(env, lang, MachineChoice.HOST)
        self.assertEqual(compiler.version, version)
Пример #13
0
 def test_non_utf8_fails(self):
     # FIXME: VS backend does not use flags from compiler.get_always_args()
     # and thus it's missing /utf-8 argument. Was that intentional? This needs
     # to be revisited.
     if self.backend is not Backend.ninja:
         raise SkipTest(f'This test only pass with ninja backend (not {self.backend.name}).')
     testdir = os.path.join(self.platform_test_dir, '18 msvc charset')
     env = get_fake_env(testdir, self.builddir, self.prefix)
     cc = detect_c_compiler(env, MachineChoice.HOST)
     if cc.get_argument_syntax() != 'msvc':
         raise SkipTest('Not using MSVC')
     self.init(testdir, extra_args=['-Dtest-failure=true'])
     self.assertRaises(subprocess.CalledProcessError, self.build)
Пример #14
0
    def test_install_pdb_introspection(self):
        testdir = os.path.join(self.platform_test_dir, '1 basic')

        env = get_fake_env(testdir, self.builddir, self.prefix)
        cc = detect_c_compiler(env, MachineChoice.HOST)
        if cc.get_argument_syntax() != 'msvc':
            raise SkipTest('Test only applies to MSVC-like compilers')

        self.init(testdir)
        installed = self.introspect('--installed')
        files = [os.path.basename(path) for path in installed.values()]

        self.assertIn('prog.pdb', files)
Пример #15
0
 def test_ignore_libs(self):
     '''
     Test that find_library on libs that are to be ignored returns an empty
     array of arguments. Must be a unit test because we cannot inspect
     ExternalLibraryHolder from build files.
     '''
     testdir = os.path.join(self.platform_test_dir, '1 basic')
     env = get_fake_env(testdir, self.builddir, self.prefix)
     cc = detect_c_compiler(env, MachineChoice.HOST)
     if cc.get_argument_syntax() != 'msvc':
         raise SkipTest('Not using MSVC')
     # To force people to update this test, and also test
     self.assertEqual(set(cc.ignore_libs), {'c', 'm', 'pthread', 'dl', 'rt', 'execinfo'})
     for l in cc.ignore_libs:
         self.assertEqual(cc.find_library(l, env, []), [])
Пример #16
0
    def test_msvc_cpp17(self):
        testdir = os.path.join(self.unit_test_dir, '45 vscpp17')

        env = get_fake_env(testdir, self.builddir, self.prefix)
        cc = detect_c_compiler(env, MachineChoice.HOST)
        if cc.get_argument_syntax() != 'msvc':
            raise SkipTest('Test only applies to MSVC-like compilers')

        try:
            self.init(testdir)
        except subprocess.CalledProcessError:
            # According to Python docs, output is only stored when
            # using check_output. We don't use it, so we can't check
            # that the output is correct (i.e. that it failed due
            # to the right reason).
            return
        self.build()
Пример #17
0
    def _check_ld(self, name: str, lang: str, expected: str) -> None:
        if not shutil.which(name):
            raise SkipTest(f'Could not find {name}.')
        envvars = [mesonbuild.envconfig.ENV_VAR_PROG_MAP[f'{lang}_ld']]

        # Also test a deprecated variable if there is one.
        if f'{lang}_ld' in mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP:
            envvars.append(
                mesonbuild.envconfig.DEPRECATED_ENV_PROG_MAP[f'{lang}_ld'])

        for envvar in envvars:
            with mock.patch.dict(os.environ, {envvar: name}):
                env = get_fake_env()
                try:
                    comp = compiler_from_language(env, lang, MachineChoice.HOST)
                except EnvironmentException:
                    raise SkipTest(f'Could not find a compiler for {lang}')
                self.assertEqual(comp.linker.id, expected)
Пример #18
0
    def test_compiler_checks_vscrt(self):
        '''
        Test that the correct VS CRT is used when running compiler checks
        '''
        # Verify that the `b_vscrt` option is available
        env = get_fake_env()
        cc = detect_c_compiler(env, MachineChoice.HOST)
        if OptionKey('b_vscrt') not in cc.base_options:
            raise SkipTest('Compiler does not support setting the VS CRT')

        def sanitycheck_vscrt(vscrt):
            checks = self.get_meson_log_sanitychecks()
            self.assertTrue(len(checks) > 0)
            for check in checks:
                self.assertIn(vscrt, check)

        testdir = os.path.join(self.common_test_dir, '1 trivial')
        self.init(testdir)
        sanitycheck_vscrt('/MDd')

        self.new_builddir()
        self.init(testdir, extra_args=['-Dbuildtype=debugoptimized'])
        sanitycheck_vscrt('/MD')

        self.new_builddir()
        self.init(testdir, extra_args=['-Dbuildtype=release'])
        sanitycheck_vscrt('/MD')

        self.new_builddir()
        self.init(testdir, extra_args=['-Db_vscrt=md'])
        sanitycheck_vscrt('/MD')

        self.new_builddir()
        self.init(testdir, extra_args=['-Db_vscrt=mdd'])
        sanitycheck_vscrt('/MDd')

        self.new_builddir()
        self.init(testdir, extra_args=['-Db_vscrt=mt'])
        sanitycheck_vscrt('/MT')

        self.new_builddir()
        self.init(testdir, extra_args=['-Db_vscrt=mtd'])
        sanitycheck_vscrt('/MTd')
Пример #19
0
 def test_compiler_options_documented(self):
     '''
     Test that C and C++ compiler options and base options are documented in
     Builtin-Options.md. Only tests the default compiler for the current
     platform on the CI.
     '''
     md = None
     with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
         md = f.read()
     self.assertIsNotNone(md)
     env = get_fake_env()
     # FIXME: Support other compilers
     cc = detect_c_compiler(env, MachineChoice.HOST)
     cpp = detect_cpp_compiler(env, MachineChoice.HOST)
     for comp in (cc, cpp):
         for opt in comp.get_options():
             self.assertIn(str(opt), md)
         for opt in comp.base_options:
             self.assertIn(str(opt), md)
     self.assertNotIn('b_unknown', md)
Пример #20
0
 def test_apple_bitcode(self):
     '''
     Test that -fembed-bitcode is correctly added while compiling and
     -bitcode_bundle is added while linking when b_bitcode is true and not
     when it is false.  This can't be an ordinary test case because we need
     to inspect the compiler database.
     '''
     testdir = os.path.join(self.platform_test_dir, '7 bitcode')
     env = get_fake_env(testdir, self.builddir, self.prefix)
     cc = detect_c_compiler(env, MachineChoice.HOST)
     if cc.id != 'clang':
         raise unittest.SkipTest('Not using Clang on OSX')
     # Try with bitcode enabled
     out = self.init(testdir, extra_args='-Db_bitcode=true')
     # Warning was printed
     self.assertRegex(out, 'WARNING:.*b_bitcode')
     # Compiler options were added
     for compdb in self.get_compdb():
         if 'module' in compdb['file']:
             self.assertNotIn('-fembed-bitcode', compdb['command'])
         else:
             self.assertIn('-fembed-bitcode', compdb['command'])
     build_ninja = os.path.join(self.builddir, 'build.ninja')
     # Linker options were added
     with open(build_ninja, encoding='utf-8') as f:
         contents = f.read()
         m = re.search('LINK_ARGS =.*-bitcode_bundle', contents)
     self.assertIsNotNone(m, msg=contents)
     # Try with bitcode disabled
     self.setconf('-Db_bitcode=false')
     # Regenerate build
     self.build()
     for compdb in self.get_compdb():
         self.assertNotIn('-fembed-bitcode', compdb['command'])
     build_ninja = os.path.join(self.builddir, 'build.ninja')
     with open(build_ninja, encoding='utf-8') as f:
         contents = f.read()
         m = re.search('LINK_ARGS =.*-bitcode_bundle', contents)
     self.assertIsNone(m, msg=contents)
Пример #21
0
 def test_link_environment_variable_optlink(self):
     env = get_fake_env()
     comp = detect_c_compiler(env, MachineChoice.HOST)
     if isinstance(comp, GnuLikeCompiler):
         raise SkipTest('GCC cannot be used with link compatible linkers.')
     self._check_ld('optlink', 'c', 'optlink')
Пример #22
0
    def test_builtin_options_documented(self):
        '''
        Test that universal options and base options are documented in
        Builtin-Options.md.
        '''
        from itertools import tee
        md = None
        with open('docs/markdown/Builtin-options.md', encoding='utf-8') as f:
            md = f.read()
        self.assertIsNotNone(md)

        found_entries = set()
        sections = re.finditer(r"^## (.+)$", md, re.MULTILINE)
        # Extract the content for this section
        content = self._get_section_content("Universal options", sections, md)
        subsections = tee(re.finditer(r"^### (.+)$", content, re.MULTILINE))
        subcontent1 = self._get_section_content("Directories", subsections[0], content)
        subcontent2 = self._get_section_content("Core options", subsections[1], content)
        subcontent3 = self._get_section_content("Module options", sections, md)
        for subcontent in (subcontent1, subcontent2, subcontent3):
            # Find the option names
            options = set()
            # Match either a table row or a table heading separator: | ------ |
            rows = re.finditer(r"^\|(?: (\w+) .* | *-+ *)\|", subcontent, re.MULTILINE)
            # Skip the header of the first table
            next(rows)
            # Skip the heading separator of the first table
            next(rows)
            for m in rows:
                value = m.group(1)
                # End when the `buildtype` table starts
                if value is None:
                    break
                options.add(value)
            self.assertEqual(len(found_entries & options), 0)
            found_entries |= options

        self.assertEqual(found_entries, {
            *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS),
            *(str(k.evolve(module=None)) for k in mesonbuild.coredata.BUILTIN_OPTIONS_PER_MACHINE),
        })

        # Check that `buildtype` table inside `Core options` matches how
        # setting of builtin options behaves
        #
        # Find all tables inside this subsection
        tables = re.finditer(r"^\| (\w+) .* \|\n\| *[-|\s]+ *\|$", subcontent2, re.MULTILINE)
        # Get the table we want using the header of the first column
        table = self._get_section_content('buildtype', tables, subcontent2)
        # Get table row data
        rows = re.finditer(r"^\|(?: (\w+)\s+\| (\w+)\s+\| (\w+) .* | *-+ *)\|", table, re.MULTILINE)
        env = get_fake_env()
        for m in rows:
            buildtype, debug, opt = m.groups()
            if debug == 'true':
                debug = True
            elif debug == 'false':
                debug = False
            else:
                raise RuntimeError(f'Invalid debug value {debug!r} in row:\n{m.group()}')
            env.coredata.set_option(OptionKey('buildtype'), buildtype)
            self.assertEqual(env.coredata.options[OptionKey('buildtype')].value, buildtype)
            self.assertEqual(env.coredata.options[OptionKey('optimization')].value, opt)
            self.assertEqual(env.coredata.options[OptionKey('debug')].value, debug)