6464__version__ = '0.11.0.dev0'
6565
6666
67- class _depstr :
68- """Namespace that holds the requirement strings for dependencies we *might*
69- need at runtime. Having them in one place makes it easier to update.
70- """
71- patchelf = 'patchelf >= 0.11.0'
72- wheel = 'wheel >= 0.36.0' # noqa: F811
73-
74-
7567_COLORS = {
7668 'cyan' : '\33 [36m' ,
7769 'yellow' : '\33 [93m' ,
@@ -82,6 +74,16 @@ class _depstr:
8274 'reset' : '\33 [0m' ,
8375}
8476_NO_COLORS = {color : '' for color in _COLORS }
77+ _NINJA_REQUIRED_VERSION = '1.8.2'
78+
79+
80+ class _depstr :
81+ """Namespace that holds the requirement strings for dependencies we *might*
82+ need at runtime. Having them in one place makes it easier to update.
83+ """
84+ patchelf = 'patchelf >= 0.11.0'
85+ wheel = 'wheel >= 0.36.0' # noqa: F811
86+ ninja = f'ninja >= { _NINJA_REQUIRED_VERSION } '
8587
8688
8789def _init_colors () -> Dict [str , str ]:
@@ -565,6 +567,12 @@ def __init__(
565567 self ._build_dir = pathlib .Path (build_dir ).absolute () if build_dir else (self ._working_dir / 'build' )
566568 self ._install_dir = self ._working_dir / 'install'
567569 self ._meson_native_file = self ._source_dir / '.mesonpy-native-file.ini'
570+ self ._env = os .environ .copy ()
571+
572+ # prepare environment
573+ ninja_path = _env_ninja_command ()
574+ if ninja_path is not None :
575+ self ._env .setdefault ('NINJA' , str (ninja_path ))
568576
569577 # load config -- PEP 621 support is optional
570578 self ._config = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
@@ -637,7 +645,7 @@ def _get_config_key(self, key: str) -> Any:
637645 def _proc (self , * args : str ) -> None :
638646 """Invoke a subprocess."""
639647 print ('{cyan}{bold}+ {}{reset}' .format (' ' .join (args ), ** _STYLES ))
640- subprocess .check_call (list (args ))
648+ subprocess .check_call (list (args ), env = self . _env )
641649
642650 def _meson (self , * args : str ) -> None :
643651 """Invoke Meson."""
@@ -957,6 +965,37 @@ def _validate_string_collection(key: str) -> None:
957965 yield project
958966
959967
968+ def _env_ninja_command (* , version : str = _NINJA_REQUIRED_VERSION ) -> Optional [pathlib .Path ]:
969+ """
970+ Returns the path to ninja, or None if no ninja found.
971+ """
972+ required_version = tuple (int (v ) for v in version .split ('.' ))
973+ env_ninja = os .environ .get ('NINJA' , None )
974+ ninja_candidates = [env_ninja ] if env_ninja else ['ninja' , 'ninja-build' , 'samu' ]
975+ for ninja in ninja_candidates :
976+ ninja_path = shutil .which (ninja )
977+ if ninja_path is None :
978+ continue
979+
980+ result = subprocess .run ([ninja_path , '--version' ], check = False , text = True , capture_output = True )
981+
982+ try :
983+ candidate_version = tuple (int (x ) for x in result .stdout .split ('.' )[:3 ])
984+ except ValueError :
985+ continue
986+ if candidate_version < required_version :
987+ continue
988+ return pathlib .Path (ninja_path )
989+
990+ return None
991+
992+
993+ def get_requires_for_build_sdist (
994+ config_settings : Optional [Dict [str , str ]] = None ,
995+ ) -> List [str ]:
996+ return [_depstr .ninja ] if _env_ninja_command () is None else []
997+
998+
960999def build_sdist (
9611000 sdist_directory : str ,
9621001 config_settings : Optional [Dict [Any , Any ]] = None ,
@@ -972,12 +1011,24 @@ def get_requires_for_build_wheel(
9721011 config_settings : Optional [Dict [str , str ]] = None ,
9731012) -> List [str ]:
9741013 dependencies = [_depstr .wheel ]
975- with _project (config_settings ) as project :
976- if not project .is_pure and platform .system () == 'Linux' :
977- # we may need patchelf
978- if not shutil .which ('patchelf' ): # XXX: This is slightly dangerous.
979- # patchelf not already acessible on the system
1014+
1015+ if _env_ninja_command () is None :
1016+ dependencies .append (_depstr .ninja )
1017+
1018+ if sys .platform .startswith ('linux' ):
1019+ # we may need patchelf
1020+ if not shutil .which ('patchelf' ):
1021+ # patchelf not already accessible on the system
1022+ if _env_ninja_command () is not None :
1023+ # we have ninja available, so we can run Meson and check if the project needs patchelf
1024+ with _project (config_settings ) as project :
1025+ if not project .is_pure :
1026+ dependencies .append (_depstr .patchelf )
1027+ else :
1028+ # we can't check if the project needs patchelf, so always add it
1029+ # XXX: wait for https://github.com/mesonbuild/meson/pull/10779
9801030 dependencies .append (_depstr .patchelf )
1031+
9811032 return dependencies
9821033
9831034
0 commit comments