Permit overriding find_program from the cross file.

pull/2276/merge
Jussi Pakkanen 7 years ago
parent e94a9c8fcf
commit 72a6683c6f
  1. 6
      docs/markdown/Reference-manual.md
  2. 15
      docs/markdown/snippets/cross_find.md
  3. 46
      mesonbuild/interpreter.py
  4. 22
      run_unittests.py
  5. 12
      test cases/unit/12 cross prog/meson.build
  6. 5
      test cases/unit/12 cross prog/some_cross_tool.py
  7. 5
      test cases/unit/12 cross prog/sometool.py

@ -466,6 +466,12 @@ Keyword arguments are the following:
then use the `.found()` method on the returned object to check then use the `.found()` method on the returned object to check
whether it was found or not. whether it was found or not.
- `native` defines how this executable should be searched. By default
it is set to `false`, which causes Meson to first look for the
executable in the cross file (when cross building) and if it is not
defined there, then from the system. If set to `true`, the cross
file is ignored and the program is only searched from the system.
Meson will also autodetect scripts with a shebang line and run them Meson will also autodetect scripts with a shebang line and run them
with the executable/interpreter specified in it both on Windows with the executable/interpreter specified in it both on Windows
(because the command invocator will reject the command otherwise) and (because the command invocator will reject the command otherwise) and

@ -0,0 +1,15 @@
# Can override executables in the cross file
The cross file can now be used for overriding the result of
`find_program`. As an example if you want to find the `objdump`
command and have the following definition in your cross file:
[binaries]
...
objdump = '/usr/bin/arm-linux-gnueabihf-objdump-6'
Then issuing the command `find_program('objdump')` will return the
version specified in the cross file. If you need the build machine's
objdump, you can specify the `native` keyword like this:
native_objdump = find_program('objdump', native : true)

@ -1317,7 +1317,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'}, 'custom_target': {'input', 'output', 'command', 'install', 'install_dir', 'build_always', 'capture', 'depends', 'depend_files', 'depfile', 'build_by_default'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'}, 'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'},
'executable': exe_kwargs, 'executable': exe_kwargs,
'find_program': {'required'}, 'find_program': {'required', 'native'},
'generator': {'arguments', 'output', 'depfile'}, 'generator': {'arguments', 'output', 'depfile'},
'include_directories': {'is_system'}, 'include_directories': {'is_system'},
'install_data': {'install_dir', 'install_mode', 'sources'}, 'install_data': {'install_dir', 'install_mode', 'sources'},
@ -1963,13 +1963,22 @@ class Interpreter(InterpreterBase):
break break
self.coredata.base_options[optname] = oobj self.coredata.base_options[optname] = oobj
@permittedKwargs(permitted_kwargs['find_program']) def program_from_cross_file(self, prognames):
def func_find_program(self, node, args, kwargs): bins = self.environment.cross_info.config['binaries']
if not args: for p in prognames:
raise InterpreterException('No program name specified.') if hasattr(p, 'held_object'):
required = kwargs.get('required', True) p = p.held_object
if not isinstance(required, bool): if isinstance(p, mesonlib.File):
raise InvalidArguments('"required" argument must be a boolean.') continue # Always points to a local (i.e. self generated) file.
if not isinstance(p, str):
raise InterpreterException('Executable name must be a string.')
if p in bins:
exename = bins[p]
extprog = dependencies.ExternalProgram(exename)
progobj = ExternalProgramHolder(extprog)
return progobj
def program_from_system(self, args):
# Search for scripts relative to current subdir. # Search for scripts relative to current subdir.
# Do not cache found programs because find_program('foobar') # Do not cache found programs because find_program('foobar')
# might give different results when run from different source dirs. # might give different results when run from different source dirs.
@ -1992,8 +2001,27 @@ class Interpreter(InterpreterBase):
progobj = ExternalProgramHolder(extprog) progobj = ExternalProgramHolder(extprog)
if progobj.found(): if progobj.found():
return progobj return progobj
if required and not progobj.found():
@permittedKwargs(permitted_kwargs['find_program'])
def func_find_program(self, node, args, kwargs):
if not args:
raise InterpreterException('No program name specified.')
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():
use_native = kwargs.get('native', False)
if not isinstance(use_native, bool):
raise InvalidArguments('Argument to "native" must be a boolean.')
if not use_native:
progobj = self.program_from_cross_file(args)
if progobj is None:
progobj = self.program_from_system(args)
if required and (progobj is None or not progobj.found()):
raise InvalidArguments('Program "%s" not found or not executable' % exename) raise InvalidArguments('Program "%s" not found or not executable' % exename)
if progobj is None:
return ExternalProgramHolder(dependencies.ExternalProgram('nonexistingprogram'))
return progobj return progobj
def func_find_library(self, node, args, kwargs): def func_find_library(self, node, args, kwargs):

@ -1923,6 +1923,28 @@ class LinuxlikeTests(BasePlatformTests):
self.run_tests() self.run_tests()
self.run_target('coverage-html') self.run_target('coverage-html')
def test_cross_find_program(self):
testdir = os.path.join(self.unit_test_dir, '12 cross prog')
crossfile = tempfile.NamedTemporaryFile(mode='w')
print(os.path.join(testdir, 'some_cross_tool.py'))
crossfile.write('''[binaries]
c = '/usr/bin/cc'
ar = '/usr/bin/ar'
strip = '/usr/bin/ar'
sometool.py = '%s'
[properties]
[host_machine]
system = 'linux'
cpu_family = 'arm'
cpu = 'armv7' # Not sure if correct.
endian = 'little'
''' % os.path.join(testdir, 'some_cross_tool.py'))
crossfile.flush()
self.init(testdir, ['--cross-file='+crossfile.name])
class LinuxArmCrossCompileTests(BasePlatformTests): class LinuxArmCrossCompileTests(BasePlatformTests):
''' '''
Tests that verify cross-compilation to Linux/ARM Tests that verify cross-compilation to Linux/ARM

@ -0,0 +1,12 @@
project('cross find program', 'c')
native_exe = find_program('sometool.py', native : true)
cross_exe = find_program('sometool.py')
native_out = run_command(native_exe).stdout().strip()
cross_out = run_command(cross_exe).stdout().strip()
assert(native_out == 'native',
'Native output incorrect:' + native_out)
assert(cross_out == 'cross',
'Cross output incorrect:' + cross_out)

@ -0,0 +1,5 @@
#!/usr/bin/env python
from __future__ import print_function
print('cross')

@ -0,0 +1,5 @@
#!/usr/bin/env python
from __future__ import print_function
print('native')
Loading…
Cancel
Save