diff options
-rw-r--r-- | docs/markdown/Adding-new-projects-to-wrapdb.md | 11 | ||||
-rw-r--r-- | docs/markdown/Reference-manual.md | 3 | ||||
-rw-r--r-- | docs/markdown/SimpleStart.md | 4 | ||||
-rw-r--r-- | docs/markdown/snippets/error_msg.md | 4 | ||||
-rw-r--r-- | docs/markdown/snippets/permit_generator_customtarget.md | 4 | ||||
-rw-r--r-- | mesonbuild/backend/vs2010backend.py | 26 | ||||
-rw-r--r-- | mesonbuild/build.py | 34 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 149 | ||||
-rw-r--r-- | mesonbuild/interpreterbase.py | 6 | ||||
-rw-r--r-- | mesonbuild/mcompile.py | 19 | ||||
-rwxr-xr-x | run_unittests.py | 5 | ||||
-rwxr-xr-x | test cases/common/106 generatorcustom/gen-resx.py | 9 | ||||
-rw-r--r-- | test cases/common/106 generatorcustom/main.c | 5 | ||||
-rw-r--r-- | test cases/common/106 generatorcustom/meson.build | 12 |
14 files changed, 173 insertions, 118 deletions
diff --git a/docs/markdown/Adding-new-projects-to-wrapdb.md b/docs/markdown/Adding-new-projects-to-wrapdb.md index 5bdadfa..a1d2486 100644 --- a/docs/markdown/Adding-new-projects-to-wrapdb.md +++ b/docs/markdown/Adding-new-projects-to-wrapdb.md @@ -62,7 +62,12 @@ provided. ### Request a new repository -Create an issue on the [wrapdb bug +*Note:* you should only do this if you have written the build files +and want to contribute them for inclusion to WrapDB. The maintainers +have only limited reesources and unfortunately can not take requests +to write Meson build definitions for arbitrary projects. + +The submission starts by creating an issue on the [wrapdb bug tracker](https://github.com/mesonbuild/wrapdb/issues) using *Title* and *Description* below as a template. @@ -75,7 +80,9 @@ version: <version_you_have_a_wrap_for> ``` Wait until the new repository or branch is created. A link to the new -repository or branch will be posted in a comment to this issue. +repository or branch will be posted in a comment to this issue. After +this you can createa a merge request in that repository for your build +files. NOTE: Requesting a branch is not necessary. WrapDB maintainer can create the branch and modify the PR accordingly if the project diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 3693e57..4fb0b63 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -580,6 +580,9 @@ Returns a [disabler object](#disabler-object). Print the argument string and halts the build process. +*(since 0.58.0)* Can take more than one argument that will be separated by +space. + ### environment() ``` meson diff --git a/docs/markdown/SimpleStart.md b/docs/markdown/SimpleStart.md index bda532a..2c18dc4 100644 --- a/docs/markdown/SimpleStart.md +++ b/docs/markdown/SimpleStart.md @@ -161,4 +161,6 @@ is put in the `build` subdirectory and can be run directly from there. The project is now ready for development. You can edit the code with any editor and it is rebuilt by going in the `build` subdirectory and -executing the `meson compile` command. +executing the `meson compile` command. If your version of Meson is too +old, you can compile the project by running the command `ninja` +instead. diff --git a/docs/markdown/snippets/error_msg.md b/docs/markdown/snippets/error_msg.md new file mode 100644 index 0000000..a17372f --- /dev/null +++ b/docs/markdown/snippets/error_msg.md @@ -0,0 +1,4 @@ +## `error()` with multiple arguments + +Just like `warning()` and `message()`, `error()` can now take more than one +argument that will be separated by space. diff --git a/docs/markdown/snippets/permit_generator_customtarget.md b/docs/markdown/snippets/permit_generator_customtarget.md new file mode 100644 index 0000000..0a5a6b5 --- /dev/null +++ b/docs/markdown/snippets/permit_generator_customtarget.md @@ -0,0 +1,4 @@ +## Allow using generator with CustomTaget or Index of CustomTarget. + +Calling `generator.process()` with either a CustomTaget or Index of CustomTarget +as files is now permitted. diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 7bbd2b6..82891cd 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -272,17 +272,25 @@ class Vs2010Backend(backends.Backend): all_deps[ldep.get_id()] = ldep for obj_id, objdep in self.get_obj_target_deps(target.objects): all_deps[obj_id] = objdep - for gendep in target.get_generated_sources(): - if isinstance(gendep, build.CustomTarget): - all_deps[gendep.get_id()] = gendep - elif isinstance(gendep, build.CustomTargetIndex): - all_deps[gendep.target.get_id()] = gendep.target - else: - gen_exe = gendep.generator.get_exe() - if isinstance(gen_exe, build.Executable): - all_deps[gen_exe.get_id()] = gen_exe else: raise MesonException('Unknown target type for target %s' % target) + + for gendep in target.get_generated_sources(): + if isinstance(gendep, build.CustomTarget): + all_deps[gendep.get_id()] = gendep + elif isinstance(gendep, build.CustomTargetIndex): + all_deps[gendep.target.get_id()] = gendep.target + else: + generator = gendep.get_generator() + gen_exe = generator.get_exe() + if isinstance(gen_exe, build.Executable): + all_deps[gen_exe.get_id()] = gen_exe + for d in generator.depends: + if isinstance(d, build.CustomTargetIndex): + all_deps[d.get_id()] = d.target + else: + all_deps[d.get_id()] = d + if not t or not recursive: return all_deps ret = self.get_target_deps(all_deps, recursive) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index de8d94b..b6ded5e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1571,17 +1571,31 @@ class Generator: return relpath.parts[0] != '..' # For subdirs we can only go "down". def process_files(self, name, files, state, preserve_path_from=None, extra_args=None): + new = False output = GeneratedList(self, state.subdir, preserve_path_from, extra_args=extra_args if extra_args is not None else []) - for f in files: - if isinstance(f, str): - f = File.from_source_file(state.environment.source_dir, state.subdir, f) - elif not isinstance(f, File): - raise InvalidArguments('{} arguments must be strings or files not {!r}.'.format(name, f)) - if preserve_path_from: - abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) - if not self.is_parent_path(preserve_path_from, abs_f): - raise InvalidArguments('When using preserve_path_from, all input files must be in a subdirectory of the given dir.') - output.add_file(f, state) + for e in unholder(files): + fs = [e] + if isinstance(e, (CustomTarget, CustomTargetIndex, GeneratedList)): + self.depends.append(e) + fs = [] + for f in e.get_outputs(): + fs.append(File.from_built_file(state.subdir, f)) + new = True + elif isinstance(e, str): + fs = [File.from_source_file(state.environment.source_dir, state.subdir, e)] + elif not isinstance(e, File): + raise InvalidArguments('{} arguments must be strings, files or CustomTargets, not {!r}.'.format(name, e)) + + for f in fs: + if preserve_path_from: + abs_f = f.absolute_path(state.environment.source_dir, state.environment.build_dir) + if not self.is_parent_path(preserve_path_from, abs_f): + raise InvalidArguments('generator.process: When using preserve_path_from, all input files must be in a subdirectory of the given dir.') + output.add_file(f, state) + if new: + FeatureNew.single_use( + 'Calling "{}" with CustomTaget or Index of CustomTarget.'.format(name), + '0.57.0', state.subproject) return output diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 08c7424..e99500d 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -61,28 +61,29 @@ permitted_method_kwargs = { 'sources'}, } -def stringifyUserArguments(args): +def stringifyUserArguments(args, quote=False): if isinstance(args, list): - return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args]) + return '[%s]' % ', '.join([stringifyUserArguments(x, True) for x in args]) elif isinstance(args, dict): - return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k), stringifyUserArguments(v)) for k, v in args.items()]) + return '{%s}' % ', '.join(['%s : %s' % (stringifyUserArguments(k, True), stringifyUserArguments(v, True)) for k, v in args.items()]) elif isinstance(args, int): return str(args) elif isinstance(args, str): - return "'%s'" % args - raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.') + return f"'{args}'" if quote else args + raise InvalidArguments('Function accepts only strings, integers, lists, dictionaries and lists thereof.') class OverrideProgram(dependencies.ExternalProgram): pass -class FeatureOptionHolder(InterpreterObject, ObjectHolder): - def __init__(self, env: 'Environment', name, option): +class FeatureOptionHolder(InterpreterObject, ObjectHolder[coredata.UserFeatureOption]): + def __init__(self, env: 'Environment', name: str, option: coredata.UserFeatureOption): InterpreterObject.__init__(self) ObjectHolder.__init__(self, option) if option.is_auto(): - self.held_object = env.coredata.options[OptionKey('auto_features')] + # TODO: we need to case here because options is not a TypedDict + self.held_object = T.cast(coredata.UserFeatureOption, env.coredata.options[OptionKey('auto_features')]) self.name = name self.methods.update({'enabled': self.enabled_method, 'disabled': self.disabled_method, @@ -236,7 +237,7 @@ class RunProcess(InterpreterObject): def stderr_method(self, args, kwargs): return self.stderr -class ConfigureFileHolder(InterpreterObject, ObjectHolder): +class ConfigureFileHolder(InterpreterObject, ObjectHolder[build.ConfigureFile]): def __init__(self, subdir, sourcename, targetname, configuration_data): InterpreterObject.__init__(self) @@ -244,7 +245,7 @@ class ConfigureFileHolder(InterpreterObject, ObjectHolder): ObjectHolder.__init__(self, obj) -class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder): +class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder[build.EnvironmentVariables]): def __init__(self, initial_values=None): MutableInterpreterObject.__init__(self) ObjectHolder.__init__(self, build.EnvironmentVariables()) @@ -304,7 +305,7 @@ class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder): self.add_var(self.held_object.prepend, args, kwargs) -class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder): +class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder[build.ConfigurationData]): def __init__(self, pv, initial_values=None): MutableInterpreterObject.__init__(self) self.used = False # These objects become immutable after use in configure_file. @@ -429,8 +430,8 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder): # Interpreter objects can not be pickled so we must have # these wrappers. -class DependencyHolder(InterpreterObject, ObjectHolder): - def __init__(self, dep, pv): +class DependencyHolder(InterpreterObject, ObjectHolder[Dependency]): + def __init__(self, dep: Dependency, pv: str): InterpreterObject.__init__(self) ObjectHolder.__init__(self, dep, pv) self.methods.update({'found': self.found_method, @@ -537,8 +538,8 @@ class DependencyHolder(InterpreterObject, ObjectHolder): new_dep = self.held_object.generate_link_whole_dependency() return DependencyHolder(new_dep, self.subproject) -class ExternalProgramHolder(InterpreterObject, ObjectHolder): - def __init__(self, ep, subproject, backend=None): +class ExternalProgramHolder(InterpreterObject, ObjectHolder[ExternalProgram]): + def __init__(self, ep: ExternalProgram, subproject: str, backend=None): InterpreterObject.__init__(self) ObjectHolder.__init__(self, ep) self.subproject = subproject @@ -604,8 +605,8 @@ class ExternalProgramHolder(InterpreterObject, ObjectHolder): self.cached_version = match.group(1) return self.cached_version -class ExternalLibraryHolder(InterpreterObject, ObjectHolder): - def __init__(self, el, pv): +class ExternalLibraryHolder(InterpreterObject, ObjectHolder[dependencies.ExternalLibrary]): + def __init__(self, el: dependencies.ExternalLibrary, pv: str): InterpreterObject.__init__(self) ObjectHolder.__init__(self, el, pv) self.methods.update({'found': self.found_method, @@ -645,7 +646,7 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder): pdep = self.held_object.get_partial_dependency(**kwargs) return DependencyHolder(pdep, self.subproject) -class GeneratorHolder(InterpreterObject, ObjectHolder): +class GeneratorHolder(InterpreterObject, ObjectHolder[build.Generator]): @FeatureNewKwargs('generator', '0.43.0', ['capture']) def __init__(self, interp, args, kwargs): self.interpreter = interp @@ -672,7 +673,7 @@ class GeneratorHolder(InterpreterObject, ObjectHolder): return GeneratedListHolder(gl) -class GeneratedListHolder(InterpreterObject, ObjectHolder): +class GeneratedListHolder(InterpreterObject, ObjectHolder[build.GeneratedList]): def __init__(self, arg1, extra_args=None): InterpreterObject.__init__(self) if isinstance(arg1, GeneratorHolder): @@ -688,8 +689,8 @@ class GeneratedListHolder(InterpreterObject, ObjectHolder): self.held_object.add_file(a) # A machine that's statically known from the cross file -class MachineHolder(InterpreterObject, ObjectHolder): - def __init__(self, machine_info): +class MachineHolder(InterpreterObject, ObjectHolder['MachineInfo']): + def __init__(self, machine_info: 'MachineInfo'): InterpreterObject.__init__(self) ObjectHolder.__init__(self, machine_info) self.methods.update({'system': self.system_method, @@ -718,12 +719,12 @@ class MachineHolder(InterpreterObject, ObjectHolder): def endian_method(self, args: T.List[TYPE_var], kwargs: TYPE_nkwargs) -> str: return self.held_object.endian -class IncludeDirsHolder(InterpreterObject, ObjectHolder): - def __init__(self, idobj): +class IncludeDirsHolder(InterpreterObject, ObjectHolder[build.IncludeDirs]): + def __init__(self, idobj: build.IncludeDirs): InterpreterObject.__init__(self) ObjectHolder.__init__(self, idobj) -class HeadersHolder(InterpreterObject, ObjectHolder): +class HeadersHolder(InterpreterObject, ObjectHolder[build.Headers]): def __init__(self, obj: build.Headers): InterpreterObject.__init__(self) @@ -744,8 +745,8 @@ class HeadersHolder(InterpreterObject, ObjectHolder): def get_custom_install_mode(self): return self.held_object.custom_install_mode -class DataHolder(InterpreterObject, ObjectHolder): - def __init__(self, data): +class DataHolder(InterpreterObject, ObjectHolder[build.Data]): + def __init__(self, data: build.Data): InterpreterObject.__init__(self) ObjectHolder.__init__(self, data) @@ -758,13 +759,13 @@ class DataHolder(InterpreterObject, ObjectHolder): def get_install_dir(self): return self.held_object.install_dir -class InstallDirHolder(InterpreterObject, ObjectHolder): +class InstallDirHolder(InterpreterObject, ObjectHolder[build.IncludeDirs]): def __init__(self, obj: build.InstallDir): InterpreterObject.__init__(self) ObjectHolder.__init__(self, obj) -class ManHolder(InterpreterObject, ObjectHolder): +class ManHolder(InterpreterObject, ObjectHolder[build.Man]): def __init__(self, obj: build.Man): InterpreterObject.__init__(self) @@ -779,19 +780,26 @@ class ManHolder(InterpreterObject, ObjectHolder): def get_sources(self) -> T.List[mesonlib.File]: return self.held_object.sources -class GeneratedObjectsHolder(InterpreterObject, ObjectHolder): - def __init__(self, held_object): +class GeneratedObjectsHolder(InterpreterObject, ObjectHolder[build.ExtractedObjects]): + def __init__(self, held_object: build.ExtractedObjects): InterpreterObject.__init__(self) ObjectHolder.__init__(self, held_object) -class TargetHolder(InterpreterObject, ObjectHolder): - def __init__(self, target, interp): + +_Target = T.TypeVar('_Target', bound=build.Target) + + +class TargetHolder(InterpreterObject, ObjectHolder[_Target]): + def __init__(self, target: _Target, interp: 'Interpreter'): InterpreterObject.__init__(self) ObjectHolder.__init__(self, target, interp.subproject) self.interpreter = interp -class BuildTargetHolder(TargetHolder): - def __init__(self, target, interp): + +_BuildTarget = T.TypeVar('_BuildTarget', bound=build.BuildTarget) + +class BuildTargetHolder(TargetHolder[_BuildTarget]): + def __init__(self, target: _BuildTarget, interp: 'Interpreter'): super().__init__(target, interp) self.methods.update({'extract_objects': self.extract_objects_method, 'extract_all_objects': self.extract_all_objects_method, @@ -856,16 +864,14 @@ class BuildTargetHolder(TargetHolder): def name_method(self, args, kwargs): return self.held_object.name -class ExecutableHolder(BuildTargetHolder): - def __init__(self, target: build.Executable, interp: 'Interpreter'): - super().__init__(target, interp) +class ExecutableHolder(BuildTargetHolder[build.Executable]): + pass -class StaticLibraryHolder(BuildTargetHolder): - def __init__(self, target, interp): - super().__init__(target, interp) +class StaticLibraryHolder(BuildTargetHolder[build.StaticLibrary]): + pass -class SharedLibraryHolder(BuildTargetHolder): - def __init__(self, target, interp): +class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]): + def __init__(self, target: build.SharedLibrary, interp: 'Interpreter'): super().__init__(target, interp) # Set to True only when called from self.func_shared_lib(). target.shared_library_only = False @@ -897,16 +903,14 @@ class BothLibrariesHolder(BuildTargetHolder): def get_static_lib_method(self, args, kwargs): return self.static_holder -class SharedModuleHolder(BuildTargetHolder): - def __init__(self, target, interp): - super().__init__(target, interp) +class SharedModuleHolder(BuildTargetHolder[build.SharedModule]): + pass -class JarHolder(BuildTargetHolder): - def __init__(self, target, interp): - super().__init__(target, interp) +class JarHolder(BuildTargetHolder[build.Jar]): + pass -class CustomTargetIndexHolder(TargetHolder): - def __init__(self, target, interp): +class CustomTargetIndexHolder(TargetHolder[build.CustomTargetIndex]): + def __init__(self, target: build.CustomTargetIndex, interp: 'Interpreter'): super().__init__(target, interp) self.methods.update({'full_path': self.full_path_method, }) @@ -992,9 +996,9 @@ class Test(InterpreterObject): def get_name(self): return self.name -class SubprojectHolder(InterpreterObject, ObjectHolder): +class SubprojectHolder(InterpreterObject, ObjectHolder[T.Optional['Interpreter']]): - def __init__(self, subinterpreter, subdir, warnings=0, disabled_feature=None, + def __init__(self, subinterpreter: T.Optional['Interpreter'], subdir: str, warnings=0, disabled_feature=None, exception=None): InterpreterObject.__init__(self) ObjectHolder.__init__(self, subinterpreter) @@ -1786,7 +1790,7 @@ class ModuleState(T.NamedTuple): current_node: mparser.BaseNode -class ModuleHolder(InterpreterObject, ObjectHolder): +class ModuleHolder(InterpreterObject, ObjectHolder['ExtensionModule']): def __init__(self, modname: str, module: 'ExtensionModule', interpreter: 'Interpreter'): InterpreterObject.__init__(self) ObjectHolder.__init__(self, module) @@ -2181,8 +2185,7 @@ class MesonMain(InterpreterObject): name, exe = args if not isinstance(name, str): raise InterpreterException('First argument must be a string') - if hasattr(exe, 'held_object'): - exe = exe.held_object + exe = unholder(exe) if isinstance(exe, mesonlib.File): abspath = exe.absolute_path(self.interpreter.environment.source_dir, self.interpreter.environment.build_dir) @@ -2202,8 +2205,7 @@ class MesonMain(InterpreterObject): dep = args[1] if not isinstance(name, str) or not name: raise InterpreterException('First argument must be a string and cannot be empty') - if hasattr(dep, 'held_object'): - dep = dep.held_object + dep = unholder(dep) if not isinstance(dep, dependencies.Dependency): raise InterpreterException('Second argument must be a dependency object') identifier = dependencies.get_dep_identifier(name, kwargs) @@ -2566,9 +2568,7 @@ class Interpreter(InterpreterBase): return DependencyHolder(item, self.subproject) elif isinstance(item, dependencies.ExternalProgram): return ExternalProgramHolder(item, self.subproject) - elif hasattr(item, 'held_object'): - return item - elif isinstance(item, InterpreterObject): + elif isinstance(item, (InterpreterObject, ObjectHolder)): return item else: raise InterpreterException('Module returned a value of unknown type.') @@ -2601,9 +2601,7 @@ class Interpreter(InterpreterBase): return InstallDirHolder(v) elif isinstance(v, Test): self.build.tests.append(v) - elif hasattr(v, 'held_object'): - pass - elif isinstance(v, (int, str, bool, Disabler)): + elif isinstance(v, (int, str, bool, Disabler, ObjectHolder)): pass else: raise InterpreterException('Module returned a value of unknown type.') @@ -3276,26 +3274,12 @@ external dependencies (including libraries) must go to "dependencies".''') success &= self.add_languages(args, required, MachineChoice.HOST) return success - def get_message_string_arg(self, arg): - if isinstance(arg, list): - argstr = stringifyUserArguments(arg) - elif isinstance(arg, dict): - argstr = stringifyUserArguments(arg) - elif isinstance(arg, str): - argstr = arg - elif isinstance(arg, int): - argstr = str(arg) - else: - raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.') - - return argstr - @noArgsFlattening @noKwargs def func_message(self, node, args, kwargs): if len(args) > 1: FeatureNew.single_use('message with more than one argument', '0.54.0', self.subproject) - args_str = [self.get_message_string_arg(i) for i in args] + args_str = [stringifyUserArguments(i) for i in args] self.message_impl(args_str) def message_impl(self, args): @@ -3357,13 +3341,16 @@ external dependencies (including libraries) must go to "dependencies".''') def func_warning(self, node, args, kwargs): if len(args) > 1: FeatureNew.single_use('warning with more than one argument', '0.54.0', self.subproject) - args_str = [self.get_message_string_arg(i) for i in args] + args_str = [stringifyUserArguments(i) for i in args] mlog.warning(*args_str, location=node) + @noArgsFlattening @noKwargs def func_error(self, node, args, kwargs): - self.validate_arguments(args, 1, [str]) - raise InterpreterException('Problem encountered: ' + args[0]) + if len(args) > 1: + FeatureNew.single_use('error with more than one argument', '0.58.0', self.subproject) + args_str = [stringifyUserArguments(i) for i in args] + raise InterpreterException('Problem encountered: ' + ' '.join(args_str)) @noKwargs @noPosargs diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py index e924e93..376f8b0 100644 --- a/mesonbuild/interpreterbase.py +++ b/mesonbuild/interpreterbase.py @@ -60,9 +60,9 @@ class InterpreterObject: TV_InterpreterObject = T.TypeVar('TV_InterpreterObject') class ObjectHolder(T.Generic[TV_InterpreterObject]): - def __init__(self, obj: InterpreterObject, subproject: T.Optional[str] = None) -> None: - self.held_object = obj # type: InterpreterObject - self.subproject = subproject # type: str + def __init__(self, obj: TV_InterpreterObject, subproject: str = '') -> None: + self.held_object = obj + self.subproject = subproject def __repr__(self) -> str: return '<Holder: {!r}>'.format(self.held_object) diff --git a/mesonbuild/mcompile.py b/mesonbuild/mcompile.py index 16eb82a..ba1d3cf 100644 --- a/mesonbuild/mcompile.py +++ b/mesonbuild/mcompile.py @@ -142,14 +142,9 @@ def get_parsed_args_ninja(options: 'argparse.Namespace', builddir: Path) -> T.Tu if runner is None: raise MesonException('Cannot find ninja.') - cmd = runner + ['-C', builddir.as_posix()] - - if options.targets: - intro_data = parse_introspect_data(builddir) - for t in options.targets: - cmd.extend(generate_target_names_ninja(ParsedTargetName(t), builddir, intro_data)) - if options.clean: - cmd.append('clean') + cmd = runner + if not builddir.samefile('.'): + cmd.extend(['-C', builddir.as_posix()]) # If the value is set to < 1 then don't set anything, which let's # ninja/samu decide what to do. @@ -163,6 +158,14 @@ def get_parsed_args_ninja(options: 'argparse.Namespace', builddir: Path) -> T.Tu cmd += options.ninja_args + # operands must be processed after options/option-arguments + if options.targets: + intro_data = parse_introspect_data(builddir) + for t in options.targets: + cmd.extend(generate_target_names_ninja(ParsedTargetName(t), builddir, intro_data)) + if options.clean: + cmd.append('clean') + return cmd, None def generate_target_name_vs(target: ParsedTargetName, builddir: Path, introspect_data: dict) -> str: diff --git a/run_unittests.py b/run_unittests.py index a82e476..1989e93 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -5864,6 +5864,11 @@ class FailureTests(BasePlatformTests): "meson.override_dependency('zlib', declare_dependency())", """Tried to override dependency 'zlib' which has already been resolved or overridden""") + def test_error_func(self): + self.assertMesonRaises("error('a', 'b', ['c', ['d', {'e': 'f'}]], 'g')", + "Problem encountered: a b \['c', \['d', {'e' : 'f'}\]\] g") + + @unittest.skipUnless(is_windows() or is_cygwin(), "requires Windows (or Windows via Cygwin)") class WindowsTests(BasePlatformTests): ''' diff --git a/test cases/common/106 generatorcustom/gen-resx.py b/test cases/common/106 generatorcustom/gen-resx.py new file mode 100755 index 0000000..7d31ade --- /dev/null +++ b/test cases/common/106 generatorcustom/gen-resx.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3 + +import sys + +ofile = sys.argv[1] +num = sys.argv[2] + +with open(ofile, 'w') as f: + f.write('res{}\n'.format(num)) diff --git a/test cases/common/106 generatorcustom/main.c b/test cases/common/106 generatorcustom/main.c index 4b6857d..153dc12 100644 --- a/test cases/common/106 generatorcustom/main.c +++ b/test cases/common/106 generatorcustom/main.c @@ -1,7 +1,8 @@ -#include<stdio.h> +#include <stdio.h> -#include"alltogether.h" +#include "alltogether.h" int main(void) { + printf("%s - %s - %s - %s\n", res1, res2, res3, res4); return 0; } diff --git a/test cases/common/106 generatorcustom/meson.build b/test cases/common/106 generatorcustom/meson.build index b3f50bb..2128d21 100644 --- a/test cases/common/106 generatorcustom/meson.build +++ b/test cases/common/106 generatorcustom/meson.build @@ -2,12 +2,21 @@ project('generatorcustom', 'c') creator = find_program('gen.py') catter = find_program('catter.py') +gen_resx = find_program('gen-resx.py') gen = generator(creator, output: '@BASENAME@.h', arguments : ['@INPUT@', '@OUTPUT@']) -hs = gen.process('res1.txt', 'res2.txt') +res3 = custom_target('gen-res3', + output : 'res3.txt', + command : [gen_resx, '@OUTPUT@', '3']) + +res4 = custom_target('gen-res4', + output : 'res4.txt', + command : [gen_resx, '@OUTPUT@', '4']) + +hs = gen.process('res1.txt', 'res2.txt', res3, res4[0]) allinone = custom_target('alltogether', input : hs, @@ -17,4 +26,3 @@ allinone = custom_target('alltogether', proggie = executable('proggie', 'main.c', allinone) test('proggie', proggie) - |