Git fork

meson: distinguish build and target host binaries

Almost all of the tools we discover during the build process need to be
native programs. There are only a handful of exceptions, which typically
are programs whose paths we need to embed into the resulting executable
so that they can be found on the target system when Git executes. While
this distinction typically doesn't matter, it does start to matter when
considering cross-compilation where the build and target machines are
different.

Meson supports cross-compilation via so-called machine files. These
machine files allow the user to override parameters for the build
machine, but also for the target machine when cross-compiling. Part of
the machine file is a section that allows the user to override the
location where binaries are to be found in the target system. The
following machine file would for example override the path of the POSIX
shell:

[binaries]
sh = '/usr/xpg4/bin/sh'

It can be handed over to Meson via `meson setup --cross-file`.

We do not handle this correctly right now though because we don't know
to distinguish binaries for the build and target hosts at all. Address
this by explicitly passing the `native:` parameter to `find_program()`:

- When set to `true`, we get binaries discovered on the build host.

- When set to `false`, we get either the path specified in the
machine file. Or, if no machine file exists or it doesn't specify
the binary path, then we fall back to the binary discovered on the
build host.

As mentioned, only a handful of binaries are not native: only the system
shell, Python and Perl need to be treated specially here.

Reported-by: Peter Seiderer <ps.report@gmx.net>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
23633466 bdd04b91

