From ab68af0fa3a1112f48d35a83752f5f83a351e4ec Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 11 Sep 2023 09:00:58 -0700 Subject: [PATCH] extend override_find_program with native keyword For the most part, what we had before would work correctly for cross building. There is, however a case where this might not work correctly, which is a project for the host machine that builds a build machine target and uses that as an override (think some kind of transpiler), to make this work correctly we need to add a native keyword argument to the `override_find_program` method. --- .../subproject_and_override_program_native.md | 13 +++++++++++++ docs/yaml/builtins/meson.yaml | 11 ++++++++++- docs/yaml/functions/subproject.yaml | 7 +++++++ mesonbuild/interpreter/interpreter.py | 5 ++--- mesonbuild/interpreter/mesonmain.py | 6 +++--- test cases/native/10 native subproject/maingen.c | 8 ++++++++ test cases/native/10 native subproject/meson.build | 2 ++ .../subprojects/buildtool/buildtool.c | 5 ++++- .../subprojects/buildtool/meson.build | 11 ++++++++++- 9 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 docs/markdown/snippets/subproject_and_override_program_native.md create mode 100644 test cases/native/10 native subproject/maingen.c diff --git a/docs/markdown/snippets/subproject_and_override_program_native.md b/docs/markdown/snippets/subproject_and_override_program_native.md new file mode 100644 index 000000000000..8d5e5c9fa87e --- /dev/null +++ b/docs/markdown/snippets/subproject_and_override_program_native.md @@ -0,0 +1,13 @@ +## subproject() and meson.override_find_program() now support the native keyword argument + +Subprojects may now be built for the host or build machine (or both). This means +that build time dependencies can be built for the matching running the build in a +cross compile setup. When a subproject is run for the build machine it will act +just like a normal build == host setup, except that no targets will be installed. + +This necessarily means that `meson.override_find_program()` must differentiate +between programs for the host and those for the build machine, as you may need +two versions of the same program, which have different outputs based on the +machine they are for. For backwards compatibility reasons the default is for the +host machine. Inside a native subproject the host and build machine will both be +the build machine. diff --git a/docs/yaml/builtins/meson.yaml b/docs/yaml/builtins/meson.yaml index 516e41c3d9ae..18da890bc7fe 100644 --- a/docs/yaml/builtins/meson.yaml +++ b/docs/yaml/builtins/meson.yaml @@ -139,7 +139,7 @@ methods: to install only a subset of the files. By default the script has no install tag which means it is not being run when `meson install --tags` argument is specified. - + dry_run: type: bool since: 1.1.0 @@ -392,6 +392,15 @@ methods: type: exe | file | external_program description: The program to set as the override for `progname`. + native: + type: bool + since: 1.3.0 + default: false + description : | + If set to `true`, the override is for the build machine, and will be returned + by `find_program(..., native : true)`, otherwise for the host machine. This + is an important distinction when cross compiling. + - name: override_dependency returns: void since: 0.54.0 diff --git a/docs/yaml/functions/subproject.yaml b/docs/yaml/functions/subproject.yaml index bccac791e6ba..3dbf6d5a5bdf 100644 --- a/docs/yaml/functions/subproject.yaml +++ b/docs/yaml/functions/subproject.yaml @@ -65,3 +65,10 @@ kwargs: default: true description: | Works just the same as in [[dependency]]. + + native: + type: bool + since: 1.3.0 + default: false + description : | + Whether to build this subproject for the host or build machine. diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index ebfd17498c8d..ffa196a4c1dc 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1636,9 +1636,8 @@ def store_name_lookups(self, command_names: T.List[mesonlib.FileOrString], for_m if isinstance(name, str): self.build.searched_programs[for_machine].add(name) - def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram']) -> None: - # XXX: What to do here? We probably need to add an explicit native here... - for_machine = MachineChoice.HOST + def add_find_program_override(self, name: str, exe: T.Union[build.Executable, ExternalProgram, 'OverrideProgram'], + for_machine: MachineChoice = MachineChoice.HOST) -> None: if name in self.build.searched_programs[for_machine]: raise InterpreterException(f'Tried to override finding of executable "{name}" which has already been found.') if name in self.build.find_overrides[for_machine]: diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py index e62a8cd559e4..9f0523a44664 100644 --- a/mesonbuild/interpreter/mesonmain.py +++ b/mesonbuild/interpreter/mesonmain.py @@ -324,8 +324,8 @@ def install_dependency_manifest_method(self, args: T.Tuple[str], kwargs: 'TYPE_k @FeatureNew('meson.override_find_program', '0.46.0') @typed_pos_args('meson.override_find_program', str, (mesonlib.File, ExternalProgram, build.Executable)) - @noKwargs - def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: 'TYPE_kwargs') -> None: + @typed_kwargs('meson.override_find_program', NATIVE_KW.evolve(since='1.3.0')) + def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, ExternalProgram, build.Executable]], kwargs: NativeKW) -> None: name, exe = args if isinstance(exe, mesonlib.File): abspath = exe.absolute_path(self.interpreter.environment.source_dir, @@ -333,7 +333,7 @@ def override_find_program_method(self, args: T.Tuple[str, T.Union[mesonlib.File, if not os.path.exists(abspath): raise InterpreterException(f'Tried to override {name} with a file that does not exist.') exe = OverrideProgram(name, [abspath]) - self.interpreter.add_find_program_override(name, exe) + self.interpreter.add_find_program_override(name, exe, kwargs['native']) @typed_kwargs( 'meson.override_dependency', diff --git a/test cases/native/10 native subproject/maingen.c b/test cases/native/10 native subproject/maingen.c new file mode 100644 index 000000000000..c05cfe553997 --- /dev/null +++ b/test cases/native/10 native subproject/maingen.c @@ -0,0 +1,8 @@ +#include + +int main(void) { + printf("const char * gen_main(void) {\n"); + printf(" return \"int main() \";\n"); + printf("}\n"); + return 0; +} diff --git a/test cases/native/10 native subproject/meson.build b/test cases/native/10 native subproject/meson.build index de878d793353..2745f107bb4b 100644 --- a/test cases/native/10 native subproject/meson.build +++ b/test cases/native/10 native subproject/meson.build @@ -4,6 +4,8 @@ project('native subproject', 'c', meson_version : '>= 1.3.0') subproject('both', native : true) subproject('both', native : false) +maingen = executable('maingen', 'maingen.c', native : true) +meson.override_find_program('maingen', maingen, native : true) gen = subproject('buildtool', native : true).get_variable('e') ct = custom_target( diff --git a/test cases/native/10 native subproject/subprojects/buildtool/buildtool.c b/test cases/native/10 native subproject/subprojects/buildtool/buildtool.c index 579c760a77f2..face28e25f73 100644 --- a/test cases/native/10 native subproject/subprojects/buildtool/buildtool.c +++ b/test cases/native/10 native subproject/subprojects/buildtool/buildtool.c @@ -1,6 +1,9 @@ #include +const char * gen_main(void); + int main() { - printf("int main() { return 0; }\n"); + printf("%s", gen_main()); + printf("{ return 0; }\n"); return 0; } diff --git a/test cases/native/10 native subproject/subprojects/buildtool/meson.build b/test cases/native/10 native subproject/subprojects/buildtool/meson.build index 74bf2826ccf9..1d3b3c999b5f 100644 --- a/test cases/native/10 native subproject/subprojects/buildtool/meson.build +++ b/test cases/native/10 native subproject/subprojects/buildtool/meson.build @@ -1,6 +1,15 @@ project('buildtool', 'c', meson_version : '>= 1.3.0') -e = executable('buildtool', 'buildtool.c') +maingen = find_program('maingen') + +ct = custom_target( + 'gen', + command : [maingen], + output : 'gen.c', + capture : true, +) + +e = executable('buildtool', 'buildtool.c', ct) meson.override_find_program('buildtool', e)