3434from ..util .helpers import prepare_command
3535from ..util .packaging import find_compatible_wheel
3636from ..util .python_build_standalone import create_python_build_standalone_environment
37- from ..venv import constraint_flags , virtualenv
37+ from ..venv import constraint_flags , find_uv , virtualenv
3838
39-
40- def android_triplet (identifier : str ) -> str :
41- return {
42- "arm64_v8a" : "aarch64-linux-android" ,
43- "x86_64" : "x86_64-linux-android" ,
44- }[parse_identifier (identifier )[1 ]]
39+ ANDROID_TRIPLET = {
40+ "arm64_v8a" : "aarch64-linux-android" ,
41+ "x86_64" : "x86_64-linux-android" ,
42+ }
4543
4644
4745def parse_identifier (identifier : str ) -> tuple [str , str ]:
@@ -53,6 +51,10 @@ def parse_identifier(identifier: str) -> tuple[str, str]:
5351 return (f"{ major } .{ minor } " , arch )
5452
5553
54+ def android_triplet (identifier : str ) -> str :
55+ return ANDROID_TRIPLET [parse_identifier (identifier )[1 ]]
56+
57+
5658@dataclass (frozen = True )
5759class PythonConfiguration :
5860 version : str
@@ -147,7 +149,7 @@ def build(options: Options, tmp_path: Path) -> None:
147149 built_wheel = build_wheel (state )
148150 repaired_wheel = repair_wheel (state , built_wheel )
149151
150- test_wheel (state , repaired_wheel )
152+ test_wheel (state , repaired_wheel , build_frontend = build_options . build_frontend . name )
151153
152154 output_wheel : Path | None = None
153155 if compatible_wheel is None :
@@ -187,6 +189,13 @@ def setup_env(
187189 * android_env, which uses the environment while simulating running on Android.
188190 """
189191 log .step ("Setting up build environment..." )
192+ build_frontend = build_options .build_frontend .name
193+ use_uv = build_frontend == "build[uv]"
194+ uv_path = find_uv ()
195+ if use_uv and uv_path is None :
196+ msg = "uv not found"
197+ raise AssertionError (msg )
198+ pip = ["pip" ] if not use_uv else [str (uv_path ), "pip" ]
190199
191200 # Create virtual environment
192201 python_exe = create_python_build_standalone_environment (
@@ -197,14 +206,14 @@ def setup_env(
197206 version = config .version , tmp_dir = build_path
198207 )
199208 build_env = virtualenv (
200- config .version , python_exe , venv_dir , dependency_constraint , use_uv = False
209+ config .version , python_exe , venv_dir , dependency_constraint , use_uv = use_uv
201210 )
202211 create_cmake_toolchain (config , build_path , python_dir , build_env )
203212
204213 # Apply custom environment variables, and check environment is still valid
205214 build_env = build_options .environment .as_dictionary (build_env )
206215 build_env ["PIP_DISABLE_PIP_VERSION_CHECK" ] = "1"
207- for command in ["python" , "pip" ]:
216+ for command in ["python" ] if use_uv else [ "python" , "pip" ]:
208217 command_path = call ("which" , command , env = build_env , capture_stdout = True ).strip ()
209218 if command_path != f"{ venv_dir } /bin/{ command } " :
210219 msg = (
@@ -219,11 +228,10 @@ def setup_env(
219228 android_env = setup_android_env (config , python_dir , venv_dir , build_env )
220229
221230 # Install build tools
222- build_frontend = build_options .build_frontend
223- if build_frontend .name != "build" :
231+ if build_frontend not in {"build" , "build[uv]" }:
224232 msg = "Android requires the build frontend to be 'build'"
225233 raise errors .FatalError (msg )
226- call (" pip" , "install" , "build" , * constraint_flags (dependency_constraint ), env = build_env )
234+ call (* pip , "install" , "build" , * constraint_flags (dependency_constraint ), env = build_env )
227235
228236 # Build-time requirements must be queried within android_env, because
229237 # `get_requires_for_build` can run arbitrary code in setup.py scripts, which may be
@@ -243,13 +251,13 @@ def make_extra_environ(self) -> dict[str, str]:
243251
244252 pb = ProjectBuilder .from_isolated_env (AndroidEnv (), build_options .package_dir )
245253 if pb .build_system_requires :
246- call (" pip" , "install" , * pb .build_system_requires , env = build_env )
254+ call (* pip , "install" , * pb .build_system_requires , env = build_env )
247255
248256 requires_for_build = pb .get_requires_for_build (
249257 "wheel" , parse_config_settings (build_options .config_settings )
250258 )
251259 if requires_for_build :
252- call (" pip" , "install" , * requires_for_build , env = build_env )
260+ call (* pip , "install" , * requires_for_build , env = build_env )
253261
254262 return build_env , android_env
255263
@@ -559,12 +567,19 @@ def soname_with_hash(src_path: Path) -> str:
559567 return src_name
560568
561569
562- def test_wheel (state : BuildState , wheel : Path ) -> None :
570+ def test_wheel (state : BuildState , wheel : Path , * , build_frontend : str ) -> None :
563571 test_command = state .options .test_command
564572 if not (test_command and state .options .test_selector (state .config .identifier )):
565573 return
566574
567575 log .step ("Testing wheel..." )
576+ use_uv = build_frontend == "build[uv]"
577+ uv_path = find_uv ()
578+ if use_uv and uv_path is None :
579+ msg = "uv not found"
580+ raise AssertionError (msg )
581+ pip = ["pip" ] if not use_uv else [str (uv_path ), "pip" ]
582+
568583 native_arch = arch_synonym (platform .machine (), platforms .native_platform (), "android" )
569584 if state .config .arch != native_arch :
570585 log .warning (
@@ -580,15 +595,23 @@ def test_wheel(state: BuildState, wheel: Path) -> None:
580595 env = state .build_env ,
581596 )
582597
598+ platform_args = (
599+ ["--python-platform" , android_triplet (state .config .identifier )]
600+ if use_uv
601+ else [
602+ "--platform" ,
603+ sysconfig_print ("get_platform()" , state .android_env ).replace ("-" , "_" ),
604+ ]
605+ )
606+
583607 # Install the wheel and test-requires.
584608 site_packages_dir = state .build_path / "site-packages"
585609 site_packages_dir .mkdir ()
586610 call (
587- " pip" ,
611+ * pip ,
588612 "install" ,
589613 "--only-binary=:all:" ,
590- "--platform" ,
591- sysconfig_print ("get_platform()" , state .android_env ).replace ("-" , "_" ),
614+ * platform_args ,
592615 "--target" ,
593616 site_packages_dir ,
594617 f"{ wheel } { state .options .test_extras } " ,
0 commit comments