aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/coredata.py2
-rw-r--r--mesonbuild/dependencies/base.py8
-rw-r--r--mesonbuild/envconfig.py36
-rw-r--r--mesonbuild/environment.py66
-rw-r--r--mesonbuild/interpreter.py8
-rw-r--r--mesonbuild/mesonlib.py97
-rwxr-xr-xrun_tests.py2
-rwxr-xr-xrun_unittests.py2
8 files changed, 141 insertions, 80 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py
index 34adad3..b8f0578 100644
--- a/mesonbuild/coredata.py
+++ b/mesonbuild/coredata.py
@@ -243,7 +243,7 @@ class CoreData:
self.init_builtins()
self.backend_options = {}
self.user_options = {}
- self.compiler_options = PerMachine({}, {}, {})
+ self.compiler_options = PerMachine({}, {})
self.base_options = {}
self.cross_files = self.__load_config_files(options.cross_file, 'cross')
self.compilers = OrderedDict()
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 8f38d6c..034f6df 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -522,7 +522,7 @@ class ConfigToolDependency(ExternalDependency):
class PkgConfigDependency(ExternalDependency):
# The class's copy of the pkg-config path. Avoids having to search for it
# multiple times in the same Meson invocation.
- class_pkgbin = PerMachine(None, None, None)
+ class_pkgbin = PerMachine(None, None)
# We cache all pkg-config subprocess invocations to avoid redundant calls
pkgbin_cache = {}
@@ -957,9 +957,9 @@ class CMakeTarget:
class CMakeDependency(ExternalDependency):
# The class's copy of the CMake path. Avoids having to search for it
# multiple times in the same Meson invocation.
- class_cmakebin = PerMachine(None, None, None)
- class_cmakevers = PerMachine(None, None, None)
- class_cmakeinfo = PerMachine(None, None, None)
+ class_cmakebin = PerMachine(None, None)
+ class_cmakevers = PerMachine(None, None)
+ class_cmakeinfo = PerMachine(None, None)
# We cache all pkg-config subprocess invocations to avoid redundant calls
cmake_cache = {}
# Version string for the minimum CMake version
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py
index 70f964e..0cdb4c4 100644
--- a/mesonbuild/envconfig.py
+++ b/mesonbuild/envconfig.py
@@ -16,7 +16,7 @@ import configparser, os, shlex, subprocess
import typing
from . import mesonlib
-from .mesonlib import EnvironmentException, MachineChoice, PerMachine
+from .mesonlib import EnvironmentException
from . import mlog
_T = typing.TypeVar('_T')
@@ -255,40 +255,6 @@ class MachineInfo:
def libdir_layout_is_win(self) -> bool:
return self.is_windows() or self.is_cygwin()
-class PerMachineDefaultable(PerMachine[typing.Optional[_T]]):
- """Extends `PerMachine` with the ability to default from `None`s.
- """
- def __init__(self) -> None:
- super().__init__(None, None, None)
-
- def default_missing(self) -> None:
- """Default host to buid and target to host.
-
- This allows just specifying nothing in the native case, just host in the
- cross non-compiler case, and just target in the native-built
- cross-compiler case.
- """
- if self.host is None:
- self.host = self.build
- if self.target is None:
- self.target = self.host
-
- def miss_defaulting(self) -> None:
- """Unset definition duplicated from their previous to None
-
- This is the inverse of ''default_missing''. By removing defaulted
- machines, we can elaborate the original and then redefault them and thus
- avoid repeating the elaboration explicitly.
- """
- if self.target == self.host:
- self.target = None
- if self.host == self.build:
- self.host = None
-
-class MachineInfos(PerMachineDefaultable[MachineInfo]):
- def matches_build_machine(self, machine: MachineChoice) -> bool:
- return self.build == self[machine]
-
class BinaryTable(HasEnvVarFallback):
def __init__(
self,
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 9620639..f86b613 100644
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -19,12 +19,13 @@ from .linkers import ArLinker, ArmarLinker, VisualStudioLinker, DLinker, CcrxLin
from . import mesonlib
from .mesonlib import (
MesonException, EnvironmentException, MachineChoice, Popen_safe,
+ PerMachineDefaultable, PerThreeMachineDefaultable
)
from . import mlog
from .envconfig import (
- BinaryTable, Directories, MachineInfo, MachineInfos, MesonConfigFile,
- PerMachineDefaultable, Properties, known_cpu_families,
+ BinaryTable, Directories, MachineInfo, MesonConfigFile,
+ Properties, known_cpu_families,
)
from . import compilers
from .compilers import (
@@ -403,48 +404,62 @@ class Environment:
# Just create a fresh coredata in this case
self.create_new_coredata(options)
- self.machines = MachineInfos()
- # Will be fully initialized later using compilers later.
- self.detect_build_machine()
+ ## locally bind some unfrozen configuration
+
+ # Stores machine infos, the only *three* machine one because we have a
+ # target machine info on for the user (Meson never cares about the
+ # target machine.)
+ machines = PerThreeMachineDefaultable()
# Similar to coredata.compilers and build.compilers, but lower level in
# that there is no meta data, only names/paths.
- self.binaries = PerMachineDefaultable()
+ binaries = PerMachineDefaultable()
# Misc other properties about each machine.
- self.properties = PerMachineDefaultable()
-
- # Just uses hard-coded defaults and environment variables. Might be
- # overwritten by a native file.
- self.binaries.build = BinaryTable()
- self.properties.build = Properties()
+ properties = PerMachineDefaultable()
# Store paths for native and cross build files. There is no target
# machine information here because nothing is installed for the target
# architecture, just the build and host architectures
- self.paths = PerMachineDefaultable()
+ paths = PerMachineDefaultable()
+
+ ## Setup build machine defaults
+
+ # Will be fully initialized later using compilers later.
+ machines.build = detect_machine_info()
+
+ # Just uses hard-coded defaults and environment variables. Might be
+ # overwritten by a native file.
+ binaries.build = BinaryTable()
+ properties.build = Properties()
+
+ ## Read in native file(s) to override build machine configuration
if self.coredata.config_files is not None:
config = MesonConfigFile.from_config_parser(
coredata.load_configs(self.coredata.config_files))
- self.binaries.build = BinaryTable(config.get('binaries', {}))
- self.paths.build = Directories(**config.get('paths', {}))
+ binaries.build = BinaryTable(config.get('binaries', {}))
+ paths.build = Directories(**config.get('paths', {}))
+
+ ## Read in cross file(s) to override host machine configuration
if self.coredata.cross_files:
config = MesonConfigFile.from_config_parser(
coredata.load_configs(self.coredata.cross_files))
- self.properties.host = Properties(config.get('properties', {}), False)
- self.binaries.host = BinaryTable(config.get('binaries', {}), False)
+ properties.host = Properties(config.get('properties', {}), False)
+ binaries.host = BinaryTable(config.get('binaries', {}), False)
if 'host_machine' in config:
- self.machines.host = MachineInfo.from_literal(config['host_machine'])
+ machines.host = MachineInfo.from_literal(config['host_machine'])
if 'target_machine' in config:
- self.machines.target = MachineInfo.from_literal(config['target_machine'])
- self.paths.host = Directories(**config.get('paths', {}))
+ machines.target = MachineInfo.from_literal(config['target_machine'])
+ paths.host = Directories(**config.get('paths', {}))
+
+ ## "freeze" now initialized configuration, and "save" to the class.
- self.machines.default_missing()
- self.binaries.default_missing()
- self.properties.default_missing()
- self.paths.default_missing()
+ self.machines = machines.default_missing()
+ self.binaries = binaries.default_missing()
+ self.properties = properties.default_missing()
+ self.paths = paths.default_missing()
exe_wrapper = self.binaries.host.lookup_entry('exe_wrapper')
if exe_wrapper is not None:
@@ -1233,9 +1248,6 @@ class Environment:
self._handle_exceptions(popen_exceptions, linkers, 'linker')
raise EnvironmentException('Unknown static linker "%s"' % ' '.join(linkers))
- def detect_build_machine(self, compilers = None):
- self.machines.build = detect_machine_info(compilers)
-
def get_source_dir(self):
return self.source_dir
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 1e8f972..0afbb10 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -2047,12 +2047,12 @@ class Interpreter(InterpreterBase):
if not mock:
self.parse_project()
- # Initialize machine descriptions. We can do a better job now because we
+ # Re-initialize machine descriptions. We can do a better job now because we
# have the compilers needed to gain more knowledge, so wipe out old
# inferrence and start over.
- self.build.environment.machines.miss_defaulting()
- self.build.environment.detect_build_machine(self.coredata.compilers)
- self.build.environment.machines.default_missing()
+ machines = self.build.environment.machines.miss_defaulting()
+ machines.build = environment.detect_machine_info(self.coredata.compilers)
+ 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
assert self.build.environment.machines.target.cpu is not None
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 07beb69..f53197b 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -313,37 +313,120 @@ class OrderedEnum(Enum):
return self.value < other.value
return NotImplemented
+
class MachineChoice(OrderedEnum):
- """Enum class representing one of the three possible values for binaries,
- the build, host, and target machines.
+ """Enum class representing one of the two abstract machine names used in
+ most places: the build, and host, machines.
"""
BUILD = 0
HOST = 1
- TARGET = 2
+
class PerMachine(typing.Generic[_T]):
- def __init__(self, build: _T, host: _T, target: _T):
+ def __init__(self, build: _T, host: _T):
self.build = build
self.host = host
- self.target = target
def __getitem__(self, machine: MachineChoice) -> _T:
return {
MachineChoice.BUILD: self.build,
MachineChoice.HOST: self.host,
- MachineChoice.TARGET: self.target
}[machine]
def __setitem__(self, machine: MachineChoice, val: _T) -> None:
key = {
MachineChoice.BUILD: 'build',
MachineChoice.HOST: 'host',
- MachineChoice.TARGET: 'target'
}[machine]
setattr(self, key, val)
+ def miss_defaulting(self) -> "PerMachineDefaultable[typing.Optional[_T]]":
+ """Unset definition duplicated from their previous to None
+
+ This is the inverse of ''default_missing''. By removing defaulted
+ machines, we can elaborate the original and then redefault them and thus
+ avoid repeating the elaboration explicitly.
+ """
+ unfreeze = PerMachineDefaultable() # type: PerMachineDefaultable[typing.Optional[_T]]
+ unfreeze.build = self.build
+ unfreeze.host = self.host
+ if unfreeze.host == unfreeze.build:
+ unfreeze.host = None
+ return unfreeze
+
+
+class PerThreeMachine(PerMachine[_T]):
+ """Like `PerMachine` but includes `target` too.
+
+ It turns out just one thing do we need track the target machine. There's no
+ need to computer the `target` field so we don't bother overriding the
+ `__getitem__`/`__setitem__` methods.
+ """
+ def __init__(self, build: _T, host: _T, target: _T):
+ super().__init__(build, host)
+ self.target = target
+
+ def miss_defaulting(self) -> "PerThreeMachineDefaultable[typing.Optional[_T]]":
+ """Unset definition duplicated from their previous to None
+
+ This is the inverse of ''default_missing''. By removing defaulted
+ machines, we can elaborate the original and then redefault them and thus
+ avoid repeating the elaboration explicitly.
+ """
+ unfreeze = PerThreeMachineDefaultable() # type: PerThreeMachineDefaultable[typing.Optional[_T]]
+ unfreeze.build = self.build
+ unfreeze.host = self.host
+ unfreeze.target = self.target
+ if unfreeze.target == unfreeze.host:
+ unfreeze.target = None
+ if unfreeze.host == unfreeze.build:
+ unfreeze.host = None
+ return unfreeze
+
+ def matches_build_machine(self, machine: MachineChoice) -> bool:
+ return self.build == self[machine]
+
+class PerMachineDefaultable(PerMachine[typing.Optional[_T]]):
+ """Extends `PerMachine` with the ability to default from `None`s.
+ """
+ def __init__(self) -> None:
+ super().__init__(None, None)
+
+ def default_missing(self) -> "PerMachine[typing.Optional[_T]]":
+ """Default host to buid
+
+ This allows just specifying nothing in the native case, and just host in the
+ cross non-compiler case.
+ """
+ freeze = PerMachine(self.build, self.host)
+ if freeze.host is None:
+ freeze.host = freeze.build
+ return freeze
+
+
+class PerThreeMachineDefaultable(PerMachineDefaultable, PerThreeMachine[typing.Optional[_T]]):
+ """Extends `PerThreeMachine` with the ability to default from `None`s.
+ """
+ def __init__(self) -> None:
+ PerThreeMachine.__init__(self, None, None, None)
+
+ def default_missing(self) -> "PerThreeMachine[typing.Optional[_T]]":
+ """Default host to buid and target to host.
+
+ This allows just specifying nothing in the native case, just host in the
+ cross non-compiler case, and just target in the native-built
+ cross-compiler case.
+ """
+ freeze = PerThreeMachine(self.build, self.host, self.target)
+ if freeze.host is None:
+ freeze.host = freeze.build
+ if freeze.target is None:
+ freeze.target = freeze.host
+ return freeze
+
+
def is_sunos() -> bool:
return platform.system().lower() == 'sunos'
diff --git a/run_tests.py b/run_tests.py
index a4b0fa2..f427736 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -220,7 +220,7 @@ def clear_meson_configure_class_caches():
mesonbuild.compilers.CCompiler.find_library_cache = {}
mesonbuild.compilers.CCompiler.find_framework_cache = {}
mesonbuild.dependencies.PkgConfigDependency.pkgbin_cache = {}
- mesonbuild.dependencies.PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None, None)
+ mesonbuild.dependencies.PkgConfigDependency.class_pkgbin = mesonlib.PerMachine(None, None)
def run_configure_inprocess(commandlist):
old_stdout = sys.stdout
diff --git a/run_unittests.py b/run_unittests.py
index f4d969c..7242a5f 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -848,7 +848,7 @@ class InternalTests(unittest.TestCase):
PkgConfigDependency.check_pkgconfig = old_check
# Reset dependency class to ensure that in-process configure doesn't mess up
PkgConfigDependency.pkgbin_cache = {}
- PkgConfigDependency.class_pkgbin = PerMachine(None, None, None)
+ PkgConfigDependency.class_pkgbin = PerMachine(None, None)
def test_version_compare(self):
comparefunc = mesonbuild.mesonlib.version_compare_many