diff options
author | John Ericson <git@JohnEricson.me> | 2019-08-02 14:29:40 -0400 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2020-03-23 17:51:36 +0200 |
commit | 3a4388e51dee5e7e58f1e5ad4e60fb73b4aacf08 (patch) | |
tree | 8f0637e630777cc4a5707c16a30c4d980b888371 /mesonbuild/envconfig.py | |
parent | f6b0425576640e1613f64503951c7c604b868947 (diff) | |
download | meson-3a4388e51dee5e7e58f1e5ad4e60fb73b4aacf08.zip meson-3a4388e51dee5e7e58f1e5ad4e60fb73b4aacf08.tar.gz meson-3a4388e51dee5e7e58f1e5ad4e60fb73b4aacf08.tar.bz2 |
Fix legacy env var support with cross
Fix #3969
Diffstat (limited to 'mesonbuild/envconfig.py')
-rw-r--r-- | mesonbuild/envconfig.py | 114 |
1 files changed, 65 insertions, 49 deletions
diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 0ae1e6d..ac13a71 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -16,7 +16,7 @@ import configparser, os, subprocess import typing as T from . import mesonlib -from .mesonlib import EnvironmentException, split_args +from .mesonlib import EnvironmentException, MachineChoice, PerMachine, split_args from . import mlog _T = T.TypeVar('_T') @@ -108,27 +108,47 @@ class MesonConfigFile: out[s] = section return out -class HasEnvVarFallback: +def get_env_var_pair(for_machine: MachineChoice, + is_cross: bool, + var_name: str) -> T.Tuple[T.Optional[str], T.Optional[str]]: """ - A tiny class to indicate that this class contains data that can be - initialized from either a config file or environment file. The `fallback` - field says whether env vars should be used. Downstream logic (e.g. subclass - methods) can check it to decide what to do, since env vars are currently - lazily decoded. - - Frankly, this is a pretty silly class at the moment. The hope is the way - that we deal with environment variables will become more structured, and - this can be starting point. + Returns the exact env var and the value. """ - def __init__(self, fallback: bool = True): - self.fallback = fallback - -class Properties(HasEnvVarFallback): + candidates = PerMachine( + # The prefixed build version takes priority, but if we are native + # compiling we fall back on the unprefixed host version. This + # allows native builds to never need to worry about the 'BUILD_*' + # ones. + ([var_name + '_FOR_BUILD'] if is_cross else [var_name]), + # Always just the unprefixed host verions + ([] if is_cross else [var_name]), + )[for_machine] + for var in candidates: + value = os.environ.get(var) + if value is not None: + break + else: + formatted = ', '.join(['{!r}'.format(var) for var in candidates]) + mlog.debug('None of {} are defined in the environment, not changing global flags.'.format(formatted)) + return None + mlog.log('Using {!r} from environment with value: {!r}'.format(var, value)) + return var, value + +def get_env_var(for_machine: MachineChoice, + is_cross: bool, + var_name: str) -> T.Tuple[T.Optional[str], T.Optional[str]]: + ret = get_env_var_pair(for_machine, is_cross, var_name) + if ret is None: + return None + else: + var, value = ret + return value + +class Properties: def __init__( self, properties: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None, - fallback: bool = True): - super().__init__(fallback) + ): self.properties = properties or {} # type: T.Dict[str, T.Union[str, T.List[str]]] def has_stdlib(self, language: str) -> bool: @@ -290,12 +310,11 @@ class MachineInfo: def libdir_layout_is_win(self) -> bool: return self.is_windows() or self.is_cygwin() -class BinaryTable(HasEnvVarFallback): +class BinaryTable: def __init__( self, binaries: T.Optional[T.Dict[str, T.Union[str, T.List[str]]]] = None, - fallback: bool = True): - super().__init__(fallback) + ): self.binaries = binaries or {} # type: T.Dict[str, T.Union[str, T.List[str]]] for name, command in self.binaries.items(): if not isinstance(command, (list, str)): @@ -355,13 +374,6 @@ class BinaryTable(HasEnvVarFallback): return ['ccache'] @classmethod - def _warn_about_lang_pointing_to_cross(cls, compiler_exe: str, evar: str) -> None: - evar_str = os.environ.get(evar, 'WHO_WOULD_CALL_THEIR_COMPILER_WITH_THIS_NAME') - if evar_str == compiler_exe: - mlog.warning('''Env var %s seems to point to the cross compiler. -This is probably wrong, it should always point to the native compiler.''' % evar) - - @classmethod def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.List[str]]: compiler = mesonlib.stringlistify(entry) # Ensure ccache exists and remove it if it doesn't @@ -373,38 +385,42 @@ This is probably wrong, it should always point to the native compiler.''' % evar # Return value has to be a list of compiler 'choices' return compiler, ccache - def lookup_entry(self, name: str) -> T.Optional[T.List[str]]: + def lookup_entry(self, + for_machine: MachineChoice, + is_cross: bool, + name: str) -> T.Optional[T.List[str]]: """Lookup binary in cross/native file and fallback to environment. Returns command with args as list if found, Returns `None` if nothing is found. """ # Try explicit map, don't fall back on env var - command = self.binaries.get(name) - if command is not None: - command = mesonlib.stringlistify(command) - # Relies on there being no "" env var - evar = self.evarMap.get(name, "") - self._warn_about_lang_pointing_to_cross(command[0], evar) - elif self.fallback: - # Relies on there being no "" env var - evar = self.evarMap.get(name, "") - command = os.environ.get(evar) - if command is None: - deprecated = self.DEPRECATION_MAP.get(evar) - if deprecated: - command = os.environ.get(deprecated) - if command: - mlog.deprecation( - 'The', deprecated, 'environment variable is deprecated in favor of', - evar, once=True) - if command is not None: - command = split_args(command) + # Try explict map, then env vars + for _ in [()]: # a trick to get `break` + raw_command = self.binaries.get(name) + if raw_command is not None: + command = mesonlib.stringlistify(raw_command) + break # found + evar = self.evarMap.get(name) + if evar is not None: + raw_command = get_env_var(for_machine, is_cross, evar) + if raw_command is None: + deprecated = self.DEPRECATION_MAP.get(evar) + if deprecated is not None: + raw_command = get_env_var(for_machine, is_cross, deprecated) + if raw_command is not None: + mlog.deprecation( + 'The', deprecated, 'environment variable is deprecated in favor of', + evar, once=True) + if raw_command is not None: + command = split_args(raw_command) + break # found + command = None # Do not return empty or blank string entries if command is not None and (len(command) == 0 or len(command[0].strip()) == 0): - return None + command = None return command class Directories: |