aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/markdown/Reference-manual.md4
-rw-r--r--docs/markdown/snippets/overrideexe.md8
-rw-r--r--mesonbuild/build.py4
-rw-r--r--mesonbuild/dependencies/base.py4
-rw-r--r--mesonbuild/interpreter.py14
-rwxr-xr-xrun_unittests.py11
-rw-r--r--test cases/common/206 override with exe/main2.input0
-rw-r--r--test cases/common/206 override with exe/meson.build15
-rw-r--r--test cases/common/206 override with exe/subprojects/sub/foobar.c12
-rw-r--r--test cases/common/206 override with exe/subprojects/sub/meson.build3
-rw-r--r--test cases/failing/81 override exe config/foo.c3
-rw-r--r--test cases/failing/81 override exe config/meson.build6
12 files changed, 78 insertions, 6 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index ea11f60..9762c5d 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -1529,7 +1529,9 @@ the following methods.
specifies that whenever `find_program` is used to find a program
named `progname`, Meson should not not look it up on the system but
instead return `program`, which may either be the result of
- `find_program` or `configure_file`.
+ `find_program`, `configure_file` or `executable`.
+
+ If `program` is an `executable`, it cannot be used during configure.
- `project_version()` returns the version string specified in
`project` function call.
diff --git a/docs/markdown/snippets/overrideexe.md b/docs/markdown/snippets/overrideexe.md
new file mode 100644
index 0000000..59213c5
--- /dev/null
+++ b/docs/markdown/snippets/overrideexe.md
@@ -0,0 +1,8 @@
+## More flexible `override_find_program()`.
+
+It is now possible to pass an `executable` to
+`override_find_program()` if the overridden program is not used during
+configure.
+
+This is particularly useful for fallback dependencies like Protobuf
+that also provide a tool like protoc.
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index efe58f8..585a8d3 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1314,6 +1314,10 @@ class Executable(BuildTarget):
# Only linkwithable if using export_dynamic
self.is_linkwithable = self.export_dynamic
+ def description(self):
+ '''Human friendly description of the executable'''
+ return self.name
+
def type_suffix(self):
return "@exe"
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index e375f10..b369780 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -1057,6 +1057,10 @@ class ExternalProgram:
r = '<{} {!r} -> {!r}>'
return r.format(self.__class__.__name__, self.name, self.command)
+ def description(self):
+ '''Human friendly description of the command'''
+ return ' '.join(self.command)
+
@staticmethod
def from_cross_info(cross_info, name):
if name not in cross_info.config['binaries']:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index dba3fc0..9bd21e3 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -480,7 +480,7 @@ class ExternalProgramHolder(InterpreterObject, ObjectHolder):
return self.held_object.get_path()
def found(self):
- return self.held_object.found()
+ return isinstance(self.held_object, build.Executable) or self.held_object.found()
def get_command(self):
return self.held_object.get_command()
@@ -1780,9 +1780,8 @@ class MesonMain(InterpreterObject):
if not os.path.exists(abspath):
raise InterpreterException('Tried to override %s with a file that does not exist.' % name)
exe = dependencies.ExternalProgram(abspath)
- 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.')
+ if not isinstance(exe, (dependencies.ExternalProgram, build.Executable)):
+ raise InterpreterException('Second argument must be an external program or executable.')
self.interpreter.add_find_program_override(name, exe)
@noPosargs
@@ -2184,6 +2183,11 @@ external dependencies (including libraries) must go to "dependencies".''')
'or configure_file(), or a compiler object; not {!r}'
if isinstance(cmd, ExternalProgramHolder):
cmd = cmd.held_object
+ if isinstance(cmd, build.Executable):
+ progname = node.args.arguments[0].value
+ msg = 'Program {!r} was overridden with the compiled executable {!r}'\
+ ' and therefore cannot be used during configuration'
+ raise InterpreterException(msg.format(progname, cmd.description()))
elif isinstance(cmd, CompilerHolder):
cmd = cmd.compiler.get_exelist()[0]
prog = ExternalProgram(cmd, silent=True)
@@ -2758,7 +2762,7 @@ external dependencies (including libraries) must go to "dependencies".''')
exe = self.build.find_overrides[name]
if not silent:
mlog.log('Program', mlog.bold(name), 'found:', mlog.green('YES'),
- '(overridden: %s)' % ' '.join(exe.command))
+ '(overridden: %s)' % exe.description())
return ExternalProgramHolder(exe)
return None
diff --git a/run_unittests.py b/run_unittests.py
index 94c1aba..d446a54 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -3881,6 +3881,17 @@ endian = 'little'
return
raise RuntimeError('Could not find the rpath')
+ def test_override_with_exe_dep(self):
+ '''
+ Test that we produce the correct dependencies when a program is overridden with an executable.
+ '''
+ testdir = os.path.join(self.common_test_dir, '206 override with exe')
+ self.init(testdir)
+ with open(os.path.join(self.builddir, 'build.ninja')) as bfile:
+ for line in bfile:
+ if 'main1.c:' in line or 'main2.c:' in line:
+ self.assertIn('| subprojects/sub/foobar', line)
+
@skipIfNoPkgconfig
def test_usage_external_library(self):
'''
diff --git a/test cases/common/206 override with exe/main2.input b/test cases/common/206 override with exe/main2.input
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test cases/common/206 override with exe/main2.input
diff --git a/test cases/common/206 override with exe/meson.build b/test cases/common/206 override with exe/meson.build
new file mode 100644
index 0000000..81f6c02
--- /dev/null
+++ b/test cases/common/206 override with exe/meson.build
@@ -0,0 +1,15 @@
+project('myexe', 'c')
+sub = subproject('sub')
+prog = find_program('foobar')
+custom1 = custom_target('custom1',
+ build_by_default : true,
+ input : [],
+ output : 'main1.c',
+ command : [prog, '@OUTPUT@'])
+gen = generator(prog,
+ output : '@BASENAME@.c',
+ arguments : ['@OUTPUT@'])
+custom2 = gen.process('main2.input')
+
+executable('e1', custom1)
+executable('e2', custom2)
diff --git a/test cases/common/206 override with exe/subprojects/sub/foobar.c b/test cases/common/206 override with exe/subprojects/sub/foobar.c
new file mode 100644
index 0000000..030ac49
--- /dev/null
+++ b/test cases/common/206 override with exe/subprojects/sub/foobar.c
@@ -0,0 +1,12 @@
+#include <assert.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[]) {
+ FILE *f = fopen(argv[1], "w");
+ const char msg[] = "int main(void) {return 0;}\n";
+ size_t w = fwrite(msg, 1, sizeof(msg) - 1, f);
+ assert(w == sizeof(msg) - 1);
+ int r = fclose(f);
+ assert(r == 0);
+ return 0;
+}
diff --git a/test cases/common/206 override with exe/subprojects/sub/meson.build b/test cases/common/206 override with exe/subprojects/sub/meson.build
new file mode 100644
index 0000000..1f186da
--- /dev/null
+++ b/test cases/common/206 override with exe/subprojects/sub/meson.build
@@ -0,0 +1,3 @@
+project('sub', 'c')
+foobar = executable('foobar', 'foobar.c', native : true)
+meson.override_find_program('foobar', foobar)
diff --git a/test cases/failing/81 override exe config/foo.c b/test cases/failing/81 override exe config/foo.c
new file mode 100644
index 0000000..03b2213
--- /dev/null
+++ b/test cases/failing/81 override exe config/foo.c
@@ -0,0 +1,3 @@
+int main(void) {
+ return 0;
+}
diff --git a/test cases/failing/81 override exe config/meson.build b/test cases/failing/81 override exe config/meson.build
new file mode 100644
index 0000000..29a7416
--- /dev/null
+++ b/test cases/failing/81 override exe config/meson.build
@@ -0,0 +1,6 @@
+project('myexe', 'c')
+
+foo = executable('foo', 'foo.c')
+meson.override_find_program('bar', foo)
+bar = find_program('bar')
+run_command(bar)