summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xclaessens@netflix.com>2025-10-14 12:42:53 -0400
committerXavier Claessens <xclaesse@gmail.com>2025-10-15 12:15:39 -0400
commit2fde6d8940e220f10ffe6d781a77298990d1edb8 (patch)
tree5f421ed6bbc16a3863b8b10d6a4421fbcede5a87
parent569fe981b08f8fa38ff3533651ceff414decadf4 (diff)
downloadmeson-2fde6d8940e220f10ffe6d781a77298990d1edb8.tar.gz
Add interpreter kwarg to local_program()
-rw-r--r--docs/yaml/functions/local_program.yaml7
-rw-r--r--mesonbuild/interpreter/interpreter.py15
-rw-r--r--mesonbuild/interpreter/kwargs.py1
-rw-r--r--test cases/common/285 local program/meson.build16
4 files changed, 38 insertions, 1 deletions
diff --git a/docs/yaml/functions/local_program.yaml b/docs/yaml/functions/local_program.yaml
index d91867b02..07fafcf3a 100644
--- a/docs/yaml/functions/local_program.yaml
+++ b/docs/yaml/functions/local_program.yaml
@@ -34,3 +34,10 @@ kwargs:
Specifies that this target depends on the specified
target(s). If specified, this program can only be used at build time,
after those targets have been built.
+
+ interpreter:
+ type: external_program
+ description: |
+ When the program is a [[@custom_tgt]], Meson cannot derive the interpreter
+ from the file's "shebang" (`#!`) line before it's built. If needed, this
+ argument allows specifying an interpreter for the script.
diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py
index 7cf9ecc9c..f05344877 100644
--- a/mesonbuild/interpreter/interpreter.py
+++ b/mesonbuild/interpreter/interpreter.py
@@ -1801,16 +1801,29 @@ class Interpreter(InterpreterBase, HoldableObject):
'local_program',
DEPENDS_KW,
DEPEND_FILES_KW,
+ KwargInfo('interpreter', (ExternalProgram, NoneType), default=None),
)
def func_local_program(self, node: mparser.BaseNode, args: T.Tuple[T.Union[mesonlib.FileOrString, build.Executable, build.CustomTarget, build.CustomTargetIndex]],
kwargs: kwtypes.LocalProgram) -> build.LocalProgram:
depends = [d.target if isinstance(d, build.CustomTargetIndex) else d for d in kwargs['depends']]
depend_files = self.source_strings_to_files(kwargs['depend_files'])
+ interpreter = kwargs['interpreter']
exe = args[0]
if isinstance(exe, (str, mesonlib.File)):
file = self.source_strings_to_files([exe])[0]
abspath = file.absolute_path(self.environment.source_dir, self.environment.build_dir)
- exe = ExternalProgram(file.fname, command=[abspath], silent=True)
+ prog = ExternalProgram(file.fname, command=[abspath], silent=True)
+ return build.LocalProgram(prog, self.project_version, depends, depend_files)
+ if interpreter:
+ if not isinstance(exe, (build.CustomTarget, build.CustomTargetIndex)):
+ raise InvalidArguments('The "interpreter" argument can only be used when the first argument is a custom target.')
+ if not interpreter.found():
+ raise InvalidArguments(f'Specified interpreter program {interpreter.description()!r} not found.')
+ target = exe.target if isinstance(exe, build.CustomTargetIndex) else exe
+ depends.append(target)
+ cmd = interpreter.get_command() + [self.backend.get_target_filename(exe)]
+ prog = ExternalProgram(exe.name, command=cmd, silent=True)
+ return build.LocalProgram(prog, self.project_version, depends, depend_files)
return build.LocalProgram(exe, self.project_version, depends, depend_files)
# When adding kwargs, please check if they make sense in dependencies.get_dep_identifier()
diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py
index b7b22827d..d863b0892 100644
--- a/mesonbuild/interpreter/kwargs.py
+++ b/mesonbuild/interpreter/kwargs.py
@@ -251,6 +251,7 @@ class LocalProgram(TypedDict):
depend_files: T.List[FileOrString]
depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]
+ interpreter: T.Optional[ExternalProgram]
class RunCommand(TypedDict):
diff --git a/test cases/common/285 local program/meson.build b/test cases/common/285 local program/meson.build
index e7a4a98e9..fba59e8e5 100644
--- a/test cases/common/285 local program/meson.build
+++ b/test cases/common/285 local program/meson.build
@@ -38,3 +38,19 @@ custom_target(
capture: true,
build_by_default: true,
)
+
+test('test-prog3', prog3)
+
+# Custom target as local program. Meson cannot parse the shebang at configure time,
+# so we need to specify it otherwise it won't run on Windows.
+prog_ct = custom_target(
+ input: 'prog.py',
+ output: 'prog-ct.py',
+ command: [python3, '-c', 'import shutil,sys;shutil.copy(sys.argv[1], sys.argv[2])', '@INPUT@', '@OUTPUT@'],
+ depends: pymod,
+)
+meson.override_find_program('prog4', local_program(prog_ct, interpreter: python3))
+prog4 = find_program('prog4')
+assert(prog4.version() == '2.0')
+assert(prog4.found())
+test('test-prog4', prog4)