diff options
30 files changed, 136 insertions, 120 deletions
diff --git a/docs/markdown/Compiler-properties.md b/docs/markdown/Compiler-properties.md index 4def628..579417a 100644 --- a/docs/markdown/Compiler-properties.md +++ b/docs/markdown/Compiler-properties.md @@ -173,7 +173,7 @@ Does a structure contain a member? == Some platforms have different standard structures. Here's how one -would check if a struct called `mystruct` from header `myheader.h</hh> +would check if a struct called `mystruct` from header `myheader.h` contains a member called `some_member`. ```meson diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index ee3b8c2..5ee0db1 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -57,7 +57,7 @@ These are provided by the `.system()` method call. | windows | Any version of Windows | | cygwin | The Cygwin environment for Windows | | haiku | | -| freebsd | FreeBSD and it's derivatives | +| freebsd | FreeBSD and its derivatives | | dragonfly | DragonFly BSD | | netbsd | | diff --git a/docs/markdown/Users.md b/docs/markdown/Users.md index 78ad1b7..0503c22 100644 --- a/docs/markdown/Users.md +++ b/docs/markdown/Users.md @@ -37,12 +37,14 @@ If you have a project that uses Meson that you want to add to this list, let us - [Mesa](https://www.mesa3d.org/), An open source graphics driver project - [Nautilus](https://git.gnome.org/browse/nautilus/commit/?id=ed5652c89ac0654df2e82b54b00b27d51c825465) the Gnome file manager - [Orc](http://cgit.freedesktop.org/gstreamer/orc/), the Optimized Inner Loop Runtime Compiler (not the default yet) + - [Outlier](https://github.com/kerolasa/outlier), a small Hello World style meson example project - [Pango](https://git.gnome.org/browse/pango/), an Internationalized text layout and rendering library (not the default yet) - [Parzip](https://github.com/jpakkane/parzip), a multithreaded reimplementation of Zip - [Pitivi](http://pitivi.org/), a nonlinear video editor - [Polari](https://git.gnome.org/browse/polari), an IRC client - [Sysprof](https://wiki.gnome.org/Apps/Sysprof), a profiling tool - [systemd](https://github.com/systemd/systemd), the init system + - [Taisei Project](https://taisei-project.org/), an open-source Touhou Project clone and fangame - [Xorg](https://cgit.freedesktop.org/xorg/xserver/) the X.org display server (not the default yet) - [Valum](https://github.com/valum-framework/valum), a micro web framework written in Vala - [Wayland and Weston](https://lists.freedesktop.org/archives/wayland-devel/2016-November/031984.html), a next generation display server (not merged yet) diff --git a/docs/markdown/snippets/config-tool-cross.md b/docs/markdown/snippets/config-tool-cross.md new file mode 100644 index 0000000..1102481 --- /dev/null +++ b/docs/markdown/snippets/config-tool-cross.md @@ -0,0 +1,13 @@ +# Config-Tool based dependencies can be specified in a cross file + +Tools like LLVM and pcap use a config tool for dependencies, this is a script +or binary that is run to get configuration information (cflags, ldflags, etc) +from. + +These binaries may now be specified in the `binaries` section of a cross file. + +```dosini +[binaries] +cc = ... +llvm-config = '/usr/bin/llvm-config32' +``` diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 5a5db22..292b027 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -322,7 +322,7 @@ class Backend: continue if os.path.splitext(libpath)[1] not in ['.dll', '.lib', '.so']: continue - absdir = os.path.split(libpath)[0] + absdir = os.path.dirname(libpath) rel_to_src = absdir[len(self.environment.get_source_dir()) + 1:] assert(not os.path.isabs(rel_to_src)) paths.append(os.path.join(self.build_to_src, rel_to_src)) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 77c7d50..9318926 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -823,7 +823,7 @@ int dummy; if subdir is None: subdir = os.path.join(manroot, 'man' + num) srcabs = f.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir()) - dstabs = os.path.join(subdir, os.path.split(f.fname)[1] + '.gz') + dstabs = os.path.join(subdir, os.path.basename(f.fname) + '.gz') i = [srcabs, dstabs] d.man.append(i) @@ -836,7 +836,7 @@ int dummy; subdir = de.install_dir for f in de.sources: assert(isinstance(f, mesonlib.File)) - plain_f = os.path.split(f.fname)[1] + plain_f = os.path.basename(f.fname) dstabs = os.path.join(subdir, plain_f) i = [f.absolute_path(srcdir, builddir), dstabs, de.install_mode] d.data.append(i) @@ -1278,7 +1278,7 @@ int dummy; # Target names really should not have slashes in them, but # unfortunately we did not check for that and some downstream projects # now have them. Once slashes are forbidden, remove this bit. - target_slashname_workaround_dir = os.path.join(os.path.split(target.name)[0], + target_slashname_workaround_dir = os.path.join(os.path.dirname(target.name), self.get_target_dir(target)) else: target_slashname_workaround_dir = self.get_target_dir(target) @@ -1401,7 +1401,7 @@ int dummy; objects = [] # Relative to swift invocation dir rel_objects = [] # Relative to build.ninja for i in abssrc + abs_generated: - base = os.path.split(i)[1] + base = os.path.basename(i) oname = os.path.splitext(base)[0] + '.o' objects.append(oname) rel_objects.append(os.path.join(self.get_target_private_dir(target), oname)) @@ -1928,7 +1928,7 @@ rule FORTRAN_DEP_HACK # Check if a source uses a module it exports itself. # Potential bug if multiple targets have a file with # the same name. - if mod_source_file.fname == os.path.split(src)[1]: + if mod_source_file.fname == os.path.basename(src): continue mod_name = compiler.module_name_to_filename( usematch.group(1)) @@ -2271,7 +2271,7 @@ rule FORTRAN_DEP_HACK commands = [] commands += self.generate_basic_compiler_args(target, compiler) - just_name = os.path.split(header)[1] + just_name = os.path.basename(header) (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args commands += self.get_compile_debugfile_args(compiler, target, objname) @@ -2281,7 +2281,7 @@ rule FORTRAN_DEP_HACK def generate_gcc_pch_command(self, target, compiler, pch): commands = self._generate_single_compile(target, compiler) dst = os.path.join(self.get_target_private_dir(target), - os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix()) + os.path.basename(pch) + '.' + compiler.get_pch_suffix()) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. @@ -2476,7 +2476,7 @@ rule FORTRAN_DEP_HACK # unfortunately we did not check for that and some downstream projects # now have them. Once slashes are forbidden, remove this bit. target_slashname_workaround_dir = os.path.join( - os.path.split(target.name)[0], + os.path.dirname(target.name), self.get_target_dir(target)) else: target_slashname_workaround_dir = self.get_target_dir(target) diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 1722db7..057e7c9 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1034,7 +1034,7 @@ class Vs2010Backend(backends.Backend): pch_file = ET.SubElement(inc_cl, 'PrecompiledHeaderFile') # MSBuild searches for the header relative from the implementation, so we have to use # just the file name instead of the relative path to the file. - pch_file.text = os.path.split(header)[1] + pch_file.text = os.path.basename(header) self.add_additional_options(lang, inc_cl, file_args) self.add_preprocessor_defines(lang, inc_cl, file_defines) self.add_include_dirs(lang, inc_cl, file_inc_dirs) diff --git a/mesonbuild/backend/xcodebackend.py b/mesonbuild/backend/xcodebackend.py index aca3aea..3ae31e4 100644 --- a/mesonbuild/backend/xcodebackend.py +++ b/mesonbuild/backend/xcodebackend.py @@ -311,7 +311,7 @@ class XCodeBackend(backends.Backend): for fname, idval in self.filemap.items(): fullpath = os.path.join(self.environment.get_source_dir(), fname) xcodetype = self.get_xcodetype(fname) - name = os.path.split(fname)[-1] + name = os.path.basename(fname) path = fname self.ofile.write(src_templ % (idval, fullpath, xcodetype, name, path)) target_templ = '%s /* %s */ = { isa = PBXFileReference; explicitFileType = "%s"; path = %s; refType = %d; sourceTree = BUILT_PRODUCTS_DIR; };\n' diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 5eab794..dc19b73 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1065,7 +1065,7 @@ class Generator: depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') - if os.path.split(depfile)[1] != depfile: + if os.path.basename(depfile) != depfile: raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile if 'capture' in kwargs: @@ -1075,7 +1075,7 @@ class Generator: self.capture = capture def get_base_outnames(self, inname): - plainname = os.path.split(inname)[1] + plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] bases = [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.outputs] return bases @@ -1083,12 +1083,12 @@ class Generator: def get_dep_outname(self, inname): if self.depfile is None: raise InvalidArguments('Tried to get dep name for rule that does not have dependency file defined.') - plainname = os.path.split(inname)[1] + plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return self.depfile.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) def get_arglist(self, inname): - plainname = os.path.split(inname)[1] + plainname = os.path.basename(inname) basename = os.path.splitext(plainname)[0] return [x.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) for x in self.arglist] @@ -1130,7 +1130,7 @@ class GeneratedList: in_abs = infile.absolute_path(state.environment.source_dir, state.environment.build_dir) assert(os.path.isabs(self.preserve_path_from)) rel = os.path.relpath(in_abs, self.preserve_path_from) - path_segment = os.path.split(rel)[0] + path_segment = os.path.dirname(rel) for of in outfiles: result.append(os.path.join(path_segment, of)) return result @@ -1637,6 +1637,10 @@ class CustomTarget(Target): for i in self.outputs: if not(isinstance(i, str)): raise InvalidArguments('Output argument not a string.') + if i == '': + raise InvalidArguments('Output must not be empty.') + if i.strip() == '': + raise InvalidArguments('Output must not consist only of whitespace.') if '/' in i: raise InvalidArguments('Output must not contain a path segment.') if '@INPUT@' in i or '@INPUT0@' in i: @@ -1659,7 +1663,7 @@ class CustomTarget(Target): depfile = kwargs['depfile'] if not isinstance(depfile, str): raise InvalidArguments('Depfile must be a string.') - if os.path.split(depfile)[1] != depfile: + if os.path.basename(depfile) != depfile: raise InvalidArguments('Depfile must be a plain filename without a subdirectory.') self.depfile = depfile self.command = self.flatten_command(kwargs['command']) diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index 4c6e3a2..f738615 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -172,10 +172,10 @@ class CCompiler(Compiler): return ' '.join(self.exelist) def get_pch_use_args(self, pch_dir, header): - return ['-include', os.path.split(header)[-1]] + return ['-include', os.path.basename(header)] def get_pch_name(self, header_name): - return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix() + return os.path.basename(header_name) + '.' + self.get_pch_suffix() def get_linker_search_args(self, dirname): return ['-L' + dirname] @@ -804,6 +804,13 @@ class CCompiler(Compiler): return ['-pthread'] def has_multi_arguments(self, args, env): + for arg in args: + if arg.startswith('-Wl,'): + mlog.warning('''{} looks like a linker argument, but has_argument +and other similar methods only support checking compiler arguments. +Using them to check linker arguments are never supported, and results +are likely to be wrong regardless of the compiler you are using. +'''.format(arg)) return self.compiles('int i;\n', env, extra_args=args) @@ -875,7 +882,7 @@ class GnuCCompiler(GnuCompiler, CCompiler): return ['-shared'] def get_pch_use_args(self, pch_dir, header): - return ['-fpch-preprocess', '-include', os.path.split(header)[-1]] + return ['-fpch-preprocess', '-include', os.path.basename(header)] class IntelCCompiler(IntelCompiler, CCompiler): @@ -954,13 +961,13 @@ class VisualStudioCCompiler(CCompiler): return 'pch' def get_pch_name(self, header): - chopped = os.path.split(header)[-1].split('.')[:-1] + chopped = os.path.basename(header).split('.')[:-1] chopped.append(self.get_pch_suffix()) pchname = '.'.join(chopped) return pchname def get_pch_use_args(self, pch_dir, header): - base = os.path.split(header)[-1] + base = os.path.basename(header) pchname = self.get_pch_name(header) return ['/FI' + base, '/Yu' + base, '/Fp' + os.path.join(pch_dir, pchname)] @@ -1087,7 +1094,7 @@ class VisualStudioCCompiler(CCompiler): mlog.debug('Running VS compile:') mlog.debug('Command line: ', ' '.join(commands)) mlog.debug('Code:\n', code) - p, stdo, stde = Popen_safe(commands, cwd=os.path.split(srcname)[0]) + p, stdo, stde = Popen_safe(commands, cwd=os.path.dirname(srcname)) if p.returncode != 0: return False return not(warning_text in stde or warning_text in stdo) diff --git a/mesonbuild/compilers/compilers.py b/mesonbuild/compilers/compilers.py index 2602d14..dbaf730 100644 --- a/mesonbuild/compilers/compilers.py +++ b/mesonbuild/compilers/compilers.py @@ -1040,7 +1040,7 @@ class GnuCompiler: return 'gch' def split_shlib_to_parts(self, fname): - return os.path.split(fname)[0], fname + return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) @@ -1188,10 +1188,10 @@ class IntelCompiler: self.lang_header, '-include', header, '-x', 'none'] def get_pch_name(self, header_name): - return os.path.split(header_name)[-1] + '.' + self.get_pch_suffix() + return os.path.basename(header_name) + '.' + self.get_pch_suffix() def split_shlib_to_parts(self, fname): - return os.path.split(fname)[0], fname + return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): if self.icc_type == ICC_STANDARD: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 5e32ace..c10f38e 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -14,6 +14,7 @@ import os.path +from .. import mlog from .. import coredata from ..mesonlib import version_compare @@ -129,7 +130,7 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): return [] def get_pch_use_args(self, pch_dir, header): - return ['-fpch-preprocess', '-include', os.path.split(header)[-1]] + return ['-fpch-preprocess', '-include', os.path.basename(header)] class IntelCPPCompiler(IntelCompiler, CPPCompiler): @@ -174,6 +175,13 @@ class IntelCPPCompiler(IntelCompiler, CPPCompiler): return [] def has_multi_arguments(self, args, env): + for arg in args: + if arg.startswith('-Wl,'): + mlog.warning('''{} looks like a linker argument, but has_argument +and other similar methods only support checking compiler arguments. +Using them to check linker arguments are never supported, and results +are likely to be wrong regardless of the compiler you are using. +'''.format(arg)) return super().has_multi_arguments(args + ['-diag-error', '10006'], env) diff --git a/mesonbuild/compilers/fortran.py b/mesonbuild/compilers/fortran.py index 1b42bfa..f9fcc1c 100644 --- a/mesonbuild/compilers/fortran.py +++ b/mesonbuild/compilers/fortran.py @@ -91,7 +91,7 @@ end program prog return gnulike_buildtype_linker_args[buildtype] def split_shlib_to_parts(self, fname): - return os.path.split(fname)[0], fname + return os.path.dirname(fname), fname def get_soname_args(self, prefix, shlib_name, suffix, path, soversion, is_shared_module): return get_gcc_soname_args(self.gcc_type, prefix, shlib_name, suffix, path, soversion, is_shared_module) diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 560e389..f89e631 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -212,6 +212,7 @@ class ConfigToolDependency(ExternalDependency): def __init__(self, name, environment, language, kwargs): super().__init__('config-tool', environment, language, kwargs) self.name = name + self.native = kwargs.get('native', False) self.tools = listify(kwargs.get('tools', self.tools)) req_version = kwargs.get('version', None) @@ -260,8 +261,20 @@ class ConfigToolDependency(ExternalDependency): if not isinstance(versions, list) and versions is not None: versions = listify(versions) + if self.env.is_cross_build() and not self.native: + cross_file = self.env.cross_info.config['binaries'] + try: + tools = [cross_file[self.tool_name]] + except KeyError: + mlog.warning('No entry for {0} specified in your cross file. ' + 'Falling back to searching PATH. This may find a ' + 'native version of {0}!'.format(self.tool_name)) + tools = self.tools + else: + tools = self.tools + best_match = (None, None) - for tool in self.tools: + for tool in tools: try: p, out = Popen_safe([tool, '--version'])[:2] except (FileNotFoundError, PermissionError): diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 53bba60..4737dd3 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -594,7 +594,7 @@ class Environment: return self.scratch_dir def get_depfixer(self): - path = os.path.split(__file__)[0] + path = os.path.dirname(__file__) return os.path.join(path, 'depfixer.py') def detect_objc_compiler(self, want_cross): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index b5ced9b..9c2fd00 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1583,7 +1583,7 @@ class Interpreter(InterpreterBase): modname = args[0] if modname.startswith('unstable-'): plainname = modname.split('-', 1)[1] - mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases' % modname, location=node) + mlog.warning('Module %s has no backwards or forwards compatibility and might not exist in future releases.' % modname, location=node) modname = 'unstable_' + plainname if modname not in self.environment.coredata.modules: try: @@ -2739,7 +2739,7 @@ root and issuing %s. values = mesonlib.get_filenames_templates_dict([ifile_abs], None) outputs = mesonlib.substitute_values([output], values) output = outputs[0] - if os.path.split(output)[0] != '': + if os.path.dirname(output) != '': raise InterpreterException('Output file name must not contain a subdirectory.') (ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output)) ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname) @@ -2756,7 +2756,7 @@ root and issuing %s. var_list = ", ".join(map(repr, sorted(missing_variables))) mlog.warning( "The variable(s) %s in the input file %s are not " - "present in the given configuration data" % ( + "present in the given configuration data." % ( var_list, inputfile), location=node) else: mesonlib.dump_conf_header(ofile_abs, conf.held_object) @@ -2977,7 +2977,7 @@ different subdirectory. norm = os.path.relpath(norm, self.environment.source_dir) assert(not os.path.isabs(norm)) (num_sps, sproj_name) = self.evaluate_subproject_info(norm, self.subproject_dir) - plain_filename = os.path.split(norm)[-1] + plain_filename = os.path.basename(norm) if num_sps == 0: if self.subproject == '': return @@ -3006,6 +3006,8 @@ different subdirectory. def add_target(self, name, tobj): if name == '': raise InterpreterException('Target name must not be empty.') + if name.strip() == '': + raise InterpreterException('Target name must not consist only of whitespace.') if name.startswith('meson-'): raise InvalidArguments("Target names starting with 'meson-' are reserved " "for Meson's internal use. Please rename.") diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index 9dc6b0f..35ca5c8 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -74,7 +74,7 @@ class permittedKwargs: loc = None for k in kwargs: if k not in self.permitted: - mlog.warning('''Passed invalid keyword argument "{}"'''.format(k), location=loc) + mlog.warning('''Passed invalid keyword argument "{}".'''.format(k), location=loc) mlog.warning('This will become a hard error in the future.') return f(s, node_or_state, args, kwargs) return wrapped diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 4871bf7..a90cb6e 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -576,7 +576,8 @@ def do_conf_file(src, dst, confdata): return missing_variables def dump_conf_header(ofilename, cdata): - with open(ofilename, 'w', encoding='utf-8') as ofile: + ofilename_tmp = ofilename + '~' + with open(ofilename_tmp, 'w', encoding='utf-8') as ofile: ofile.write('''/* * Autogenerated by the Meson build system. * Do not edit, your changes will be lost. @@ -598,6 +599,7 @@ def dump_conf_header(ofilename, cdata): ofile.write('#define %s %s\n\n' % (k, v)) else: raise MesonException('Unknown data type in configuration file entry: ' + k) + replace_if_different(ofilename, ofilename_tmp) def replace_if_different(dst, dst_tmp): # If contents are identical, don't touch the file to prevent @@ -855,7 +857,7 @@ def get_filenames_templates_dict(inputs, outputs): values['@INPUT{}@'.format(ii)] = vv if len(inputs) == 1: # Just one value, substitute @PLAINNAME@ and @BASENAME@ - values['@PLAINNAME@'] = plain = os.path.split(inputs[0])[1] + values['@PLAINNAME@'] = plain = os.path.basename(inputs[0]) values['@BASENAME@'] = os.path.splitext(plain)[0] if outputs: # Gather values derived from the outputs, similar to above. @@ -863,7 +865,7 @@ def get_filenames_templates_dict(inputs, outputs): for (ii, vv) in enumerate(outputs): values['@OUTPUT{}@'.format(ii)] = vv # Outdir should be the same for all outputs - values['@OUTDIR@'] = os.path.split(outputs[0])[0] + values['@OUTDIR@'] = os.path.dirname(outputs[0]) # Many external programs fail on empty arguments. if values['@OUTDIR@'] == '': values['@OUTDIR@'] = '.' @@ -893,7 +895,7 @@ def detect_subprojects(spdir_name, current_dir='', result=None): if not os.path.exists(spdir): return result for trial in glob(os.path.join(spdir, '*')): - basename = os.path.split(trial)[1] + basename = os.path.basename(trial) if trial == 'packagecache': continue append_this = True diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 11a631a..619aa39 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -366,10 +366,11 @@ def run(original_args, mainfile=None): app.generate() except Exception as e: if isinstance(e, MesonException): + mlog.log() if hasattr(e, 'file') and hasattr(e, 'lineno') and hasattr(e, 'colno'): - mlog.log(mlog.red('\nMeson encountered an error in file %s, line %d, column %d:' % (e.file, e.lineno, e.colno))) + mlog.log('%s:%d:%d:' % (e.file, e.lineno, e.colno), mlog.red('ERROR: '), end='') else: - mlog.log(mlog.red('\nMeson encountered an error:')) + mlog.log(mlog.red('ERROR: '), end='') # Error message mlog.log(e) # Path to log file diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py index b23869f..aaaf8fc 100644 --- a/mesonbuild/mintro.py +++ b/mesonbuild/mintro.py @@ -49,14 +49,14 @@ parser.add_argument('builddir', nargs='?', help='The build directory') def determine_installed_path(target, installdata): install_target = None for i in installdata.targets: - if os.path.split(i[0])[1] == target.get_filename(): # FIXME, might clash due to subprojects. + if os.path.basename(i[0]) == target.get_filename(): # FIXME, might clash due to subprojects. install_target = i break if install_target is None: raise RuntimeError('Something weird happened. File a bug.') fname = i[0] outdir = i[1] - outname = os.path.join(installdata.prefix, outdir, os.path.split(fname)[-1]) + outname = os.path.join(installdata.prefix, outdir, os.path.basename(fname)) # Normalize the path by using os.path.sep consistently, etc. # Does not change the effective path. return str(pathlib.PurePath(outname)) diff --git a/mesonbuild/mlog.py b/mesonbuild/mlog.py index aa2ac20..273552d 100644 --- a/mesonbuild/mlog.py +++ b/mesonbuild/mlog.py @@ -105,12 +105,15 @@ def log(*args, **kwargs): def warning(*args, **kwargs): from . import environment + args = (yellow('WARNING:'),) + args + if kwargs.get('location'): location = kwargs['location'] del kwargs['location'] - args += ('in file {}, line {}.'.format(os.path.join(location.subdir, environment.build_filename), location.lineno),) + location = '{}:{}:'.format(os.path.join(location.subdir, environment.build_filename), location.lineno) + args = (location,) + args - log(yellow('WARNING:'), *args, **kwargs) + log(*args, **kwargs) # Format a list for logging purposes as a string. It separates # all but the last item with commas, and the last with 'and'. diff --git a/mesonbuild/modules/qt.py b/mesonbuild/modules/qt.py index 595269e..f5ce1ed 100644 --- a/mesonbuild/modules/qt.py +++ b/mesonbuild/modules/qt.py @@ -73,7 +73,7 @@ class QtBaseModule: def parse_qrc(self, state, fname): abspath = os.path.join(state.environment.source_dir, state.subdir, fname) - relative_part = os.path.split(fname)[0] + relative_part = os.path.dirname(fname) try: tree = ET.parse(abspath) root = tree.getroot() @@ -116,7 +116,7 @@ class QtBaseModule: sources.append(res_target) else: for rcc_file in rcc_files: - basename = os.path.split(rcc_file)[1] + basename = os.path.basename(rcc_file) name = 'qt' + str(self.qt_version) + '-' + basename.replace('.', '_') rcc_kwargs = {'input': rcc_file, 'output': name + '.cpp', diff --git a/mesonbuild/mparser.py b/mesonbuild/mparser.py index eb03393..5df056f 100644 --- a/mesonbuild/mparser.py +++ b/mesonbuild/mparser.py @@ -368,7 +368,7 @@ class ArgumentNode: def set_kwarg(self, name, value): if name in self.kwargs: - mlog.warning('Keyword argument "{}" defined multiple times'.format(name), location=self) + mlog.warning('Keyword argument "{}" defined multiple times.'.format(name), location=self) mlog.warning('This will be an error in future Meson releases.') self.kwargs[name] = value diff --git a/mesonbuild/mtest.py b/mesonbuild/mtest.py index b39f5af..2032e05 100644 --- a/mesonbuild/mtest.py +++ b/mesonbuild/mtest.py @@ -438,7 +438,7 @@ TIMEOUT: %4d logfile_base = os.path.join(self.options.wd, 'meson-logs', self.options.logbase) if self.options.wrapper: - namebase = os.path.split(self.get_wrapper()[0])[1] + namebase = os.path.basename(self.get_wrapper()[0]) elif self.options.setup: namebase = self.options.setup diff --git a/mesonbuild/scripts/coverage.py b/mesonbuild/scripts/coverage.py index 25451d4..d1fad11 100644 --- a/mesonbuild/scripts/coverage.py +++ b/mesonbuild/scripts/coverage.py @@ -14,7 +14,7 @@ from mesonbuild import environment -import sys, os, subprocess +import sys, os, subprocess, pathlib def remove_dir_from_trace(lcov_command, covfile, dirname): tmpfile = covfile + '.tmp' @@ -68,6 +68,15 @@ def coverage(source_root, build_root, log_dir): '--show-details', '--branch-coverage', covinfo]) + if gcovr_exe: + print('') + print('XML coverage report can be found at', + pathlib.Path(log_dir, 'coverage.xml').as_uri()) + print('Text coverage report can be found at', + pathlib.Path(log_dir, 'coverage.txt').as_uri()) + if lcov_exe and genhtml_exe: + print('Html coverage report can be found at', + pathlib.Path(htmloutdir, 'index.html').as_uri()) return 0 def run(args): diff --git a/mesonbuild/scripts/gettext.py b/mesonbuild/scripts/gettext.py index 30ac54c..f308c5a 100644 --- a/mesonbuild/scripts/gettext.py +++ b/mesonbuild/scripts/gettext.py @@ -81,7 +81,7 @@ def do_install(src_sub, bld_sub, dest, pkgname, langs): srcfile = os.path.join(bld_sub, l + '.gmo') outfile = os.path.join(dest, l, 'LC_MESSAGES', pkgname + '.mo') - os.makedirs(os.path.split(outfile)[0], exist_ok=True) + os.makedirs(os.path.dirname(outfile), exist_ok=True) shutil.copyfile(srcfile, outfile) shutil.copystat(srcfile, outfile) print('Installing %s to %s' % (srcfile, outfile)) diff --git a/mesonbuild/scripts/meson_install.py b/mesonbuild/scripts/meson_install.py index fe1de1f..2f9f135 100644 --- a/mesonbuild/scripts/meson_install.py +++ b/mesonbuild/scripts/meson_install.py @@ -164,10 +164,10 @@ def do_copydir(data, src_prefix, src_dir, dst_dir, exclude): print('Tried to copy file %s but a directory of that name already exists.' % abs_dst) if os.path.exists(abs_dst): os.unlink(abs_dst) - parent_dir = os.path.split(abs_dst)[0] + parent_dir = os.path.dirname(abs_dst) if not os.path.isdir(parent_dir): os.mkdir(parent_dir) - shutil.copystat(os.path.split(abs_src)[0], parent_dir) + shutil.copystat(os.path.dirname(abs_src), parent_dir) shutil.copy2(abs_src, abs_dst, follow_symlinks=False) append_to_log(abs_dst) @@ -211,7 +211,7 @@ def install_data(d): fullfilename = i[0] outfilename = get_destdir_path(d, i[1]) mode = i[2] - outdir = os.path.split(outfilename)[0] + outdir = os.path.dirname(outfilename) d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (fullfilename, outdir)) do_copyfile(fullfilename, outfilename) @@ -221,7 +221,7 @@ def install_man(d): for m in d.man: full_source_filename = m[0] outfilename = get_destdir_path(d, m[1]) - outdir = os.path.split(outfilename)[0] + outdir = os.path.dirname(outfilename) d.dirmaker.makedirs(outdir, exist_ok=True) print('Installing %s to %s' % (full_source_filename, outdir)) if outfilename.endswith('.gz') and not full_source_filename.endswith('.gz'): @@ -238,7 +238,7 @@ def install_man(d): def install_headers(d): for t in d.headers: fullfilename = t[0] - fname = os.path.split(fullfilename)[1] + fname = os.path.basename(fullfilename) outdir = get_destdir_path(d, t[1]) outfilename = os.path.join(outdir, fname) print('Installing %s to %s' % (fname, outdir)) @@ -304,7 +304,7 @@ def install_targets(d): for t in d.targets: fname = check_for_stampfile(t[0]) outdir = get_destdir_path(d, t[1]) - outname = os.path.join(outdir, os.path.split(fname)[-1]) + outname = os.path.join(outdir, os.path.basename(fname)) aliases = t[2] should_strip = t[3] install_rpath = t[4] @@ -316,7 +316,7 @@ def install_targets(d): do_copyfile(fname, outname) if should_strip and d.strip_bin is not None: if fname.endswith('.jar'): - print('Not stripping jar target:', os.path.split(fname)[1]) + print('Not stripping jar target:', os.path.basename(fname)) continue print('Stripping target {!r}'.format(fname)) ps, stdo, stde = Popen_safe(d.strip_bin + [outname]) @@ -366,7 +366,7 @@ def run(args): print('Installer script for Meson. Do not run on your own, mmm\'kay?') print('meson_install.py [install info file]') datafilename = args[0] - private_dir = os.path.split(datafilename)[0] + private_dir = os.path.dirname(datafilename) log_dir = os.path.join(private_dir, '../meson-logs') with open(os.path.join(log_dir, 'install-log.txt'), 'w') as lf: install_log_file = lf diff --git a/mesonbuild/wrap/wraptool.py b/mesonbuild/wrap/wraptool.py index 0bdc417..09a0289 100644 --- a/mesonbuild/wrap/wraptool.py +++ b/mesonbuild/wrap/wraptool.py @@ -150,7 +150,7 @@ def do_promotion(from_path, spdir_name): assert(from_path.endswith('.wrap')) shutil.copy(from_path, spdir_name) elif os.path.isdir(from_path): - sproj_name = os.path.split(from_path)[1] + sproj_name = os.path.basename(from_path) outputdir = os.path.join(spdir_name, sproj_name) if os.path.exists(outputdir): sys.exit('Output dir %s already exists. Will not overwrite.' % outputdir) @@ -178,7 +178,7 @@ def promote(argument): def status(): print('Subproject status') for w in glob('subprojects/*.wrap'): - name = os.path.split(w)[1][:-5] + name = os.path.basename(w)[:-5] try: (latest_branch, latest_revision) = get_latest_version(name) except Exception: diff --git a/run_project_tests.py b/run_project_tests.py index d191e28..1d17000 100755 --- a/run_project_tests.py +++ b/run_project_tests.py @@ -31,7 +31,7 @@ import argparse import xml.etree.ElementTree as ET import time import multiprocessing -import concurrent.futures as conc +from concurrent.futures import ProcessPoolExecutor import re from run_unittests import get_fake_options, run_configure @@ -59,50 +59,6 @@ class TestResult: self.buildtime = buildtime self.testtime = testtime -class DummyFuture(conc.Future): - ''' - Dummy Future implementation that executes the provided function when you - ask for the result. Used on platforms where sem_open() is not available: - MSYS2, OpenBSD, etc: https://bugs.python.org/issue3770 - ''' - def set_function(self, fn, *args, **kwargs): - self.fn = fn - self.fn_args = args - self.fn_kwargs = kwargs - - def result(self, **kwargs): - try: - result = self.fn(*self.fn_args, **self.fn_kwargs) - except BaseException as e: - self.set_exception(e) - else: - self.set_result(result) - return super().result(**kwargs) - - -class DummyExecutor(conc.Executor): - ''' - Dummy single-thread 'concurrent' executor for use on platforms where - sem_open is not available: https://bugs.python.org/issue3770 - ''' - - def __init__(self): - from threading import Lock - self._shutdown = False - self._shutdownLock = Lock() - - def submit(self, fn, *args, **kwargs): - with self._shutdownLock: - if self._shutdown: - raise RuntimeError('Cannot schedule new futures after shutdown') - f = DummyFuture() - f.set_function(fn, *args, **kwargs) - return f - - def shutdown(self, wait=True): - with self._shutdownLock: - self._shutdown = True - class AutoDeletedDir: def __init__(self, d): @@ -548,11 +504,7 @@ def _run_tests(all_tests, log_name_base, extra_args): # Remove this once the following issue has been resolved: # https://github.com/mesonbuild/meson/pull/2082 num_workers *= 2 - try: - executor = conc.ProcessPoolExecutor(max_workers=num_workers) - except ImportError: - print('Platform doesn\'t ProcessPoolExecutor, falling back to single-threaded testing\n') - executor = DummyExecutor() + executor = ProcessPoolExecutor(max_workers=num_workers) for name, test_cases, skipped in all_tests: current_suite = ET.SubElement(junit_root, 'testsuite', {'name': name, 'tests': str(len(test_cases))}) diff --git a/run_unittests.py b/run_unittests.py index 7abbe6c..103847a 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -1713,13 +1713,13 @@ int main(int argc, char **argv) { tdir = os.path.join(self.unit_test_dir, '21 warning location') out = self.init(tdir) for expected in [ - r'WARNING: Keyword argument "link_with" defined multiple times in file meson.build, line 4', - r'WARNING: Keyword argument "link_with" defined multiple times in file sub' + os.path.sep + r'meson.build, line 3', - r'WARNING: a warning of some sort in file meson.build, line 6', - r'WARNING: subdir warning in file sub' + os.path.sep + r'meson.build, line 4', - r'WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases in file meson.build, line 7', - r"WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data in file meson.build, line 10", - r'WARNING: Passed invalid keyword argument "invalid" in file meson.build, line 1' + r'meson.build:4: WARNING: Keyword argument "link_with" defined multiple times.', + r'sub' + os.path.sep + r'meson.build:3: WARNING: Keyword argument "link_with" defined multiple times.', + r'meson.build:6: WARNING: a warning of some sort', + r'sub' + os.path.sep + r'meson.build:4: WARNING: subdir warning', + r'meson.build:7: WARNING: Module unstable-simd has no backwards or forwards compatibility and might not exist in future releases.', + r"meson.build:10: WARNING: The variable(s) 'MISSING' in the input file conf.in are not present in the given configuration data.", + r'meson.build:1: WARNING: Passed invalid keyword argument "invalid".', ]: self.assertRegex(out, re.escape(expected)) |