compilers: introduce common helper for sanity checks

Avoid reinventing the wheel and instead use a single helper, taking care
of logging and cross compilation.

Fixes: #14373
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2025-03-25 02:23:42 +01:00 committed by Jussi Pakkanen
parent 8909a09d2a
commit 8e564f16ae
8 changed files with 31 additions and 69 deletions

View File

@ -1200,6 +1200,23 @@ class Compiler(HoldableObject, metaclass=abc.ABCMeta):
is good enough here.
"""
def run_sanity_check(self, environment: Environment, cmdlist: T.List[str], work_dir: str, use_exe_wrapper_for_cross: bool = True) -> T.Tuple[str, str]:
# Run sanity check
if self.is_cross and use_exe_wrapper_for_cross:
if not environment.has_exe_wrapper():
# Can't check if the binaries run so we have to assume they do
return ('', '')
cmdlist = environment.exe_wrapper.get_command() + cmdlist
mlog.debug('Running test binary command: ', mesonlib.join_args(cmdlist))
try:
pe, stdo, stde = Popen_safe_logged(cmdlist, 'Sanity check', cwd=work_dir)
except Exception as e:
raise mesonlib.EnvironmentException(f'Could not invoke sanity check executable: {e!s}.')
if pe.returncode != 0:
raise mesonlib.EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.')
return stdo, stde
def split_shlib_to_parts(self, fname: str) -> T.Tuple[T.Optional[str], str]:
return None, fname

View File

@ -102,10 +102,7 @@ class CsCompiler(BasicLinkerIsCompilerMixin, Compiler):
cmdlist = [self.runner, obj]
else:
cmdlist = [os.path.join(work_dir, obj)]
pe = subprocess.Popen(cmdlist, cwd=work_dir)
pe.wait()
if pe.returncode != 0:
raise EnvironmentException('Executables created by Mono compiler %s are not runnable.' % self.name_string())
self.run_sanity_check(environment, cmdlist, work_dir, use_exe_wrapper_for_cross=False)
def needs_static_linker(self) -> bool:
return False

View File

@ -577,21 +577,12 @@ class CudaCompiler(Compiler):
# Run sanity check (if possible)
if self.is_cross:
if not env.has_exe_wrapper():
return
else:
cmdlist = env.exe_wrapper.get_command() + [binary_name]
else:
cmdlist = self.exelist + ['--run', '"' + binary_name + '"']
mlog.debug('Sanity check run command line: ', ' '.join(cmdlist))
pe, stdo, stde = Popen_safe(cmdlist, cwd=work_dir)
mlog.debug('Sanity check run stdout: ')
mlog.debug(stdo)
mlog.debug('-----\nSanity check run stderr:')
mlog.debug(stde)
mlog.debug('-----')
pe.wait()
if pe.returncode != 0:
return
cmdlist = self.exelist + ['--run', f'"{binary_name}"']
try:
stdo, stde = self.run_sanity_check(env, cmdlist, work_dir)
except EnvironmentException:
raise EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.')
# Interpret the result of the sanity test.
@ -599,8 +590,6 @@ class CudaCompiler(Compiler):
# architecture detection test.
if stde == '':
self.detected_cc = stdo
else:
mlog.debug('cudaGetDeviceCount() returned ' + stde)
def has_header_symbol(self, hname: str, symbol: str, prefix: str,
env: 'Environment', *,

View File

@ -456,15 +456,7 @@ class DCompiler(Compiler):
if pc.returncode != 0:
raise EnvironmentException('D compiler %s cannot compile programs.' % self.name_string())
if self.is_cross:
if not environment.has_exe_wrapper():
# Can't check if the binaries run so we have to assume they do
return
cmdlist = environment.exe_wrapper.get_command() + [output_name]
else:
cmdlist = [output_name]
if subprocess.call(cmdlist) != 0:
raise EnvironmentException('Executables created by D compiler %s are not runnable.' % self.name_string())
stdo, stde = self.run_sanity_check(environment, [output_name], work_dir)
def needs_static_linker(self) -> bool:
return True

View File

@ -91,10 +91,7 @@ class JavaCompiler(BasicLinkerIsCompilerMixin, Compiler):
runner = shutil.which(self.javarunner)
if runner:
cmdlist = [runner, '-cp', '.', obj]
pe = subprocess.Popen(cmdlist, cwd=work_dir)
pe.wait()
if pe.returncode != 0:
raise EnvironmentException(f'Executables created by Java compiler {self.name_string()} are not runnable.')
self.run_sanity_check(environment, cmdlist, work_dir, use_exe_wrapper_for_cross=False)
else:
m = "Java Virtual Machine wasn't found, but it's needed by Meson. " \
"Please install a JRE.\nIf you have specific needs where this " \

View File

@ -307,21 +307,7 @@ class CLikeCompiler(Compiler):
mlog.debug('-----')
if pc.returncode != 0:
raise mesonlib.EnvironmentException(f'Compiler {self.name_string()} cannot compile programs.')
# Run sanity check
if self.is_cross:
if not environment.has_exe_wrapper():
# Can't check if the binaries run so we have to assume they do
return
cmdlist = environment.exe_wrapper.get_command() + [binary_name]
else:
cmdlist = [binary_name]
mlog.debug('Running test binary command: ', mesonlib.join_args(cmdlist))
try:
pe, _, _ = Popen_safe_logged(cmdlist, 'Sanity check', cwd=work_dir)
except Exception as e:
raise mesonlib.EnvironmentException(f'Could not invoke sanity test executable: {e!s}.')
if pe.returncode != 0:
raise mesonlib.EnvironmentException(f'Executables created by {self.language} compiler {self.name_string()} are not runnable.')
self.run_sanity_check(environment, [binary_name], work_dir)
def sanity_check(self, work_dir: str, environment: 'Environment') -> None:
code = 'int main(void) { int class=0; return class; }\n'

View File

@ -5,7 +5,7 @@
from __future__ import annotations
import functools
import subprocess, os.path
import os.path
import textwrap
import re
import typing as T
@ -141,17 +141,7 @@ class RustCompiler(Compiler):
if pc.returncode != 0:
raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.')
self._native_static_libs(work_dir, source_name)
if self.is_cross:
if not environment.has_exe_wrapper():
# Can't check if the binaries run so we have to assume they do
return
cmdlist = environment.exe_wrapper.get_command() + [output_name]
else:
cmdlist = [output_name]
pe = subprocess.Popen(cmdlist, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
pe.wait()
if pe.returncode != 0:
raise EnvironmentException(f'Executables created by Rust compiler {self.name_string()} are not runnable.')
self.run_sanity_check(environment, [output_name], work_dir)
def _native_static_libs(self, work_dir: str, source_name: str) -> None:
# Get libraries needed to link with a Rust staticlib

View File

@ -8,7 +8,7 @@ import subprocess, os.path
import typing as T
from .. import mlog, options
from ..mesonlib import EnvironmentException, MesonException, version_compare
from ..mesonlib import MesonException, version_compare
from .compilers import Compiler, clike_debug_args
@ -170,13 +170,7 @@ class SwiftCompiler(Compiler):
''')
pc = subprocess.Popen(self.exelist + extra_flags + ['-emit-executable', '-o', output_name, src], cwd=work_dir)
pc.wait()
if pc.returncode != 0:
raise EnvironmentException('Swift compiler %s cannot compile programs.' % self.name_string())
if self.is_cross:
# Can't check if the binaries run so we have to assume they do
return
if subprocess.call(output_name) != 0:
raise EnvironmentException('Executables created by Swift compiler %s are not runnable.' % self.name_string())
self.run_sanity_check(environment, [output_name], work_dir)
def get_debug_args(self, is_debug: bool) -> T.List[str]:
return clike_debug_args[is_debug]