diff --git a/mesonbuild/dependencies/boost.py b/mesonbuild/dependencies/boost.py index 622ee3774..d12f37c3a 100644 --- a/mesonbuild/dependencies/boost.py +++ b/mesonbuild/dependencies/boost.py @@ -20,12 +20,14 @@ from pathlib import Path from .. import mlog from .. import mesonlib -from ..envconfig import get_env_var from ..environment import Environment from .base import DependencyException, ExternalDependency, PkgConfigDependency from .misc import threads_factory +if T.TYPE_CHECKING: + from ..environment import Properties + # On windows 3 directory layouts are supported: # * The default layout (versioned) installed: # - $BOOST_ROOT/include/boost-x_x/boost/*.hpp @@ -372,18 +374,11 @@ class BoostDependency(ExternalDependency): # First, look for paths specified in a machine file props = self.env.properties[self.for_machine] - boost_property_env = [props.get('boost_includedir'), props.get('boost_librarydir'), props.get('boost_root')] - if any(boost_property_env): + if any(x in self.env.properties[self.for_machine] for x in + ['boost_includedir', 'boost_librarydir', 'boost_root']): self.detect_boost_machine_file(props) return - # Next, look for paths in the environment - boost_manual_env_list = ['BOOST_INCLUDEDIR', 'BOOST_LIBRARYDIR', 'BOOST_ROOT', 'BOOSTROOT'] - boost_manual_env = [get_env_var(self.for_machine, self.env.is_cross_build, x) for x in boost_manual_env_list] - if any(boost_manual_env): - self.detect_boost_env() - return - # Finally, look for paths from .pc files and from searching the filesystem self.detect_roots() @@ -405,13 +400,20 @@ class BoostDependency(ExternalDependency): self.boost_root = j break - def detect_boost_machine_file(self, props: T.Dict[str, str]) -> None: + def detect_boost_machine_file(self, props: 'Properties') -> None: + """Detect boost with values in the machine file or environment. + + The machine file values are defaulted to the environment values. + """ + # XXX: if we had a TypedDict we woudn't need this incdir = props.get('boost_includedir') + assert incdir is None or isinstance(incdir, str) libdir = props.get('boost_librarydir') + assert libdir is None or isinstance(libdir, str) if incdir and libdir: - inc_dir = Path(props['boost_includedir']) - lib_dir = Path(props['boost_librarydir']) + inc_dir = Path(incdir) + lib_dir = Path(libdir) if not inc_dir.is_absolute() or not lib_dir.is_absolute(): raise DependencyException('Paths given for boost_includedir and boost_librarydir in machine file must be absolute') @@ -436,43 +438,6 @@ class BoostDependency(ExternalDependency): self.check_and_set_roots(paths) - def detect_boost_env(self) -> None: - boost_includedir = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_INCLUDEDIR') - boost_librarydir = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_LIBRARYDIR') - - boost_manual_env = [boost_includedir, boost_librarydir] - if all(boost_manual_env): - inc_dir = Path(boost_includedir) - lib_dir = Path(boost_librarydir) - - if not inc_dir.is_absolute() or not lib_dir.is_absolute(): - raise DependencyException('Paths given in BOOST_INCLUDEDIR and BOOST_LIBRARYDIR must be absolute') - - mlog.debug('Trying to find boost with:') - mlog.debug(' - BOOST_INCLUDEDIR = {}'.format(inc_dir)) - mlog.debug(' - BOOST_LIBRARYDIR = {}'.format(lib_dir)) - - return self.detect_split_root(inc_dir, lib_dir) - - elif any(boost_manual_env): - raise DependencyException('Both BOOST_INCLUDEDIR *and* BOOST_LIBRARYDIR have to be set (one is not enough). Ignoring.') - - boost_root = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOST_ROOT') - boostroot = get_env_var(self.for_machine, self.env.is_cross_build, 'BOOSTROOT') - - # It shouldn't be possible to get here without something in BOOST_ROOT or BOOSTROOT - assert(boost_root or boostroot) - - for path, name in [(boost_root, 'BOOST_ROOT'), (boostroot, 'BOOSTROOT')]: - if path: - raw_paths = path.split(os.pathsep) - paths = [Path(x) for x in raw_paths] - if paths and any([not x.is_absolute() for x in paths]): - raise DependencyException('Paths in {} must be absolute'.format(name)) - break - - self.check_and_set_roots(paths) - def run_check(self, inc_dirs: T.List[BoostIncludeDir], lib_dirs: T.List[Path]) -> bool: mlog.debug(' - potential library dirs: {}'.format([x.as_posix() for x in lib_dirs])) mlog.debug(' - potential include dirs: {}'.format([x.path.as_posix() for x in inc_dirs])) diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 69b667869..596defe53 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -163,14 +163,6 @@ def get_env_var_pair(for_machine: MachineChoice, mlog.debug('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.Optional[str]: - ret = get_env_var_pair(for_machine, is_cross, var_name) - if ret is None: - return None - return ret[1] - class Properties: def __init__( self, diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 6275da05a..ba24411eb 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -656,6 +656,7 @@ class Environment: # Take default value from env if not set in cross/native files or command line. self.set_default_options_from_env() self._set_default_binaries_from_env() + self._set_default_properties_from_env() # Warn if the user is using two different ways of setting build-type # options that override each other @@ -821,6 +822,26 @@ class Environment: _, p_env = p_env_pair self.binaries[for_machine].binaries.setdefault(name, mesonlib.split_args(p_env)) + def _set_default_properties_from_env(self) -> None: + """Properties which can alkso be set from the environment.""" + # name, evar, split + opts: T.List[T.Tuple[str, T.List[str], bool]] = [ + ('boost_includedir', ['BOOST_INCLUDEDIR'], False), + ('boost_librarydir', ['BOOST_LIBRARYDIR'], False), + ('boost_root', ['BOOST_ROOT', 'BOOSTROOT'], True), + ] + + for (name, evars, split), for_machine in itertools.product(opts, MachineChoice): + for evar in evars: + p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), evar) + if p_env_pair is not None: + _, p_env = p_env_pair + if split: + self.properties[for_machine].properties.setdefault(name, p_env.split(os.pathsep)) + else: + self.properties[for_machine].properties.setdefault(name, p_env) + break + def create_new_coredata(self, options: 'argparse.Namespace') -> None: # WARNING: Don't use any values from coredata in __init__. It gets # re-initialized with project options by the interpreter during diff --git a/run_unittests.py b/run_unittests.py index bbcdb5fb7..21b6608a6 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -5376,7 +5376,7 @@ class FailureTests(BasePlatformTests): def test_boost_BOOST_ROOT_dependency(self): # Test BOOST_ROOT; can be run even if Boost is found or not self.assertMesonRaises("dependency('boost')", - "(BOOST_ROOT.*absolute|{})".format(self.dnf), + "(boost_root.*absolute|{})".format(self.dnf), override_envvars = {'BOOST_ROOT': 'relative/path'}) def test_dependency_invalid_method(self):