64
64
__version__ = '0.11.0.dev0'
65
65
66
66
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
-
75
67
_COLORS = {
76
68
'cyan' : '\33 [36m' ,
77
69
'yellow' : '\33 [93m' ,
@@ -82,6 +74,16 @@ class _depstr:
82
74
'reset' : '\33 [0m' ,
83
75
}
84
76
_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 } '
85
87
86
88
87
89
def _init_colors () -> Dict [str , str ]:
@@ -565,6 +567,12 @@ def __init__(
565
567
self ._build_dir = pathlib .Path (build_dir ).absolute () if build_dir else (self ._working_dir / 'build' )
566
568
self ._install_dir = self ._working_dir / 'install'
567
569
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 ))
568
576
569
577
# load config -- PEP 621 support is optional
570
578
self ._config = tomllib .loads (self ._source_dir .joinpath ('pyproject.toml' ).read_text ())
@@ -637,7 +645,7 @@ def _get_config_key(self, key: str) -> Any:
637
645
def _proc (self , * args : str ) -> None :
638
646
"""Invoke a subprocess."""
639
647
print ('{cyan}{bold}+ {}{reset}' .format (' ' .join (args ), ** _STYLES ))
640
- subprocess .check_call (list (args ))
648
+ subprocess .check_call (list (args ), env = self . _env )
641
649
642
650
def _meson (self , * args : str ) -> None :
643
651
"""Invoke Meson."""
@@ -957,6 +965,37 @@ def _validate_string_collection(key: str) -> None:
957
965
yield project
958
966
959
967
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
+
960
999
def build_sdist (
961
1000
sdist_directory : str ,
962
1001
config_settings : Optional [Dict [Any , Any ]] = None ,
@@ -972,12 +1011,24 @@ def get_requires_for_build_wheel(
972
1011
config_settings : Optional [Dict [str , str ]] = None ,
973
1012
) -> List [str ]:
974
1013
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
980
1030
dependencies .append (_depstr .patchelf )
1031
+
981
1032
return dependencies
982
1033
983
1034
0 commit comments