Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ec2907c

Browse files
committed
ENH: make the Meson that is used user-configurable
Allow using a MESON environment variable, analogous to the NINJA one, or a string to an executable or Python script in the `[tool.meson-python]` section of pyproject.toml Closes mesonbuildgh-458
1 parent a0f0827 commit ec2907c

File tree

1 file changed

+55
-20
lines changed

1 file changed

+55
-20
lines changed

mesonpy/__init__.py

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,13 @@ def _bool(value: Any, name: str) -> bool:
528528
raise ConfigError(f'Configuration entry "{name}" must be a boolean')
529529
return value
530530

531+
def _str(value: Any, name: str) -> str:
532+
if not isinstance(value, str):
533+
raise ConfigError(f'Configuration entry "{name}" must be a string')
534+
return value
535+
531536
scheme = _table({
537+
'cli': _str,
532538
'limited-api': _bool,
533539
'args': _table({
534540
name: _strings for name in _MESON_ARGS_KEYS
@@ -607,7 +613,22 @@ def __init__( # noqa: C901
607613
self._meson_args: MesonArgs = collections.defaultdict(list)
608614
self._limited_api = False
609615

610-
_check_meson_version()
616+
# load pyproject.toml
617+
pyproject = tomllib.loads(self._source_dir.joinpath('pyproject.toml').read_text())
618+
619+
# load meson args from pyproject.toml
620+
pyproject_config = _validate_pyproject_config(pyproject)
621+
for key, value in pyproject_config.get('args', {}).items():
622+
self._meson_args[key].extend(value)
623+
624+
# meson arguments from the command line take precedence over
625+
# arguments from the configuration file thus are added later
626+
if meson_args:
627+
for key, value in meson_args.items():
628+
self._meson_args[key].extend(value)
629+
630+
# determine command to invoke meson
631+
self._meson = _get_meson_command(pyproject_config.get('cli'))
611632

612633
self._ninja = _env_ninja_command()
613634
if self._ninja is None:
@@ -645,20 +666,6 @@ def __init__( # noqa: C901
645666
self._meson_cross_file.write_text(cross_file_data)
646667
self._meson_args['setup'].extend(('--cross-file', os.fspath(self._meson_cross_file)))
647668

648-
# load pyproject.toml
649-
pyproject = tomllib.loads(self._source_dir.joinpath('pyproject.toml').read_text())
650-
651-
# load meson args from pyproject.toml
652-
pyproject_config = _validate_pyproject_config(pyproject)
653-
for key, value in pyproject_config.get('args', {}).items():
654-
self._meson_args[key].extend(value)
655-
656-
# meson arguments from the command line take precedence over
657-
# arguments from the configuration file thus are added later
658-
if meson_args:
659-
for key, value in meson_args.items():
660-
self._meson_args[key].extend(value)
661-
662669
# write the native file
663670
native_file_data = textwrap.dedent(f'''
664671
[binaries]
@@ -740,7 +747,7 @@ def _configure(self, reconfigure: bool = False) -> None:
740747
]
741748
if reconfigure:
742749
setup_args.insert(0, '--reconfigure')
743-
self._run(['meson', 'setup', *setup_args])
750+
self._run(self._meson + ['setup', *setup_args])
744751

745752
@property
746753
def _build_command(self) -> List[str]:
@@ -750,7 +757,7 @@ def _build_command(self) -> List[str]:
750757
# environment. Using the --ninja-args option allows to
751758
# provide the exact same semantics for the compile arguments
752759
# provided by the users.
753-
cmd = ['meson', 'compile']
760+
cmd = self._meson + ['compile']
754761
args = list(self._meson_args['compile'])
755762
if args:
756763
cmd.append(f'--ninja-args={args!r}')
@@ -824,7 +831,7 @@ def version(self) -> str:
824831
def sdist(self, directory: Path) -> pathlib.Path:
825832
"""Generates a sdist (source distribution) in the specified directory."""
826833
# generate meson dist file
827-
self._run(['meson', 'dist', '--allow-dirty', '--no-tests', '--formats', 'gztar', *self._meson_args['dist']])
834+
self._run(self._meson + ['dist', '--allow-dirty', '--no-tests', '--formats', 'gztar', *self._meson_args['dist']])
828835

829836
# move meson dist file to output path
830837
dist_name = f'{self.name}-{self.version}'
@@ -919,6 +926,34 @@ def _parse_version_string(string: str) -> Tuple[int, ...]:
919926
return (0, )
920927

921928

929+
def _get_meson_command(
930+
meson_tool: str | None = None, *, version: str = _MESON_REQUIRED_VERSION
931+
) -> List[str]:
932+
"""Return the command to invoke meson.
933+
Uses the MESON env var if set, else the `cli` entry in pyproject.toml if given,
934+
else the standard `meson` executable.
935+
"""
936+
_meson = os.environ.get('MESON')
937+
if _meson is None:
938+
if meson_tool is not None:
939+
_meson = str(pathlib.Path(meson_tool).resolve())
940+
else:
941+
_meson = 'meson'
942+
943+
# If the specified Meson string ends in `.py`, we run it with the current
944+
# Python executable. This avoids problems for users on Windows, where
945+
# making a script executable isn't enough to get it to run when invoked
946+
# directly. For packages that vendor a forked Meson, the `meson.py` in the
947+
# root of the Meson repo can be used this way.
948+
if _meson.endswith(".py"):
949+
meson_cli = [sys.executable, _meson]
950+
else:
951+
meson_cli = [_meson]
952+
953+
_check_meson_version(meson_cli, version=version)
954+
return meson_cli
955+
956+
922957
def _env_ninja_command(*, version: str = _NINJA_REQUIRED_VERSION) -> Optional[str]:
923958
"""Returns the path to ninja, or None if no ninja found."""
924959
required_version = _parse_version_string(version)
@@ -933,7 +968,7 @@ def _env_ninja_command(*, version: str = _NINJA_REQUIRED_VERSION) -> Optional[st
933968
return None
934969

935970

936-
def _check_meson_version(*, version: str = _MESON_REQUIRED_VERSION) -> None:
971+
def _check_meson_version(meson_cli : List[str], /, *, version: str = _MESON_REQUIRED_VERSION) -> None:
937972
"""Check that the meson executable in the path has an appropriate version.
938973
939974
The meson Python package is a dependency of the meson-python
@@ -944,7 +979,7 @@ def _check_meson_version(*, version: str = _MESON_REQUIRED_VERSION) -> None:
944979
945980
"""
946981
required_version = _parse_version_string(version)
947-
meson_version = subprocess.run(['meson', '--version'], check=False, text=True, capture_output=True).stdout
982+
meson_version = subprocess.run(meson_cli + ['--version'], check=False, text=True, capture_output=True).stdout
948983
if _parse_version_string(meson_version) < required_version:
949984
raise ConfigError(f'Could not find meson version {version} or newer, found {meson_version}.')
950985

0 commit comments

Comments
 (0)