fix: Ensure that build targets have all methods from ExternalProgram

As a side-effect from #8885 `find_program()` returns now `Executable`
objects when `meson.override_find_program` is called with an
executable target. To resolve this conflict the missing methods
from `ExternalProgram` are added to `BuildTarget`.
pull/8912/head
Daniel Mensinger 4 years ago committed by Jussi Pakkanen
parent 2e8729a7e6
commit 5cd9f88d6c
  1. 11
      docs/markdown/Reference-manual.md
  2. 16
      docs/markdown/snippets/build-target-found.md
  3. 25
      mesonbuild/interpreter/interpreterobjects.py
  4. 2
      mesonbuild/interpreterbase/baseobjects.py
  5. 10
      test cases/common/182 find override/meson.build
  6. 4
      test cases/common/182 find override/otherdir/meson.build

@ -2561,6 +2561,12 @@ module](#shared_module).
this and will also allow Meson to setup inter-target dependencies
correctly. Please file a bug if that doesn't work for you.
- `path()` *(since 0.59.0)* **(deprecated)**: does the exact same
as `full_path()`. **NOTE:** This function is solely kept for compatebility
with [`external program`](#external-program-object) objects. It will be
removed once the, also deprecated, corresponding `path()` function in the
`external program` object is removed.
- `private_dir_include()`: returns a opaque value that works like
`include_directories` but points to the private directory of this
target, usually only needed if an another target needs to access
@ -2568,6 +2574,11 @@ module](#shared_module).
- `name()` *(since 0.54.0)*: returns the target name.
- `found()` *(since 0.59.0)*: Always returns `true`. This function is meant
to make executables objects feature compatible with
[`external program`](#external-program-object) objects. This simplifies
use-cases where an executable is used instead of an external program.
### `configuration` data object

@ -0,0 +1,16 @@
## New `build target` methods
The [`build target` object](Reference-manual.md#build-target-object) now supports
the following two functions, to ensure feature compatebility with
[`external program` objects](Reference-manual.html#external-program-object):
- `found()`: Always returns `true`. This function is meant
to make executables objects feature compatible with
`external program` objects. This simplifies
use-cases where an executable is used instead of an external program.
- `path()`: **(deprecated)** does the exact same as `full_path()`.
**NOTE:** This function is solely kept for compatebility
with `external program` objects. It will be
removed once the, also deprecated, corresponding `path()` function in the
`external program` object is removed.

@ -582,19 +582,14 @@ class ExternalProgramHolder(ObjectHolder[ExternalProgram]):
return self._full_path()
def _full_path(self) -> str:
exe = self.held_object
# TODO: How is this case even possible? Why can this hold a build.Executable?
if isinstance(exe, build.Executable):
assert self.interpreter.backend is not None
return self.interpreter.backend.get_target_filename_abs(exe)
if not self.found():
raise InterpreterException('Unable to get the path of a not-found external program')
path = exe.get_path()
path = self.held_object.get_path()
assert path is not None
return exe.get_path()
return path
def found(self) -> bool:
return isinstance(self.held_object, build.Executable) or self.held_object.found()
return self.held_object.found()
class ExternalLibraryHolder(ObjectHolder[ExternalLibrary]):
def __init__(self, el: ExternalLibrary, interpreter: 'Interpreter'):
@ -790,6 +785,8 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
'get_id': self.get_id_method,
'outdir': self.outdir_method,
'full_path': self.full_path_method,
'path': self.path_method,
'found': self.found_method,
'private_dir_include': self.private_dir_include_method,
})
@ -808,6 +805,12 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
def is_cross(self) -> bool:
return not self._target_object.environment.machines.matches_build_machine(self._target_object.for_machine)
@noPosargs
@noKwargs
@FeatureNew('BuildTarget.found', '0.59.0')
def found_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> bool:
return True
@noPosargs
@noKwargs
def private_dir_include_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.IncludeDirs:
@ -818,6 +821,12 @@ class BuildTargetHolder(ObjectHolder[_BuildTarget]):
def full_path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_filename_abs(self._target_object)
@noPosargs
@noKwargs
@FeatureDeprecated('BuildTarget.path', '0.55.0', 'Use BuildTarget.full_path instead')
def path_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:
return self.interpreter.backend.get_target_filename_abs(self._target_object)
@noPosargs
@noKwargs
def outdir_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> str:

@ -58,7 +58,7 @@ class InterpreterObject:
if not getattr(method, 'no-args-flattening', False):
args = flatten(args)
return method(args, kwargs)
raise InvalidCode('Unknown method "%s" in object.' % method_name)
raise InvalidCode(f'Unknown method "{method_name}" in object {self} of type {type(self).__name__}.')
class MesonInterpreterObject(InterpreterObject):
''' All non-elementary objects and non-object-holders should be derived from this '''

@ -1,8 +1,10 @@
project('find program override', 'c')
gencodegen = find_program('gencodegen', required : false)
six_prog = find_program('six_meson_exe', required : false)
assert(not gencodegen.found(), 'gencodegen is an internal program, should not be found')
assert(not six_prog.found(), 'six_meson_exe is an internal program, should not be found')
# Test the check-if-found-else-override workflow
if not gencodegen.found()
@ -13,3 +15,11 @@ subdir('otherdir')
tool = find_program('sometool')
assert(tool.found())
assert(tool.full_path() != '')
assert(tool.full_path() == tool.path())
# six_meson_exe is an overritten project executable
six_prog = find_program('six_meson_exe')
assert(six_prog.found())
assert(six_prog.full_path() != '')
assert(six_prog.full_path() == six_prog.path())

@ -10,6 +10,10 @@ e = executable('six', 'main.c', src)
test('six', e)
# Override stuff with an executables
meson.override_find_program('six_meson_exe', e)
# The same again, but this time with a program that was generated
# with configure_file.

Loading…
Cancel
Save