From de65adb8b100731ff31eee92da44b4cc10ac5aa3 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sun, 11 Mar 2018 14:58:23 +0200 Subject: Made it possible to override find_program to return a different program. Closes https://github.com/mesonbuild/meson/issues/2005 --- mesonbuild/build.py | 2 + mesonbuild/interpreter.py | 45 +++++++++++++++++++++- test cases/common/182 find override/meson.build | 4 ++ .../common/182 find override/otherdir/main.c | 5 +++ .../common/182 find override/otherdir/meson.build | 11 ++++++ .../common/182 find override/otherdir/source.desc | 1 + .../common/182 find override/subdir/converter.py | 15 ++++++++ .../common/182 find override/subdir/meson.build | 3 ++ test cases/failing/70 override used/meson.build | 5 +++ test cases/failing/70 override used/other.py | 3 ++ test cases/failing/70 override used/something.py | 3 ++ test cases/failing/71 dual override/meson.build | 5 +++ test cases/failing/71 dual override/overrides.py | 4 ++ 13 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 test cases/common/182 find override/meson.build create mode 100644 test cases/common/182 find override/otherdir/main.c create mode 100644 test cases/common/182 find override/otherdir/meson.build create mode 100644 test cases/common/182 find override/otherdir/source.desc create mode 100755 test cases/common/182 find override/subdir/converter.py create mode 100644 test cases/common/182 find override/subdir/meson.build create mode 100644 test cases/failing/70 override used/meson.build create mode 100755 test cases/failing/70 override used/other.py create mode 100755 test cases/failing/70 override used/something.py create mode 100644 test cases/failing/71 dual override/meson.build create mode 100644 test cases/failing/71 dual override/overrides.py diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8d16c95..97c3df8 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -121,6 +121,8 @@ class Build: self.dep_manifest = {} self.cross_stdlibs = {} self.test_setups = {} + self.find_overrides = {} + self.searched_programs = set() # The list of all programs that have been searched for. def add_compiler(self, compiler): if self.static_linker is None and compiler.needs_static_linker(): diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index b99a413..6d7f2a9 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -1304,6 +1304,7 @@ class MesonMain(InterpreterObject): 'add_install_script': self.add_install_script_method, 'add_postconf_script': self.add_postconf_script_method, 'install_dependency_manifest': self.install_dependency_manifest_method, + 'override_find_program': self.override_find_program_method, 'project_version': self.project_version_method, 'project_license': self.project_license_method, 'version': self.version_method, @@ -1416,6 +1417,20 @@ class MesonMain(InterpreterObject): raise InterpreterException('Argument must be a string.') self.build.dep_manifest_name = args[0] + def override_find_program_method(self, args, kwargs): + if len(args) != 2: + raise InterpreterException('Override needs two arguments') + name = args[0] + exe = args[1] + if not isinstance(name, str): + raise InterpreterException('First argument must be a string') + if hasattr(exe, 'held_object'): + exe = exe.held_object + if not isinstance(exe, dependencies.ExternalProgram): + # FIXME, make this work if the exe is an Executable target. + raise InterpreterException('Second argument must be an external program.') + self.interpreter.add_find_program_override(name, exe) + def project_version_method(self, args, kwargs): return self.build.dep_manifest[self.interpreter.active_projectname]['version'] @@ -2264,6 +2279,31 @@ to directly access options of other subprojects.''') if progobj.found(): return progobj + def program_from_overrides(self, command_names): + for name in command_names: + if not isinstance(name, str): + continue + if name in self.build.find_overrides: + exe = self.build.find_overrides[name] + mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'), + '(overridden: %s)' % ' '.join(exe.command)) + return ExternalProgramHolder(exe) + return None + + def store_name_lookups(self, command_names): + for name in command_names: + if isinstance(name, str): + self.build.searched_programs.add(name) + + def add_find_program_override(self, name, exe): + if name in self.build.searched_programs: + raise InterpreterException('Tried to override finding of executable "%s" which has already been found.' + % name) + if name in self.build.find_overrides: + raise InterpreterException('Tried to override executable "%s" which has already been overridden.' + % name) + self.build.find_overrides[name] = exe + @permittedKwargs(permitted_kwargs['find_program']) def func_find_program(self, node, args, kwargs): if not args: @@ -2271,8 +2311,9 @@ to directly access options of other subprojects.''') required = kwargs.get('required', True) if not isinstance(required, bool): raise InvalidArguments('"required" argument must be a boolean.') - progobj = None - if self.build.environment.is_cross_build(): + self.store_name_lookups(args) + progobj = self.program_from_overrides(args) + if progobj is None and self.build.environment.is_cross_build(): use_native = kwargs.get('native', False) if not isinstance(use_native, bool): raise InvalidArguments('Argument to "native" must be a boolean.') diff --git a/test cases/common/182 find override/meson.build b/test cases/common/182 find override/meson.build new file mode 100644 index 0000000..ebf3a05 --- /dev/null +++ b/test cases/common/182 find override/meson.build @@ -0,0 +1,4 @@ +project('find program override', 'c') + +subdir('subdir') +subdir('otherdir') diff --git a/test cases/common/182 find override/otherdir/main.c b/test cases/common/182 find override/otherdir/main.c new file mode 100644 index 0000000..2cef67c --- /dev/null +++ b/test cases/common/182 find override/otherdir/main.c @@ -0,0 +1,5 @@ +int be_seeing_you(); + +int main(int argc, char **argv) { + return be_seeing_you() == 6 ? 0 : 1; +} diff --git a/test cases/common/182 find override/otherdir/meson.build b/test cases/common/182 find override/otherdir/meson.build new file mode 100644 index 0000000..84e7e84 --- /dev/null +++ b/test cases/common/182 find override/otherdir/meson.build @@ -0,0 +1,11 @@ +gen = find_program('codegen') # Should use overridden value set in "subdir". + +src = custom_target('arrival', + input : 'source.desc', + output : 'file.c', + command : [gen, '@INPUT@', '@OUTPUT@'] + ) + +e = executable('six', 'main.c', src) + +test('six', e) diff --git a/test cases/common/182 find override/otherdir/source.desc b/test cases/common/182 find override/otherdir/source.desc new file mode 100644 index 0000000..8b19c9c --- /dev/null +++ b/test cases/common/182 find override/otherdir/source.desc @@ -0,0 +1 @@ +be_seeing_you diff --git a/test cases/common/182 find override/subdir/converter.py b/test cases/common/182 find override/subdir/converter.py new file mode 100755 index 0000000..55b2a70 --- /dev/null +++ b/test cases/common/182 find override/subdir/converter.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 + +import sys +import pathlib + +[ifilename, ofilename] = sys.argv[1:3] + +ftempl = '''int %s() { + return 6; +} +''' + +d = pathlib.Path(ifilename).read_text().split('\n')[0].strip() + +pathlib.Path(ofilename).write_text(ftempl % d) \ No newline at end of file diff --git a/test cases/common/182 find override/subdir/meson.build b/test cases/common/182 find override/subdir/meson.build new file mode 100644 index 0000000..0d1f9d0 --- /dev/null +++ b/test cases/common/182 find override/subdir/meson.build @@ -0,0 +1,3 @@ +x = find_program('converter.py') + +meson.override_find_program('codegen', x) diff --git a/test cases/failing/70 override used/meson.build b/test cases/failing/70 override used/meson.build new file mode 100644 index 0000000..61885bb --- /dev/null +++ b/test cases/failing/70 override used/meson.build @@ -0,0 +1,5 @@ +project('overridde an already found exe', 'c') + +old = find_program('something.py') +replacement = find_program('other.py') +meson.override_find_program('something.py', replacement) diff --git a/test cases/failing/70 override used/other.py b/test cases/failing/70 override used/other.py new file mode 100755 index 0000000..f62ba96 --- /dev/null +++ b/test cases/failing/70 override used/other.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('Doing something else.') diff --git a/test cases/failing/70 override used/something.py b/test cases/failing/70 override used/something.py new file mode 100755 index 0000000..64c9454 --- /dev/null +++ b/test cases/failing/70 override used/something.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python3 + +print('Doing something.') diff --git a/test cases/failing/71 dual override/meson.build b/test cases/failing/71 dual override/meson.build new file mode 100644 index 0000000..e5f86ba --- /dev/null +++ b/test cases/failing/71 dual override/meson.build @@ -0,0 +1,5 @@ +project('yo dawg', 'c') + +p = find_program('overrides.py') +meson.override_find_program('override', p) +meson.override_find_program('override', p) diff --git a/test cases/failing/71 dual override/overrides.py b/test cases/failing/71 dual override/overrides.py new file mode 100644 index 0000000..49e9b7a --- /dev/null +++ b/test cases/failing/71 dual override/overrides.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python3 + +print('Yo dawg, we put overrides in your overrides,') +print('so now you can override when you override.') -- cgit v1.1