def validate_and_resolve(self, manual: ReferenceManual) -> ReferenceManual: mlog.log('Validating loaded manual...') # build type map and func map for methods for obj in manual.objects: assert obj.name not in self.type_map, f'Duplicate object name {obj.name}' self.type_map[obj.name] = obj for m in obj.methods: mid = f'{obj.name}.{m.name}' assert mid not in self.type_map, f'Duplicate metod {mid}' self.func_map[mid] = m # Build func map for functions for func in manual.functions: assert func.name not in [*self.func_map.keys() ], f'Duplicate function {func.name}' self.func_map[func.name] = func mlog.log('Validating functions...') for func in manual.functions: mlog.log(' -- validating', mlog.bold(func.name)) self._validate_func(func) mlog.log('Validating objects...') for obj in manual.objects: mlog.log(' -- validating', mlog.bold(obj.name)) self._validate_named_object(obj) self._validate_feature_check(obj) # Resolve and validate inheritence if obj.extends: assert obj.extends in self.type_map, f'Unknown extends object {obj.extends} in {obj.name}' obj.extends_obj = self.type_map[obj.extends] obj.extends_obj.extended_by += [obj] # Only returned objects can be associated with module if obj.obj_type is not ObjectType.RETURNED: assert obj.defined_by_module is None for m in obj.methods: assert m.obj is obj self._validate_func(m) # Resolve inherited methods for obj in manual.objects: inherited_methods = obj.inherited_methods curr = obj.extends_obj while curr is not None: inherited_methods += curr.methods curr = curr.extends_obj return manual
def generate_hotdoc_config(self): cwd = os.path.abspath(os.curdir) ncwd = os.path.join(self.sourcedir, self.subdir) mlog.log('Generating Hotdoc configuration for: ', mlog.bold(self.name)) os.chdir(ncwd) self.hotdoc.run_hotdoc(self.flatten_config_command()) os.chdir(cwd)
def _write_file(self, data: str, file_id: str) -> None: # ''' Write the data to disk ans store the id for the generated data ''' self.generated_files[file_id] = self._gen_filename(file_id) out_file = self.out_dir / self.generated_files[file_id] out_file.write_text(data, encoding='ascii') mlog.log('Generated', mlog.bold(out_file.name))
def print_system_info(): print(mlog.bold('System information.').get_text(mlog.colorize_console)) print('Architecture:', platform.architecture()) print('Machine:', platform.machine()) print('Platform:', platform.system()) print('Processor:', platform.processor()) print('System:', platform.system()) print('')
def generate(self) -> None: mlog.log('\n\n', mlog.bold('=== Functions ==='), '\n') for f in self.functions: self._generate_function(f) mlog.log('\n\n', mlog.bold('=== Elementary ==='), '\n') for obj in self.elementary: self._generate_object(obj) mlog.log('\n\n', mlog.bold('=== Builtins ==='), '\n') for obj in self.builtins: self._generate_object(obj) mlog.log('\n\n', mlog.bold('=== Returned objects ==='), '\n') for obj in self.returned: self._generate_object(obj) mlog.log('\n\n', mlog.bold('=== Modules ==='), '\n') for obj in self.modules: self._generate_object(obj) for mod_obj in self.extract_returned_by_module(obj): self._generate_object(mod_obj)
def _load_function(self, path: Path, obj: T.Optional[Object] = None) -> Function: path_label = path.relative_to(self.yaml_dir).as_posix() mlog.log('Loading', mlog.bold(path_label)) raw = self._load(self.read_file(path), self.template.s_function, label=path_label) return self._process_function_base(raw)
def print_system_info(): print(mlog.bold('System information.')) print('Architecture:', platform.architecture()) print('Machine:', platform.machine()) print('Platform:', platform.system()) print('Processor:', platform.processor()) print('System:', platform.system()) print('') print(flush=True)
def declaration(self, state, args, kwargs): if len(args) != 2: raise InterpreterException('declaration takes exactly two arguments.') check_stringlist(args) disabled, required, _ = extract_required_kwarg(kwargs, state.subproject) if disabled: return ModuleReturnValue(False, [False]) lang, compiler = self._compiler(state) parser = declaration_parsers.get(lang) if not parser: raise InterpreterException('no declaration parser for language %s' % lang) compiler_args = self._compile_args(compiler, state, kwargs) compiler_args += compiler.get_werror_args() pkg = args[0] decl = args[1] tree = parser.parse(decl) name = extract_declaration_name(tree) proto = rewrite_declaration(tree, name) check_prototype = not is_lone_identifier(tree) if check_prototype: checker = prototype_checkers.get(lang) if not checker: raise InterpreterException('no checker program for language %s' % lang) prog = checker(tree, pkg, name) ok = compiler.compiles(prog, state.environment, compiler_args, None) status = mlog.green('YES') if ok else mlog.red('NO') mlog.log('Checking that', mlog.bold(name, True), 'has prototype', mlog.bold(proto, True), ':', status) else: ok = compiler.has_header_symbol(pkg, name, '', state.environment, compiler_args, None) self._checklog('declaration for', name, ok) self._set_config_var(state, ok, name, kwargs) if not ok and required: raise InterpreterException('{} declaration {} required but not found.'.format(lang, name)) return ModuleReturnValue(ok, [ok])
def _generate_object(self, obj: Object) -> None: tags = [] tags += [{ ObjectType.ELEMENTARY: mlog.yellow('[elementary]'), ObjectType.BUILTIN: mlog.green('[builtin]'), ObjectType.MODULE: mlog.blue('[module]'), ObjectType.RETURNED: mlog.cyan('[returned]'), }[obj.obj_type]] if obj.is_container: tags += [mlog.red('[container]')] mlog.log() mlog.log('Object', mlog.bold(obj.name), *tags) with my_nested(): desc = obj.description if '\n' in desc: desc = desc[:desc.index('\n')] mlog.log('Description:', mlog.bold(desc)) mlog.log('Returned by:', mlog.bold(str([x.name for x in obj.returned_by]))) mlog.log('Methods:') with my_nested(): for m in obj.methods: self._generate_function(m)
def _generate_function(self, func: Function) -> None: mlog.log() mlog.log('Function', mlog.bold(func.name)) with my_nested(): desc = func.description if '\n' in desc: desc = desc[:desc.index('\n')] mlog.log('Description:', mlog.bold(desc)) mlog.log('Return type:', mlog.bold(self._types_to_string(func.returns))) mlog.log('Pos args: ', mlog.bold(str([x.name for x in func.posargs]))) mlog.log('Opt args: ', mlog.bold(str([x.name for x in func.optargs]))) mlog.log('Varargs: ', mlog.bold(func.varargs.name if func.varargs is not None else 'null')) mlog.log('Kwargs: ', mlog.bold(str(list(func.kwargs.keys()))))
def _load_object(self, obj_type: ObjectType, path: Path) -> Object: path_label = path.relative_to(self.yaml_dir).as_posix() mlog.log(f'Loading', mlog.bold(path_label)) raw = load(self.read_file(path), s_object, label=path_label).data def as_methods(mlist: T.List[Function]) -> T.List[Method]: res: T.List[Method] = [] for i in mlist: assert isinstance(i, Method) res += [i] return res methods = raw.pop('methods', []) obj = Object(methods=[], obj_type=obj_type, **raw) obj.methods = as_methods([self._process_function_base(x, obj) for x in methods]) return obj
def _configure_sitemap(self) -> None: ''' Replaces the `@REFMAN_PLACEHOLDER@` placeholder with the reference manual sitemap. The structure of the sitemap is derived from the file IDs. ''' raw = self.sitemap_in.read_text(encoding='utf-8') out = '' for l in raw.split('\n'): if '@REFMAN_PLACEHOLDER@' not in l: out += f'{l}\n' continue mlog.log('Generating', mlog.bold(self.sitemap_out.as_posix())) base_indent = l.replace('@REFMAN_PLACEHOLDER@', '') for k in sorted(self.generated_files.keys()): indent = base_indent + '\t' * k.count('.') out += f'{indent}{self.generated_files[k]}\n' self.sitemap_out.write_text(out, encoding='utf-8')
def bold(text): return mlog.bold(text).get_text(mlog.colorize_console)
def main(): print_system_info() parser = argparse.ArgumentParser() parser.add_argument('--cov', action='store_true') parser.add_argument('--backend', default=None, dest='backend', choices=backendlist) parser.add_argument('--cross', default=False, dest='cross', action='store_true') parser.add_argument('--failfast', action='store_true') parser.add_argument('--no-unittests', action='store_true', default=False) (options, _) = parser.parse_known_args() # Enable coverage early... enable_coverage = options.cov if enable_coverage: os.makedirs('.coverage', exist_ok=True) sys.argv.remove('--cov') import coverage coverage.process_startup() returncode = 0 cross = options.cross backend, _ = guess_backend(options.backend, shutil.which('msbuild')) no_unittests = options.no_unittests # Running on a developer machine? Be nice! if not mesonlib.is_windows() and not mesonlib.is_haiku( ) and 'CI' not in os.environ: os.nice(20) # Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) print(flush=True) # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() env['MESON_UNIT_TEST_BACKEND'] = backend.name with tempfile.TemporaryDirectory() as temp_dir: # Enable coverage on all subsequent processes. if enable_coverage: Path(temp_dir, 'usercustomize.py').open('w').write( 'import coverage\n' 'coverage.process_startup()\n') env['COVERAGE_PROCESS_START'] = '.coveragerc' if 'PYTHONPATH' in env: env['PYTHONPATH'] = os.pathsep.join( [temp_dir, env.get('PYTHONPATH')]) else: env['PYTHONPATH'] = temp_dir if not cross: cmd = mesonlib.python_command + [ 'run_meson_command_tests.py', '-v' ] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode if no_unittests: print('Skipping all unit tests.') returncode = 0 else: cmd = mesonlib.python_command + ['run_unittests.py', '-v'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode cmd = mesonlib.python_command + ['run_project_tests.py' ] + sys.argv[1:] returncode += subprocess.call(cmd, env=env) else: cross_test_args = mesonlib.python_command + ['run_cross_test.py'] print( mlog.bold('Running armhf cross tests.').get_text( mlog.colorize_console)) print(flush=True) cmd = cross_test_args + ['cross/ubuntu-armhf.txt'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode print( mlog.bold('Running mingw-w64 64-bit cross tests.').get_text( mlog.colorize_console)) print(flush=True) cmd = cross_test_args + ['cross/linux-mingw-w64-64bit.txt'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) return returncode
def main(): print_system_info() parser = argparse.ArgumentParser() parser.add_argument('--cov', action='store_true') parser.add_argument('--backend', default=None, dest='backend', choices=backendlist) parser.add_argument('--cross', default=False, dest='cross', action='store_true') parser.add_argument('--failfast', action='store_true') (options, _) = parser.parse_known_args() # Enable coverage early... enable_coverage = options.cov if enable_coverage: os.makedirs('.coverage', exist_ok=True) sys.argv.remove('--cov') import coverage coverage.process_startup() returncode = 0 cross = options.cross backend, _ = guess_backend(options.backend, shutil.which('msbuild')) # Running on a developer machine? Be nice! if not mesonlib.is_windows() and not mesonlib.is_haiku() and 'CI' not in os.environ: os.nice(20) # Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) print(flush=True) # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() env['MESON_UNIT_TEST_BACKEND'] = backend.name with tempfile.TemporaryDirectory() as temp_dir: # Enable coverage on all subsequent processes. if enable_coverage: Path(temp_dir, 'usercustomize.py').open('w').write( 'import coverage\n' 'coverage.process_startup()\n') env['COVERAGE_PROCESS_START'] = '.coveragerc' if 'PYTHONPATH' in env: env['PYTHONPATH'] = os.pathsep.join([temp_dir, env.get('PYTHONPATH')]) else: env['PYTHONPATH'] = temp_dir if not cross: cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode cmd = mesonlib.python_command + ['run_unittests.py', '-v'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:] returncode += subprocess.call(cmd, env=env) else: cross_test_args = mesonlib.python_command + ['run_cross_test.py'] print(mlog.bold('Running armhf cross tests.').get_text(mlog.colorize_console)) print(flush=True) cmd = cross_test_args + ['cross/ubuntu-armhf.txt'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode print(mlog.bold('Running mingw-w64 64-bit cross tests.') .get_text(mlog.colorize_console)) print(flush=True) cmd = cross_test_args + ['cross/linux-mingw-w64-64bit.txt'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) return returncode
# Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) print() # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() env['MESON_UNIT_TEST_BACKEND'] = backend.name with tempfile.TemporaryDirectory() as td: # Enable coverage on all subsequent processes. if enable_coverage: with open(os.path.join(td, 'usercustomize.py'), 'w') as f: f.write('import coverage\n' 'coverage.process_startup()\n') env['COVERAGE_PROCESS_START'] = '.coveragerc' env['PYTHONPATH'] = os.pathsep.join([td] + env.get('PYTHONPATH', [])) returncode += subprocess.call([sys.executable, 'run_unittests.py', '-v'], env=env) # Ubuntu packages do not have a binary without -6 suffix. if should_run_linux_cross_tests():
# Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) print() # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() env['MESON_UNIT_TEST_BACKEND'] = backend.name with tempfile.TemporaryDirectory() as td: # Enable coverage on all subsequent processes. if enable_coverage: with open(os.path.join(td, 'usercustomize.py'), 'w') as f: f.write('import coverage\n' 'coverage.process_startup()\n') env['COVERAGE_PROCESS_START'] = '.coveragerc' env['PYTHONPATH'] = os.pathsep.join([td] + env.get('PYTHONPATH', [])) if not cross: returncode += subprocess.call(mesonlib.python_command + ['run_meson_command_tests.py', '-v'],
def main() -> None: parser = argparse.ArgumentParser() parser.add_argument('case', type=pathlib.Path, help='The test case to run') parser.add_argument('--subtest', type=int, action='append', dest='subtests', help='which subtests to run') parser.add_argument('--backend', action='store', help="Which backend to use") parser.add_argument('--cross-file', action='store', help='File describing cross compilation environment.') parser.add_argument('--native-file', action='store', help='File describing native compilation environment.') parser.add_argument('--use-tmpdir', action='store_true', help='Use tmp directory for temporary files.') args = T.cast('ArgumentType', parser.parse_args()) setup_commands(args.backend) detect_system_compiler(args) print_tool_versions() test = TestDef(args.case, args.case.stem, []) tests = load_test_json(test, False) if args.subtests: tests = [t for i, t in enumerate(tests) if i in args.subtests] def should_fail(path: pathlib.Path) -> str: dir_ = path.parent.stem # FIXME: warning tets might not be handled correctly still… if dir_.startswith(('failing', 'warning')): if ' ' in dir_: return dir_.split(' ')[1] return 'meson' return '' results = [ run_test(t, t.args, should_fail(t.path), args.use_tmpdir) for t in tests ] failed = False for test, result in zip(tests, results): if result is None: is_skipped = True skip_reason = 'not run because preconditions were not met' else: for l in result.stdo.splitlines(): if test_emits_skip_msg(l): is_skipped = True offset = l.index('MESON_SKIP_TEST') + 16 skip_reason = l[offset:].strip() break else: is_skipped = False skip_reason = '' if is_skipped: msg = mlog.yellow('SKIP:') elif result.msg: msg = mlog.red('FAIL:') failed = True else: msg = mlog.green('PASS:'******'Reason:'), skip_reason) if result is not None and result.msg and 'MESON_SKIP_TEST' not in result.stdo: mlog.log('reason:', result.msg) if result.step is BuildStep.configure: # For configure failures, instead of printing stdout, # print the meson log if available since it's a superset # of stdout and often has very useful information. mlog.log(result.mlog) else: mlog.log(result.stdo) for cmd_res in result.cicmds: mlog.log(cmd_res) mlog.log(result.stde) exit(1 if failed else 0)
def main(): print_system_info() parser = argparse.ArgumentParser() parser.add_argument('--backend', default=None, dest='backend', choices=backendlist) parser.add_argument('--cross', default=[], dest='cross', action='append') parser.add_argument('--cross-only', action='store_true') parser.add_argument('--failfast', action='store_true') parser.add_argument('--no-unittests', action='store_true', default=False) (options, _) = parser.parse_known_args() returncode = 0 backend, _ = guess_backend(options.backend, shutil.which('msbuild')) no_unittests = options.no_unittests # Running on a developer machine? Be nice! if not mesonlib.is_windows() and not mesonlib.is_haiku( ) and 'CI' not in os.environ: os.nice(20) # Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() if not options.cross: cmd = mesonlib.python_command + ['run_meson_command_tests.py', '-v'] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode if no_unittests: print('Skipping all unit tests.') print(flush=True) returncode = 0 else: print(mlog.bold('Running unittests.')) print(flush=True) cmd = mesonlib.python_command + [ 'run_unittests.py', '--backend=' + backend.name, '-v' ] if options.failfast: cmd += ['--failfast'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode cmd = mesonlib.python_command + ['run_project_tests.py'] + sys.argv[1:] returncode += subprocess.call(cmd, env=env) else: cross_test_args = mesonlib.python_command + ['run_cross_test.py'] for cf in options.cross: print(mlog.bold(f'Running {cf} cross tests.')) print(flush=True) cmd = cross_test_args + ['cross/' + cf] if options.failfast: cmd += ['--failfast'] if options.cross_only: cmd += ['--cross-only'] returncode += subprocess.call(cmd, env=env) if options.failfast and returncode != 0: return returncode return returncode
# Appveyor sets the `platform` environment variable which completely messes # up building with the vs2010 and vs2015 backends. # # Specifically, MSBuild reads the `platform` environment variable to set # the configured value for the platform (Win32/x64/arm), which breaks x86 # builds. # # Appveyor setting this also breaks our 'native build arch' detection for # Windows in environment.py:detect_windows_arch() by overwriting the value # of `platform` set by vcvarsall.bat. # # While building for x86, `platform` should be unset. if 'APPVEYOR' in os.environ and os.environ['arch'] == 'x86': os.environ.pop('platform') # Run tests print(mlog.bold('Running unittests.').get_text(mlog.colorize_console)) print() # Can't pass arguments to unit tests, so set the backend to use in the environment env = os.environ.copy() env['MESON_UNIT_TEST_BACKEND'] = backend.name with tempfile.TemporaryDirectory() as td: # Enable coverage on all subsequent processes. if enable_coverage: with open(os.path.join(td, 'usercustomize.py'), 'w') as f: f.write('import coverage\n' 'coverage.process_startup()\n') env['COVERAGE_PROCESS_START'] = '.coveragerc' env['PYTHONPATH'] = os.pathsep.join([td] + env.get('PYTHONPATH', [])) if not cross: returncode += subprocess.call(mesonlib.python_command + ['run_meson_command_tests.py', '-v'], env=env) returncode += subprocess.call(mesonlib.python_command + ['run_unittests.py', '-v'], env=env)
def _checklog(self, which, what, ok): status = mlog.green('YES') if ok else mlog.red('NO') mlog.log('Checking that', which, mlog.bold(what, True), 'exists:', status)