summaryrefslogtreecommitdiff
path: root/mesonbuild/environment.py
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-10-07 16:29:16 +0200
committerJussi Pakkanen <jussi.pakkanen@mailbox.org>2025-10-29 18:59:30 +0200
commit1614401329f11d3763a56ed5ce207aba511a6a9d (patch)
treeaa01f773236c8d9da30c40d0d946708f14834af3 /mesonbuild/environment.py
parent1ae428cbb3200375d572e1b684241d760d1577a7 (diff)
downloadmeson-1614401329f11d3763a56ed5ce207aba511a6a9d.tar.gz
environment: move detection functions to envconfig.py
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'mesonbuild/environment.py')
-rw-r--r--mesonbuild/environment.py259
1 files changed, 3 insertions, 256 deletions
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'