aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-08-19 19:47:51 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2017-09-04 22:47:12 +0300
commit72a6683c6f564afa8f8d7e96b0238961aa867f00 (patch)
treeb6c7828fcaaf52472626bb55efb1cad4ba7bad40
parente94a9c8fcfa4776e09c9cabfe01de705ce34b735 (diff)
downloadmeson-72a6683c6f564afa8f8d7e96b0238961aa867f00.zip
meson-72a6683c6f564afa8f8d7e96b0238961aa867f00.tar.gz
meson-72a6683c6f564afa8f8d7e96b0238961aa867f00.tar.bz2
Permit overriding find_program from the cross file.
-rw-r--r--docs/markdown/Reference-manual.md6
-rw-r--r--docs/markdown/snippets/cross_find.md15
-rw-r--r--mesonbuild/interpreter.py46
-rwxr-xr-xrun_unittests.py22
-rw-r--r--test cases/unit/12 cross prog/meson.build12
-rwxr-xr-xtest cases/unit/12 cross prog/some_cross_tool.py5
-rwxr-xr-xtest cases/unit/12 cross prog/sometool.py5
7 files changed, 102 insertions, 9 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index 3f25e80..34b473d 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -466,6 +466,12 @@ Keyword arguments are the following:
then use the `.found()` method on the returned object to check
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
with the executable/interpreter specified in it both on Windows
(because the command invocator will reject the command otherwise) and
diff --git a/docs/markdown/snippets/cross_find.md b/docs/markdown/snippets/cross_find.md
new file mode 100644
index 0000000..b16d64d
--- /dev/null
+++ b/docs/markdown/snippets/cross_find.md
@@ -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)
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 72df3c7..d71ce1f 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -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'},
'declare_dependency': {'include_directories', 'link_with', 'sources', 'dependencies', 'compile_args', 'link_args', 'version'},
'executable': exe_kwargs,
- 'find_program': {'required'},
+ 'find_program': {'required', 'native'},
'generator': {'arguments', 'output', 'depfile'},
'include_directories': {'is_system'},
'install_data': {'install_dir', 'install_mode', 'sources'},
@@ -1963,13 +1963,22 @@ class Interpreter(InterpreterBase):
break
self.coredata.base_options[optname] = oobj
- @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.')
+ def program_from_cross_file(self, prognames):
+ bins = self.environment.cross_info.config['binaries']
+ for p in prognames:
+ if hasattr(p, 'held_object'):
+ p = p.held_object
+ if isinstance(p, mesonlib.File):
+ 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.
# Do not cache found programs because find_program('foobar')
# might give different results when run from different source dirs.
@@ -1992,8 +2001,27 @@ class Interpreter(InterpreterBase):
progobj = ExternalProgramHolder(extprog)
if progobj.found():
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)
+ if progobj is None:
+ return ExternalProgramHolder(dependencies.ExternalProgram('nonexistingprogram'))
return progobj
def func_find_library(self, node, args, kwargs):
diff --git a/run_unittests.py b/run_unittests.py
index 1fb1b4b..c065790 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1923,6 +1923,28 @@ class LinuxlikeTests(BasePlatformTests):
self.run_tests()
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):
'''
Tests that verify cross-compilation to Linux/ARM
diff --git a/test cases/unit/12 cross prog/meson.build b/test cases/unit/12 cross prog/meson.build
new file mode 100644
index 0000000..e628701
--- /dev/null
+++ b/test cases/unit/12 cross prog/meson.build
@@ -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)
diff --git a/test cases/unit/12 cross prog/some_cross_tool.py b/test cases/unit/12 cross prog/some_cross_tool.py
new file mode 100755
index 0000000..1edd10f
--- /dev/null
+++ b/test cases/unit/12 cross prog/some_cross_tool.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+print('cross')
diff --git a/test cases/unit/12 cross prog/sometool.py b/test cases/unit/12 cross prog/sometool.py
new file mode 100755
index 0000000..4c0e3b1
--- /dev/null
+++ b/test cases/unit/12 cross prog/sometool.py
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+from __future__ import print_function
+
+print('native')