+60 -24
+6 -6
Documentation/meson.build
··· 207 207 208 208 docs_backend = get_option('docs_backend') 209 209 if docs_backend == 'auto' 210 - if find_program('asciidoc', dirs: program_path, required: false).found() 210 + if find_program('asciidoc', dirs: program_path, native: true, required: false).found() 211 211 docs_backend = 'asciidoc' 212 - elif find_program('asciidoctor', dirs: program_path, required: false).found() 212 + elif find_program('asciidoctor', dirs: program_path, native: true, required: false).found() 213 213 docs_backend = 'asciidoctor' 214 214 else 215 215 error('Neither asciidoc nor asciidoctor were found.') ··· 217 217 endif 218 218 219 219 if docs_backend == 'asciidoc' 220 - asciidoc = find_program('asciidoc', dirs: program_path) 220 + asciidoc = find_program('asciidoc', dirs: program_path, native: true) 221 221 asciidoc_html = 'xhtml11' 222 222 asciidoc_docbook = 'docbook' 223 223 xmlto_extra = [ ] ··· 246 246 asciidoc_conf, 247 247 ] 248 248 elif docs_backend == 'asciidoctor' 249 - asciidoctor = find_program('asciidoctor', dirs: program_path) 249 + asciidoctor = find_program('asciidoctor', dirs: program_path, native: true) 250 250 asciidoc_html = 'xhtml5' 251 251 asciidoc_docbook = 'docbook5' 252 252 xmlto_extra = [ ··· 288 288 asciidoc_common_options += ['--attribute', 'with-breaking-changes'] 289 289 endif 290 290 291 - xmlto = find_program('xmlto', dirs: program_path) 291 + xmlto = find_program('xmlto', dirs: program_path, native: true) 292 292 293 293 cmd_lists = [ 294 294 'cmds-ancillaryinterrogators.adoc', ··· 409 409 pointing_to: 'git.html', 410 410 ) 411 411 412 - xsltproc = find_program('xsltproc', dirs: program_path) 412 + xsltproc = find_program('xsltproc', dirs: program_path, native: true) 413 413 414 414 user_manual_xml = custom_target( 415 415 command: asciidoc_common_options + [
+1 -1
gitweb/meson.build
··· 1 1 gitweb_config = configuration_data() 2 - gitweb_config.set_quoted('PERL_PATH', perl.full_path()) 2 + gitweb_config.set_quoted('PERL_PATH', target_perl.full_path()) 3 3 gitweb_config.set_quoted('CSSMIN', '') 4 4 gitweb_config.set_quoted('JSMIN', '') 5 5 gitweb_config.set_quoted('GIT_BINDIR', get_option('prefix') / get_option('bindir'))
+51 -15
meson.build
··· 155 155 # These machine files can be passed to `meson setup` via the `--native-file` 156 156 # option. 157 157 # 158 + # Cross compilation 159 + # ================= 160 + # 161 + # Machine files can also be used in the context of cross-compilation to 162 + # describe the target machine as well as the cross-compiler toolchain that 163 + # shall be used. An example machine file could look like the following: 164 + # 165 + # [binaries] 166 + # c = 'x86_64-w64-mingw32-gcc' 167 + # cpp = 'x86_64-w64-mingw32-g++' 168 + # ar = 'x86_64-w64-mingw32-ar' 169 + # windres = 'x86_64-w64-mingw32-windres' 170 + # strip = 'x86_64-w64-mingw32-strip' 171 + # exe_wrapper = 'wine64' 172 + # sh = 'C:/Program Files/Git for Windows/usr/bin/sh.exe' 173 + # 174 + # [host_machine] 175 + # system = 'windows' 176 + # cpu_family = 'x86_64' 177 + # cpu = 'x86_64' 178 + # endian = 'little' 179 + # 180 + # These machine files can be passed to `meson setup` via the `--cross-file` 181 + # option. 182 + # 183 + # Note that next to the cross-compiler toolchain, the `[binaries]` section is 184 + # also used to locate a couple of binaries that will be built into Git. This 185 + # includes `sh`, `python` and `perl`, so when cross-compiling Git you likely 186 + # want to set these binary paths in addition to the cross-compiler toolchain 187 + # binaries. 188 + # 158 189 # Subproject wrappers 159 190 # =================== 160 191 # ··· 173 204 # The version is only of cosmetic nature, so if we cannot find a shell yet we 174 205 # simply don't set up a version at all. This may be the case for example on 175 206 # Windows systems, where we first have to bootstrap the host environment. 176 - version: find_program('sh', required: false).found() ? run_command( 207 + version: find_program('sh', native: true, required: false).found() ? run_command( 177 208 'GIT-VERSION-GEN', meson.current_source_dir(), '--format=@GIT_VERSION@', 178 209 capture: true, 179 210 check: true, ··· 198 229 program_path = [ 'C:/Program Files/Git/bin', 'C:/Program Files/Git/usr/bin' ] 199 230 endif 200 231 201 - cygpath = find_program('cygpath', dirs: program_path, required: false) 202 - diff = find_program('diff', dirs: program_path) 203 - git = find_program('git', dirs: program_path, required: false) 204 - sed = find_program('sed', dirs: program_path) 205 - shell = find_program('sh', dirs: program_path) 206 - tar = find_program('tar', dirs: program_path) 232 + cygpath = find_program('cygpath', dirs: program_path, native: true, required: false) 233 + diff = find_program('diff', dirs: program_path, native: true) 234 + git = find_program('git', dirs: program_path, native: true, required: false) 235 + sed = find_program('sed', dirs: program_path, native: true) 236 + shell = find_program('sh', dirs: program_path, native: true) 237 + tar = find_program('tar', dirs: program_path, native: true) 238 + 239 + target_shell = find_program('sh', dirs: program_path, native: false) 207 240 208 241 # Sanity-check that programs required for the build exist. 209 242 foreach tool : ['cat', 'cut', 'grep', 'sort', 'tr', 'uname'] 210 - find_program(tool, dirs: program_path) 243 + find_program(tool, dirs: program_path, native: true) 211 244 endforeach 212 245 213 246 script_environment = environment() ··· 706 739 '-DGIT_LOCALE_PATH="' + get_option('localedir') + '"', 707 740 '-DGIT_MAN_PATH="' + get_option('mandir') + '"', 708 741 '-DPAGER_ENV="' + get_option('pager_environment') + '"', 709 - '-DSHELL_PATH="' + fs.as_posix(shell.full_path()) + '"', 742 + '-DSHELL_PATH="' + fs.as_posix(target_shell.full_path()) + '"', 710 743 ] 711 744 libgit_include_directories = [ '.' ] 712 745 libgit_dependencies = [ ] ··· 761 794 build_options_config.set_quoted('X', executable_suffix) 762 795 763 796 python = import('python').find_installation('python3', required: get_option('python')) 797 + target_python = find_program('python3', native: false, required: python.found()) 764 798 if python.found() 765 799 build_options_config.set('NO_PYTHON', '') 766 800 else ··· 790 824 # which we can do starting with Meson 1.5.0 and newer, or we have to 791 825 # match against the minor version. 792 826 if meson.version().version_compare('>=1.5.0') 793 - perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') 827 + perl = find_program('perl', dirs: program_path, native: true, required: perl_required, version: '>=5.26.0', version_argument: '-V:version') 828 + target_perl = find_program('perl', dirs: program_path, native: false, required: perl.found(), version: '>=5.26.0', version_argument: '-V:version') 794 829 else 795 - perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=26') 830 + perl = find_program('perl', dirs: program_path, native: true, required: perl_required, version: '>=26') 831 + target_perl = find_program('perl', dirs: program_path, native: false, required: perl.found(), version: '>=26') 796 832 endif 797 833 perl_features_enabled = perl.found() and get_option('perl').allowed() 798 834 if perl_features_enabled ··· 843 879 build_options_config.set('NO_PTHREADS', '1') 844 880 endif 845 881 846 - msgfmt = find_program('msgfmt', dirs: program_path, required: false) 882 + msgfmt = find_program('msgfmt', dirs: program_path, native: true, required: false) 847 883 gettext_option = get_option('gettext').disable_auto_if(not msgfmt.found()) 848 884 if not msgfmt.found() and gettext_option.enabled() 849 885 error('Internationalization via libintl requires msgfmt') ··· 1974 2010 'GIT_TEST_TEMPLATE_DIR': meson.project_build_root() / 'templates', 1975 2011 'GIT_TEST_TEXTDOMAINDIR': meson.project_build_root() / 'po', 1976 2012 'PAGER_ENV': get_option('pager_environment'), 1977 - 'PERL_PATH': perl.found() ? perl.full_path() : '', 1978 - 'PYTHON_PATH': python.found () ? python.full_path() : '', 1979 - 'SHELL_PATH': shell.full_path(), 2013 + 'PERL_PATH': target_perl.found() ? target_perl.full_path() : '', 2014 + 'PYTHON_PATH': target_python.found () ? target_python.full_path() : '', 2015 + 'SHELL_PATH': target_shell.full_path(), 1980 2016 'TAR': tar.full_path(), 1981 2017 'TEST_OUTPUT_DIRECTORY': test_output_directory, 1982 2018 'TEST_SHELL_PATH': shell.full_path(),
+2 -2
templates/meson.build
··· 1 1 template_config = configuration_data() 2 - template_config.set('PERL_PATH', perl.found() ? fs.as_posix(perl.full_path()) : '') 3 - template_config.set('SHELL_PATH', fs.as_posix(shell.full_path())) 2 + template_config.set('PERL_PATH', target_perl.found() ? fs.as_posix(target_perl.full_path()) : '') 3 + template_config.set('SHELL_PATH', fs.as_posix(target_shell.full_path())) 4 4 template_config.set('GITWEBDIR', fs.as_posix(get_option('prefix') / get_option('datadir') / 'gitweb')) 5 5 6 6 configure_file(