diff options
| -rw-r--r-- | mesonbuild/compilers/detect.py | 6 | ||||
| -rw-r--r-- | mesonbuild/dependencies/mpi.py | 2 | ||||
| -rw-r--r-- | mesonbuild/dependencies/python.py | 2 | ||||
| -rw-r--r-- | mesonbuild/dependencies/ui.py | 2 | ||||
| -rw-r--r-- | mesonbuild/envconfig.py | 263 | ||||
| -rw-r--r-- | mesonbuild/environment.py | 259 | ||||
| -rw-r--r-- | mesonbuild/interpreter/interpreter.py | 2 | ||||
| -rwxr-xr-x | run_tests.py | 3 | ||||
| -rw-r--r-- | unittests/allplatformstests.py | 16 | ||||
| -rw-r--r-- | unittests/datatests.py | 2 | ||||
| -rw-r--r-- | unittests/internaltests.py | 36 | ||||
| -rw-r--r-- | unittests/machinefiletests.py | 2 |
12 files changed, 300 insertions, 295 deletions
diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index 7300fa366..979b9ce60 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -8,7 +8,7 @@ from ..mesonlib import ( search_version, is_windows, Popen_safe, Popen_safe_logged, version_compare, windows_proof_rm, ) from ..programs import ExternalProgram -from ..envconfig import BinaryTable +from ..envconfig import BinaryTable, detect_cpu_family, detect_machine_info from .. import mlog from ..linkers import guess_win_linker, guess_nix_linker @@ -1172,8 +1172,6 @@ def detect_d_compiler(env: 'Environment', for_machine: MachineChoice) -> Compile if not is_msvc: c_compiler = {} - # Import here to avoid circular imports - from ..environment import detect_cpu_family arch = detect_cpu_family(c_compiler) if is_msvc and arch == 'x86': arch = 'x86_mscoff' @@ -1317,7 +1315,6 @@ def detect_nasm_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp # We need a C compiler to properly detect the machine info and linker cc = detect_c_compiler(env, for_machine) if not is_cross: - from ..environment import detect_machine_info info = detect_machine_info({'c': cc}) else: info = env.machines[for_machine] @@ -1362,7 +1359,6 @@ def detect_masm_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp is_cross = env.is_cross_build(for_machine) cc = detect_c_compiler(env, for_machine) if not is_cross: - from ..environment import detect_machine_info info = detect_machine_info({'c': cc}) else: info = env.machines[for_machine] diff --git a/mesonbuild/dependencies/mpi.py b/mesonbuild/dependencies/mpi.py index 074dafde3..1eae1a493 100644 --- a/mesonbuild/dependencies/mpi.py +++ b/mesonbuild/dependencies/mpi.py @@ -8,7 +8,7 @@ import typing as T import os import re -from ..environment import detect_cpu_family +from ..envconfig import detect_cpu_family from ..mesonlib import Popen_safe from .base import DependencyException, DependencyMethods, detect_compiler, SystemDependency from .configtool import ConfigToolDependency diff --git a/mesonbuild/dependencies/python.py b/mesonbuild/dependencies/python.py index 707e07499..c204a5197 100644 --- a/mesonbuild/dependencies/python.py +++ b/mesonbuild/dependencies/python.py @@ -14,7 +14,7 @@ from .detect import packages from .factory import DependencyFactory from .framework import ExtraFrameworkDependency from .pkgconfig import PkgConfigDependency -from ..environment import detect_cpu_family +from ..envconfig import detect_cpu_family from ..programs import ExternalProgram from ..options import OptionKey diff --git a/mesonbuild/dependencies/ui.py b/mesonbuild/dependencies/ui.py index 29e65ea3d..de2a4cf36 100644 --- a/mesonbuild/dependencies/ui.py +++ b/mesonbuild/dependencies/ui.py @@ -15,7 +15,7 @@ from .. import mesonlib from ..mesonlib import ( Popen_safe, version_compare_many ) -from ..environment import detect_cpu_family +from ..envconfig import detect_cpu_family from .base import DependencyException, DependencyMethods, DependencyTypeName, SystemDependency from .configtool import ConfigToolDependency diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index f50578905..f4616ac14 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -6,15 +6,20 @@ from __future__ import annotations from dataclasses import dataclass import typing as T from enum import Enum +import os +import platform +import sys from . import mesonlib -from .mesonlib import EnvironmentException, HoldableObject +from .mesonlib import EnvironmentException, HoldableObject, Popen_safe from .programs import ExternalProgram from . import mlog from pathlib import Path if T.TYPE_CHECKING: from .options import ElementaryOptionValues + from .compilers import Compiler + from .compilers.mixins.visualstudio import VisualStudioLikeCompiler # These classes contains all the data pulled from configuration files (native @@ -483,3 +488,259 @@ class CMakeVariables: def get_variables(self) -> T.Dict[str, T.List[str]]: return self.variables + + +# Machine and platform detection functions +# ======================================== + +KERNEL_MAPPINGS: T.Mapping[str, str] = {'freebsd': 'freebsd', + 'openbsd': 'openbsd', + 'netbsd': 'netbsd', + 'windows': 'nt', + 'android': 'linux', + 'linux': 'linux', + 'cygwin': 'nt', + 'darwin': 'xnu', + 'ios': 'xnu', + 'tvos': 'xnu', + 'visionos': 'xnu', + 'watchos': 'xnu', + 'dragonfly': 'dragonfly', + 'haiku': 'haiku', + 'gnu': 'gnu', + } + +def detect_windows_arch(compilers: T.Dict[str, Compiler]) -> str: + """ + Detecting the 'native' architecture of Windows is not a trivial task. We + cannot trust that the architecture that Python is built for is the 'native' + one because you can run 32-bit apps on 64-bit Windows using WOW64 and + people sometimes install 32-bit Python on 64-bit Windows. + + We also can't rely on the architecture of the OS itself, since it's + perfectly normal to compile and run 32-bit applications on Windows as if + they were native applications. It's a terrible experience to require the + user to supply a cross-info file to compile 32-bit applications on 64-bit + Windows. Thankfully, the only way to compile things with Visual Studio on + Windows is by entering the 'msvc toolchain' environment, which can be + easily detected. + + In the end, the sanest method is as follows: + 1. Check environment variables that are set by Windows and WOW64 to find out + if this is x86 (possibly in WOW64), if so use that as our 'native' + architecture. + 2. If the compiler toolchain target architecture is x86, use that as our + 'native' architecture. + 3. Otherwise, use the actual Windows architecture + + """ + os_arch = mesonlib.windows_detect_native_arch() + if os_arch == 'x86': + return os_arch + # If we're on 64-bit Windows, 32-bit apps can be compiled without + # cross-compilation. So if we're doing that, just set the native arch as + # 32-bit and pretend like we're running under WOW64. Else, return the + # actual Windows architecture that we deduced above. + for compiler in compilers.values(): + compiler = T.cast('VisualStudioLikeCompiler', compiler) + if compiler.id == 'msvc' and (compiler.target in {'x86', '80x86'}): + return 'x86' + if compiler.id == 'clang-cl' and (compiler.target in {'x86', 'i686'}): + return 'x86' + if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'): + return 'x86' + return os_arch + +def any_compiler_has_define(compilers: T.Dict[str, Compiler], define: str) -> bool: + for c in compilers.values(): + try: + if c.has_builtin_define(define): + return True + except mesonlib.MesonException: + # Ignore compilers that do not support has_builtin_define. + pass + return False + +def detect_cpu_family(compilers: T.Dict[str, Compiler]) -> str: + """ + Python is inconsistent in its platform module. + It returns different values for the same cpu. + For x86 it might return 'x86', 'i686' or some such. + Do some canonicalization. + """ + if mesonlib.is_windows(): + trial = detect_windows_arch(compilers) + elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_qnx() or mesonlib.is_aix(): + trial = platform.processor().lower() + else: + trial = platform.machine().lower() + if trial.startswith('i') and trial.endswith('86'): + trial = 'x86' + elif trial == 'bepc': + trial = 'x86' + elif trial == 'arm64': + trial = 'aarch64' + elif trial.startswith('aarch64'): + # This can be `aarch64_be` + trial = 'aarch64' + elif trial.startswith('arm') or trial.startswith('earm'): + trial = 'arm' + elif trial.startswith(('powerpc64', 'ppc64')): + trial = 'ppc64' + elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power macintosh'}: + trial = 'ppc' + elif trial in {'amd64', 'x64', 'i86pc'}: + trial = 'x86_64' + elif trial in {'sun4u', 'sun4v'}: + trial = 'sparc64' + elif trial.startswith('mips'): + if '64' not in trial: + trial = 'mips' + else: + trial = 'mips64' + elif trial in {'ip30', 'ip35'}: + trial = 'mips64' + + # On Linux (and maybe others) there can be any mixture of 32/64 bit code in + # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only + # reliable way to know is to check the compiler defines. + if trial == 'x86_64': + if any_compiler_has_define(compilers, '__i386__'): + trial = 'x86' + elif trial == 'aarch64': + if any_compiler_has_define(compilers, '__arm__'): + trial = 'arm' + # Add more quirks here as bugs are reported. Keep in sync with detect_cpu() + # below. + elif trial == 'parisc64': + # ATM there is no 64 bit userland for PA-RISC. Thus always + # report it as 32 bit for simplicity. + trial = 'parisc' + elif trial == 'ppc': + # AIX always returns powerpc, check here for 64-bit + if any_compiler_has_define(compilers, '__64BIT__'): + trial = 'ppc64' + # MIPS64 is able to run MIPS32 code natively, so there is a chance that + # such mixture mentioned above exists. + elif trial == 'mips64': + if compilers and not any_compiler_has_define(compilers, '__mips64'): + trial = 'mips' + + if trial not in known_cpu_families: + mlog.warning(f'Unknown CPU family {trial!r}, please report this at ' + 'https://github.com/mesonbuild/meson/issues/new with the ' + 'output of `uname -a` and `cat /proc/cpuinfo`') + + return trial + +def detect_cpu(compilers: T.Dict[str, Compiler]) -> str: + if mesonlib.is_windows(): + trial = detect_windows_arch(compilers) + elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix(): + trial = platform.processor().lower() + else: + trial = platform.machine().lower() + + if trial in {'amd64', 'x64', 'i86pc'}: + trial = 'x86_64' + if trial == 'x86_64': + # Same check as above for cpu_family + if any_compiler_has_define(compilers, '__i386__'): + trial = 'i686' # All 64 bit cpus have at least this level of x86 support. + elif trial.startswith('aarch64') or trial.startswith('arm64'): + # Same check as above for cpu_family + if any_compiler_has_define(compilers, '__arm__'): + trial = 'arm' + else: + # for aarch64_be + trial = 'aarch64' + elif trial.startswith('earm'): + trial = 'arm' + elif trial == 'e2k': + # Make more precise CPU detection for Elbrus platform. + trial = platform.processor().lower() + elif trial.startswith('mips'): + if '64' not in trial: + trial = 'mips' + else: + if compilers and not any_compiler_has_define(compilers, '__mips64'): + trial = 'mips' + else: + trial = 'mips64' + elif trial == 'ppc': + # AIX always returns powerpc, check here for 64-bit + if any_compiler_has_define(compilers, '__64BIT__'): + trial = 'ppc64' + + # Add more quirks here as bugs are reported. Keep in sync with + # detect_cpu_family() above. + return trial + +def detect_kernel(system: str) -> T.Optional[str]: + if system == 'sunos': + # Solaris 5.10 uname doesn't support the -o switch, and illumos started + # with version 5.11 so shortcut the logic to report 'solaris' in such + # cases where the version is 5.10 or below. + if mesonlib.version_compare(platform.uname().release, '<=5.10'): + return 'solaris' + # This needs to be /usr/bin/uname because gnu-uname could be installed and + # won't provide the necessary information + p, out, _ = Popen_safe(['/usr/bin/uname', '-o']) + if p.returncode != 0: + raise mesonlib.MesonException('Failed to run "/usr/bin/uname -o"') + out = out.lower().strip() + if out not in {'illumos', 'solaris'}: + mlog.warning(f'Got an unexpected value for kernel on a SunOS derived platform, expected either "illumos" or "solaris", but got "{out}".' + "Please open a Meson issue with the OS you're running and the value detected for your kernel.") + return None + return out + return KERNEL_MAPPINGS.get(system, None) + +def detect_subsystem(system: str) -> T.Optional[str]: + if system == 'darwin': + return 'macos' + return system + +def detect_system() -> str: + if sys.platform == 'cygwin': + return 'cygwin' + return platform.system().lower() + +def detect_msys2_arch() -> T.Optional[str]: + return os.environ.get('MSYSTEM_CARCH', None) + +def detect_machine_info(compilers: T.Optional[T.Dict[str, Compiler]] = None) -> MachineInfo: + """Detect the machine we're running on + + If compilers are not provided, we cannot know as much. None out those + fields to avoid accidentally depending on partial knowledge. The + underlying ''detect_*'' method can be called to explicitly use the + partial information. + """ + system = detect_system() + return MachineInfo( + system, + detect_cpu_family(compilers) if compilers is not None else None, + detect_cpu(compilers) if compilers is not None else None, + sys.byteorder, + detect_kernel(system), + detect_subsystem(system)) + +# TODO make this compare two `MachineInfo`s purely. How important is the +# `detect_cpu_family({})` distinction? It is the one impediment to that. +def machine_info_can_run(machine_info: MachineInfo) -> bool: + """Whether we can run binaries for this machine on the current machine. + + Can almost always run 32-bit binaries on 64-bit natively if the host + and build systems are the same. We don't pass any compilers to + detect_cpu_family() here because we always want to know the OS + architecture, not what the compiler environment tells us. + """ + if machine_info.system != detect_system(): + return False + true_build_cpu_family = detect_cpu_family({}) + assert machine_info.cpu_family is not None, 'called on incomplete machine_info' + return \ + (machine_info.cpu_family == true_build_cpu_family) or \ + ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \ + ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 970f012b0..4d89c88ef 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -5,7 +5,7 @@ from __future__ import annotations import itertools -import os, platform, re, sys, shutil +import os, re, shutil import typing as T import collections @@ -25,7 +25,8 @@ from . import mlog from .programs import ExternalProgram from .envconfig import ( - BinaryTable, MachineInfo, Properties, known_cpu_families, CMakeVariables, + BinaryTable, MachineInfo, Properties, CMakeVariables, + detect_machine_info, machine_info_can_run ) from . import compilers @@ -33,12 +34,9 @@ from mesonbuild import envconfig if T.TYPE_CHECKING: from .compilers import Compiler - from .compilers.mixins.visualstudio import VisualStudioLikeCompiler from .options import OptionDict, ElementaryOptionValues from .wrap.wrap import Resolver - CompilersDict = T.Dict[str, Compiler] - NON_LANG_ENV_OPTIONS = [ ('PKG_CONFIG_PATH', 'pkg_config_path'), @@ -312,257 +310,6 @@ def detect_clangapply() -> T.List[str]: return [path] return [] -def detect_windows_arch(compilers: CompilersDict) -> str: - """ - Detecting the 'native' architecture of Windows is not a trivial task. We - cannot trust that the architecture that Python is built for is the 'native' - one because you can run 32-bit apps on 64-bit Windows using WOW64 and - people sometimes install 32-bit Python on 64-bit Windows. - - We also can't rely on the architecture of the OS itself, since it's - perfectly normal to compile and run 32-bit applications on Windows as if - they were native applications. It's a terrible experience to require the - user to supply a cross-info file to compile 32-bit applications on 64-bit - Windows. Thankfully, the only way to compile things with Visual Studio on - Windows is by entering the 'msvc toolchain' environment, which can be - easily detected. - - In the end, the sanest method is as follows: - 1. Check environment variables that are set by Windows and WOW64 to find out - if this is x86 (possibly in WOW64), if so use that as our 'native' - architecture. - 2. If the compiler toolchain target architecture is x86, use that as our - 'native' architecture. - 3. Otherwise, use the actual Windows architecture - - """ - os_arch = mesonlib.windows_detect_native_arch() - if os_arch == 'x86': - return os_arch - # If we're on 64-bit Windows, 32-bit apps can be compiled without - # cross-compilation. So if we're doing that, just set the native arch as - # 32-bit and pretend like we're running under WOW64. Else, return the - # actual Windows architecture that we deduced above. - for compiler in compilers.values(): - compiler = T.cast('VisualStudioLikeCompiler', compiler) - if compiler.id == 'msvc' and (compiler.target in {'x86', '80x86'}): - return 'x86' - if compiler.id == 'clang-cl' and (compiler.target in {'x86', 'i686'}): - return 'x86' - if compiler.id == 'gcc' and compiler.has_builtin_define('__i386__'): - return 'x86' - return os_arch - -def any_compiler_has_define(compilers: CompilersDict, define: str) -> bool: - for c in compilers.values(): - try: - if c.has_builtin_define(define): - return True - except mesonlib.MesonException: - # Ignore compilers that do not support has_builtin_define. - pass - return False - -def detect_cpu_family(compilers: CompilersDict) -> str: - """ - Python is inconsistent in its platform module. - It returns different values for the same cpu. - For x86 it might return 'x86', 'i686' or some such. - Do some canonicalization. - """ - if mesonlib.is_windows(): - trial = detect_windows_arch(compilers) - elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_qnx() or mesonlib.is_aix(): - trial = platform.processor().lower() - else: - trial = platform.machine().lower() - if trial.startswith('i') and trial.endswith('86'): - trial = 'x86' - elif trial == 'bepc': - trial = 'x86' - elif trial == 'arm64': - trial = 'aarch64' - elif trial.startswith('aarch64'): - # This can be `aarch64_be` - trial = 'aarch64' - elif trial.startswith('arm') or trial.startswith('earm'): - trial = 'arm' - elif trial.startswith(('powerpc64', 'ppc64')): - trial = 'ppc64' - elif trial.startswith(('powerpc', 'ppc')) or trial in {'macppc', 'power macintosh'}: - trial = 'ppc' - elif trial in {'amd64', 'x64', 'i86pc'}: - trial = 'x86_64' - elif trial in {'sun4u', 'sun4v'}: - trial = 'sparc64' - elif trial.startswith('mips'): - if '64' not in trial: - trial = 'mips' - else: - trial = 'mips64' - elif trial in {'ip30', 'ip35'}: - trial = 'mips64' - - # On Linux (and maybe others) there can be any mixture of 32/64 bit code in - # the kernel, Python, system, 32-bit chroot on 64-bit host, etc. The only - # reliable way to know is to check the compiler defines. - if trial == 'x86_64': - if any_compiler_has_define(compilers, '__i386__'): - trial = 'x86' - elif trial == 'aarch64': - if any_compiler_has_define(compilers, '__arm__'): - trial = 'arm' - # Add more quirks here as bugs are reported. Keep in sync with detect_cpu() - # below. - elif trial == 'parisc64': - # ATM there is no 64 bit userland for PA-RISC. Thus always - # report it as 32 bit for simplicity. - trial = 'parisc' - elif trial == 'ppc': - # AIX always returns powerpc, check here for 64-bit - if any_compiler_has_define(compilers, '__64BIT__'): - trial = 'ppc64' - # MIPS64 is able to run MIPS32 code natively, so there is a chance that - # such mixture mentioned above exists. - elif trial == 'mips64': - if compilers and not any_compiler_has_define(compilers, '__mips64'): - trial = 'mips' - - if trial not in known_cpu_families: - mlog.warning(f'Unknown CPU family {trial!r}, please report this at ' - 'https://github.com/mesonbuild/meson/issues/new with the ' - 'output of `uname -a` and `cat /proc/cpuinfo`') - - return trial - -def detect_cpu(compilers: CompilersDict) -> str: - if mesonlib.is_windows(): - trial = detect_windows_arch(compilers) - elif mesonlib.is_freebsd() or mesonlib.is_netbsd() or mesonlib.is_openbsd() or mesonlib.is_aix(): - trial = platform.processor().lower() - else: - trial = platform.machine().lower() - - if trial in {'amd64', 'x64', 'i86pc'}: - trial = 'x86_64' - if trial == 'x86_64': - # Same check as above for cpu_family - if any_compiler_has_define(compilers, '__i386__'): - trial = 'i686' # All 64 bit cpus have at least this level of x86 support. - elif trial.startswith('aarch64') or trial.startswith('arm64'): - # Same check as above for cpu_family - if any_compiler_has_define(compilers, '__arm__'): - trial = 'arm' - else: - # for aarch64_be - trial = 'aarch64' - elif trial.startswith('earm'): - trial = 'arm' - elif trial == 'e2k': - # Make more precise CPU detection for Elbrus platform. - trial = platform.processor().lower() - elif trial.startswith('mips'): - if '64' not in trial: - trial = 'mips' - else: - if compilers and not any_compiler_has_define(compilers, '__mips64'): - trial = 'mips' - else: - trial = 'mips64' - elif trial == 'ppc': - # AIX always returns powerpc, check here for 64-bit - if any_compiler_has_define(compilers, '__64BIT__'): - trial = 'ppc64' - - # Add more quirks here as bugs are reported. Keep in sync with - # detect_cpu_family() above. - return trial - -KERNEL_MAPPINGS: T.Mapping[str, str] = {'freebsd': 'freebsd', - 'openbsd': 'openbsd', - 'netbsd': 'netbsd', - 'windows': 'nt', - 'android': 'linux', - 'linux': 'linux', - 'cygwin': 'nt', - 'darwin': 'xnu', - 'ios': 'xnu', - 'tvos': 'xnu', - 'visionos': 'xnu', - 'watchos': 'xnu', - 'dragonfly': 'dragonfly', - 'haiku': 'haiku', - 'gnu': 'gnu', - } - -def detect_kernel(system: str) -> T.Optional[str]: - if system == 'sunos': - # Solaris 5.10 uname doesn't support the -o switch, and illumos started - # with version 5.11 so shortcut the logic to report 'solaris' in such - # cases where the version is 5.10 or below. - if mesonlib.version_compare(platform.uname().release, '<=5.10'): - return 'solaris' - # This needs to be /usr/bin/uname because gnu-uname could be installed and - # won't provide the necessary information - p, out, _ = Popen_safe(['/usr/bin/uname', '-o']) - if p.returncode != 0: - raise MesonException('Failed to run "/usr/bin/uname -o"') - out = out.lower().strip() - if out not in {'illumos', 'solaris'}: - mlog.warning(f'Got an unexpected value for kernel on a SunOS derived platform, expected either "illumos" or "solaris", but got "{out}".' - "Please open a Meson issue with the OS you're running and the value detected for your kernel.") - return None - return out - return KERNEL_MAPPINGS.get(system, None) - -def detect_subsystem(system: str) -> T.Optional[str]: - if system == 'darwin': - return 'macos' - return system - -def detect_system() -> str: - if sys.platform == 'cygwin': - return 'cygwin' - return platform.system().lower() - -def detect_msys2_arch() -> T.Optional[str]: - return os.environ.get('MSYSTEM_CARCH', None) - -def detect_machine_info(compilers: T.Optional[CompilersDict] = None) -> MachineInfo: - """Detect the machine we're running on - - If compilers are not provided, we cannot know as much. None out those - fields to avoid accidentally depending on partial knowledge. The - underlying ''detect_*'' method can be called to explicitly use the - partial information. - """ - system = detect_system() - return MachineInfo( - system, - detect_cpu_family(compilers) if compilers is not None else None, - detect_cpu(compilers) if compilers is not None else None, - sys.byteorder, - detect_kernel(system), - detect_subsystem(system)) - -# TODO make this compare two `MachineInfo`s purely. How important is the -# `detect_cpu_family({})` distinction? It is the one impediment to that. -def machine_info_can_run(machine_info: MachineInfo) -> bool: - """Whether we can run binaries for this machine on the current machine. - - Can almost always run 32-bit binaries on 64-bit natively if the host - and build systems are the same. We don't pass any compilers to - detect_cpu_family() here because we always want to know the OS - architecture, not what the compiler environment tells us. - """ - if machine_info.system != detect_system(): - return False - true_build_cpu_family = detect_cpu_family({}) - assert machine_info.cpu_family is not None, 'called on incomplete machine_info' - return \ - (machine_info.cpu_family == true_build_cpu_family) or \ - ((true_build_cpu_family == 'x86_64') and (machine_info.cpu_family == 'x86')) or \ - ((true_build_cpu_family == 'mips64') and (machine_info.cpu_family == 'mips')) class Environment: private_dir = 'meson-private' diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c1500630c..3e1010471 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -309,7 +309,7 @@ class Interpreter(InterpreterBase, HoldableObject): # have the compilers needed to gain more knowledge, so wipe out old # inference and start over. machines = self.build.environment.machines.miss_defaulting() - machines.build = environment.detect_machine_info(self.coredata.compilers.build) + machines.build = envconfig.detect_machine_info(self.coredata.compilers.build) self.build.environment.machines = machines.default_missing() assert self.build.environment.machines.build.cpu is not None assert self.build.environment.machines.host.cpu is not None diff --git a/run_tests.py b/run_tests.py index ed224f817..38c1e812b 100755 --- a/run_tests.py +++ b/run_tests.py @@ -32,7 +32,8 @@ from mesonbuild import mesonlib from mesonbuild import mesonmain from mesonbuild import mtest from mesonbuild import mlog -from mesonbuild.environment import Environment, detect_ninja, detect_machine_info +from mesonbuild.environment import Environment, detect_ninja +from mesonbuild.envconfig import detect_machine_info from mesonbuild.coredata import version as meson_version from mesonbuild.options import backendlist from mesonbuild.mesonlib import setup_vsenv diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 5e4739ce3..21cdaa8be 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1054,7 +1054,7 @@ class AllPlatformTests(BasePlatformTests): def test_internal_include_order(self): - if mesonbuild.environment.detect_msys2_arch() and ('MESON_RSP_THRESHOLD' in os.environ): + if mesonbuild.envconfig.detect_msys2_arch() and ('MESON_RSP_THRESHOLD' in os.environ): raise SkipTest('Test does not yet support gcc rsp files on msys2') testdir = os.path.join(self.common_test_dir, '130 include order') @@ -4075,7 +4075,7 @@ class AllPlatformTests(BasePlatformTests): return basename def get_shared_lib_name(basename: str) -> str: - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): return f'lib{basename}.dll' elif is_windows(): return f'{basename}.dll' @@ -4288,7 +4288,7 @@ class AllPlatformTests(BasePlatformTests): self.assertTrue((covdir / f).is_file(), msg=f'{f} is not a file') def test_coverage(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: @@ -4308,7 +4308,7 @@ class AllPlatformTests(BasePlatformTests): self._check_coverage_files() def test_coverage_complex(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: @@ -4328,7 +4328,7 @@ class AllPlatformTests(BasePlatformTests): self._check_coverage_files() def test_coverage_html(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: @@ -4348,7 +4348,7 @@ class AllPlatformTests(BasePlatformTests): self._check_coverage_files(['html']) def test_coverage_text(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: @@ -4368,7 +4368,7 @@ class AllPlatformTests(BasePlatformTests): self._check_coverage_files(['text']) def test_coverage_xml(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: @@ -4388,7 +4388,7 @@ class AllPlatformTests(BasePlatformTests): self._check_coverage_files(['xml']) def test_coverage_escaping(self): - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with coverage on MSYS2') gcovr_exe, gcovr_new_rootdir = mesonbuild.environment.detect_gcovr() if not gcovr_exe: diff --git a/unittests/datatests.py b/unittests/datatests.py index 58b74188e..e529e4e5b 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -183,7 +183,7 @@ class DataTests(unittest.TestCase): arches = [m.group(1) for m in re.finditer(r"^\| (\w+) +\|", content, re.MULTILINE)] # Drop the header arches = set(arches[1:]) - self.assertEqual(arches, set(mesonbuild.environment.known_cpu_families)) + self.assertEqual(arches, set(mesonbuild.envconfig.known_cpu_families)) def test_markdown_files_in_sitemap(self): ''' diff --git a/unittests/internaltests.py b/unittests/internaltests.py index dfa797dc7..71e32ba3f 100644 --- a/unittests/internaltests.py +++ b/unittests/internaltests.py @@ -1594,9 +1594,9 @@ class InternalTests(unittest.TestCase): """Mock all of the ways we could get the trial at once.""" mocked = mock.Mock(return_value=value) - with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ - mock.patch('mesonbuild.environment.platform.processor', mocked), \ - mock.patch('mesonbuild.environment.platform.machine', mocked): + with mock.patch('mesonbuild.envconfig.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.envconfig.platform.processor', mocked), \ + mock.patch('mesonbuild.envconfig.platform.machine', mocked): yield cases = [ @@ -1629,26 +1629,26 @@ class InternalTests(unittest.TestCase): cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) - with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + with mock.patch('mesonbuild.envconfig.any_compiler_has_define', mock.Mock(return_value=False)): for test, expected in cases: with self.subTest(test, has_define=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu_family({'c': cc}) + actual = mesonbuild.envconfig.detect_cpu_family({'c': cc}) self.assertEqual(actual, expected) - with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + with mock.patch('mesonbuild.envconfig.any_compiler_has_define', mock.Mock(return_value=True)): for test, expected in [('x86_64', 'x86'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): - actual = mesonbuild.environment.detect_cpu_family({'c': cc}) + actual = mesonbuild.envconfig.detect_cpu_family({'c': cc}) self.assertEqual(actual, expected) # machine_info_can_run calls detect_cpu_family with no compilers at all with mock.patch( - 'mesonbuild.environment.any_compiler_has_define', + 'mesonbuild.envconfig.any_compiler_has_define', mock.Mock(side_effect=AssertionError('Should not be called')), ): for test, expected in [('mips64', 'mips64')]: with self.subTest(test, has_compiler=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu_family({}) + actual = mesonbuild.envconfig.detect_cpu_family({}) self.assertEqual(actual, expected) def test_detect_cpu(self) -> None: @@ -1658,9 +1658,9 @@ class InternalTests(unittest.TestCase): """Mock all of the ways we could get the trial at once.""" mocked = mock.Mock(return_value=value) - with mock.patch('mesonbuild.environment.detect_windows_arch', mocked), \ - mock.patch('mesonbuild.environment.platform.processor', mocked), \ - mock.patch('mesonbuild.environment.platform.machine', mocked): + with mock.patch('mesonbuild.envconfig.detect_windows_arch', mocked), \ + mock.patch('mesonbuild.envconfig.platform.processor', mocked), \ + mock.patch('mesonbuild.envconfig.platform.machine', mocked): yield cases = [ @@ -1678,25 +1678,25 @@ class InternalTests(unittest.TestCase): cc = ClangCCompiler([], [], 'fake', MachineChoice.HOST, False, mock.Mock()) - with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=False)): + with mock.patch('mesonbuild.envconfig.any_compiler_has_define', mock.Mock(return_value=False)): for test, expected in cases: with self.subTest(test, has_define=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu({'c': cc}) + actual = mesonbuild.envconfig.detect_cpu({'c': cc}) self.assertEqual(actual, expected) - with mock.patch('mesonbuild.environment.any_compiler_has_define', mock.Mock(return_value=True)): + with mock.patch('mesonbuild.envconfig.any_compiler_has_define', mock.Mock(return_value=True)): for test, expected in [('x86_64', 'i686'), ('aarch64', 'arm'), ('ppc', 'ppc64'), ('mips64', 'mips64')]: with self.subTest(test, has_define=True), mock_trial(test): - actual = mesonbuild.environment.detect_cpu({'c': cc}) + actual = mesonbuild.envconfig.detect_cpu({'c': cc}) self.assertEqual(actual, expected) with mock.patch( - 'mesonbuild.environment.any_compiler_has_define', + 'mesonbuild.envconfig.any_compiler_has_define', mock.Mock(side_effect=AssertionError('Should not be called')), ): for test, expected in [('mips64', 'mips64')]: with self.subTest(test, has_compiler=False), mock_trial(test): - actual = mesonbuild.environment.detect_cpu({}) + actual = mesonbuild.envconfig.detect_cpu({}) self.assertEqual(actual, expected) @mock.patch('mesonbuild.interpreter.Interpreter.load_root_meson_file', mock.Mock(return_value=None)) diff --git a/unittests/machinefiletests.py b/unittests/machinefiletests.py index 15c0e5728..7f583de2e 100644 --- a/unittests/machinefiletests.py +++ b/unittests/machinefiletests.py @@ -204,7 +204,7 @@ class NativeFileTests(BasePlatformTests): def test_config_tool_dep(self): # Do the skip at this level to avoid screwing up the cache - if mesonbuild.environment.detect_msys2_arch(): + if mesonbuild.envconfig.detect_msys2_arch(): raise SkipTest('Skipped due to problems with LLVM on MSYS2') if not shutil.which('llvm-config'): raise SkipTest('No llvm-installed, cannot test') |
