kivyforge 3.0.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kivyforge/__init__.py +9 -0
- kivyforge/artifacts/__init__.py +41 -0
- kivyforge/artifacts/cache.py +81 -0
- kivyforge/artifacts/collect.py +354 -0
- kivyforge/artifacts/download.py +125 -0
- kivyforge/artifacts/frameworks.py +240 -0
- kivyforge/artifacts/native_stage_util.py +346 -0
- kivyforge/artifacts/runtime.py +65 -0
- kivyforge/artifacts/verify.py +45 -0
- kivyforge/artifacts/wheels.py +89 -0
- kivyforge/bundle/__init__.py +1 -0
- kivyforge/bundle/pycompile.py +161 -0
- kivyforge/cli/__init__.py +52 -0
- kivyforge/cli/_common.py +62 -0
- kivyforge/cli/_platform.py +84 -0
- kivyforge/cli/build.py +111 -0
- kivyforge/cli/clean.py +135 -0
- kivyforge/cli/doctor.py +52 -0
- kivyforge/cli/init.py +612 -0
- kivyforge/cli/init_writer.py +716 -0
- kivyforge/cli/lock.py +261 -0
- kivyforge/cli/open_cmd.py +15 -0
- kivyforge/cli/package.py +134 -0
- kivyforge/cli/run.py +162 -0
- kivyforge/cli/status.py +20 -0
- kivyforge/cli/upgrade.py +314 -0
- kivyforge/config/__init__.py +46 -0
- kivyforge/config/errors.py +43 -0
- kivyforge/config/icons.py +60 -0
- kivyforge/config/loader.py +3079 -0
- kivyforge/config/model.py +817 -0
- kivyforge/doctor/__init__.py +19 -0
- kivyforge/doctor/checks_common.py +95 -0
- kivyforge/doctor/probe.py +357 -0
- kivyforge/doctor/result.py +41 -0
- kivyforge/lock/__init__.py +42 -0
- kivyforge/lock/_pip_shim.py +63 -0
- kivyforge/lock/find_links.py +182 -0
- kivyforge/lock/model.py +69 -0
- kivyforge/lock/pep751.py +111 -0
- kivyforge/lock/reader.py +30 -0
- kivyforge/lock/resolver.py +124 -0
- kivyforge/lock/wheelruntime/__init__.py +70 -0
- kivyforge/lock/wheelruntime/builder.py +280 -0
- kivyforge/lock/wheelruntime/model.py +94 -0
- kivyforge/lock/wheelruntime/native_binaries.py +127 -0
- kivyforge/lock/wheelruntime/pbs_github.py +133 -0
- kivyforge/lock/wheelruntime/profile.py +104 -0
- kivyforge/lock/wheelruntime/resolver.py +248 -0
- kivyforge/lock/wheelruntime/runtime.py +161 -0
- kivyforge/lock/wheelruntime/serialize.py +245 -0
- kivyforge/platforms/__init__.py +114 -0
- kivyforge/platforms/android/__init__.py +140 -0
- kivyforge/platforms/android/adb.py +215 -0
- kivyforge/platforms/android/bootstrap/__init__.py +7 -0
- kivyforge/platforms/android/bootstrap/contract.py +166 -0
- kivyforge/platforms/android/bootstrap/render.py +244 -0
- kivyforge/platforms/android/bootstrap/templates/androidtest/KivyforgeContractTest.java +76 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivy_bootstrap.py +50 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_bootstrap.py +54 -0
- kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_selftest.py +97 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/CMakeLists.txt +20 -0
- kivyforge/platforms/android/bootstrap/templates/cpp/main.c +150 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/jnius/NativeInvocationHandler.java +48 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonActivity.java +75 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonBundle.java +132 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonService.java +189 -0
- kivyforge/platforms/android/bootstrap/templates/java/org/renpy/android/Hardware.java +276 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDevice.java +22 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceBLESteamController.java +650 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceUSB.java +309 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLActivity.java +2120 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLAudioManager.java +514 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLControllerManager.java +856 -0
- kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLSurface.java +405 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/LICENSE-SDL.txt +18 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/SDL_REVISION.txt +3 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDevice.java +21 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceBLESteamController.java +829 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceManager.java +698 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceUSB.java +354 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDL.java +90 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLActivity.java +2240 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLAudioManager.java +126 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLControllerManager.java +1010 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLDummyEdit.java +66 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLInputConnection.java +136 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSensorManager.java +73 -0
- kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSurface.java +464 -0
- kivyforge/platforms/android/cli.py +1023 -0
- kivyforge/platforms/android/doctor.py +899 -0
- kivyforge/platforms/android/elf.py +148 -0
- kivyforge/platforms/android/generate/__init__.py +1 -0
- kivyforge/platforms/android/generate/manifest.py +261 -0
- kivyforge/platforms/android/generate/project.py +462 -0
- kivyforge/platforms/android/generate/services.py +187 -0
- kivyforge/platforms/android/gradle_wrapper/NOTICE +3 -0
- kivyforge/platforms/android/gradle_wrapper/SHA256SUMS +1 -0
- kivyforge/platforms/android/gradle_wrapper/gradle-wrapper.jar +0 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew +164 -0
- kivyforge/platforms/android/gradle_wrapper/gradlew.bat +90 -0
- kivyforge/platforms/android/gradlew.py +60 -0
- kivyforge/platforms/android/icons.py +237 -0
- kivyforge/platforms/android/lock/__init__.py +1 -0
- kivyforge/platforms/android/lock/archives.py +109 -0
- kivyforge/platforms/android/lock/builder.py +387 -0
- kivyforge/platforms/android/lock/markers.py +71 -0
- kivyforge/platforms/android/lock/maven.py +252 -0
- kivyforge/platforms/android/lock/model.py +113 -0
- kivyforge/platforms/android/lock/python_meta.py +199 -0
- kivyforge/platforms/android/lock/reader.py +206 -0
- kivyforge/platforms/android/lock/resolver.py +276 -0
- kivyforge/platforms/android/lock/writer.py +121 -0
- kivyforge/platforms/android/policy.py +214 -0
- kivyforge/platforms/android/signing.py +145 -0
- kivyforge/platforms/android/smoke.py +43 -0
- kivyforge/platforms/android/splash.py +293 -0
- kivyforge/platforms/android/stage/__init__.py +1 -0
- kivyforge/platforms/android/stage/bundle.py +295 -0
- kivyforge/platforms/android/stage/jnilibs.py +186 -0
- kivyforge/platforms/android/stage/runtime.py +61 -0
- kivyforge/platforms/android/stage/wheels.py +106 -0
- kivyforge/platforms/android/toolchain.py +29 -0
- kivyforge/platforms/base.py +157 -0
- kivyforge/platforms/ios/__init__.py +129 -0
- kivyforge/platforms/ios/assets.py +193 -0
- kivyforge/platforms/ios/buildsettings.py +128 -0
- kivyforge/platforms/ios/cli.py +543 -0
- kivyforge/platforms/ios/doctor.py +410 -0
- kivyforge/platforms/ios/entitlements.py +34 -0
- kivyforge/platforms/ios/generator.py +318 -0
- kivyforge/platforms/ios/lock/__init__.py +71 -0
- kivyforge/platforms/ios/lock/builder.py +393 -0
- kivyforge/platforms/ios/lock/markers.py +69 -0
- kivyforge/platforms/ios/lock/model.py +95 -0
- kivyforge/platforms/ios/lock/python_meta.py +187 -0
- kivyforge/platforms/ios/lock/reader.py +191 -0
- kivyforge/platforms/ios/lock/resolver.py +304 -0
- kivyforge/platforms/ios/lock/spm.py +217 -0
- kivyforge/platforms/ios/lock/writer.py +114 -0
- kivyforge/platforms/ios/lock/xcframework.py +188 -0
- kivyforge/platforms/ios/materialize.py +59 -0
- kivyforge/platforms/ios/plist.py +91 -0
- kivyforge/platforms/ios/privacy.py +39 -0
- kivyforge/platforms/ios/skeleton.py +165 -0
- kivyforge/platforms/ios/sources.py +63 -0
- kivyforge/platforms/ios/staging.py +225 -0
- kivyforge/platforms/ios/swift_packages.py +324 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.h +34 -0
- kivyforge/platforms/ios/templates/kivyforge_bootstrap.m +146 -0
- kivyforge/platforms/ios/templates/main.m +15 -0
- kivyforge/platforms/ios/templates/main_config.h.in +12 -0
- kivyforge/platforms/ios/xcframeworks.py +194 -0
- kivyforge/platforms/ios/xcode/__init__.py +76 -0
- kivyforge/platforms/ios/xcode/commands.py +296 -0
- kivyforge/platforms/ios/xcode/runner.py +316 -0
- kivyforge/platforms/linux/__init__.py +120 -0
- kivyforge/platforms/linux/appimage.py +169 -0
- kivyforge/platforms/linux/bundle.py +235 -0
- kivyforge/platforms/linux/cli.py +232 -0
- kivyforge/platforms/linux/desktop.py +71 -0
- kivyforge/platforms/linux/doctor.py +438 -0
- kivyforge/platforms/linux/elftools.py +95 -0
- kivyforge/platforms/linux/icons.py +129 -0
- kivyforge/platforms/linux/launcher.py +107 -0
- kivyforge/platforms/linux/lock/__init__.py +126 -0
- kivyforge/platforms/linux/lock/profile.py +254 -0
- kivyforge/platforms/linux/lock/runtime.py +75 -0
- kivyforge/platforms/linux/native_stage.py +47 -0
- kivyforge/platforms/linux/runtime_stage.py +107 -0
- kivyforge/platforms/linux/wheels_stage.py +103 -0
- kivyforge/platforms/macos/__init__.py +121 -0
- kivyforge/platforms/macos/bundle.py +255 -0
- kivyforge/platforms/macos/cli.py +269 -0
- kivyforge/platforms/macos/doctor.py +480 -0
- kivyforge/platforms/macos/icns.py +75 -0
- kivyforge/platforms/macos/launcher.py +118 -0
- kivyforge/platforms/macos/lock/__init__.py +112 -0
- kivyforge/platforms/macos/lock/profile.py +119 -0
- kivyforge/platforms/macos/lock/runtime.py +58 -0
- kivyforge/platforms/macos/machotools.py +138 -0
- kivyforge/platforms/macos/native_stage.py +47 -0
- kivyforge/platforms/macos/notarize.py +143 -0
- kivyforge/platforms/macos/plist.py +37 -0
- kivyforge/platforms/macos/runtime_stage.py +110 -0
- kivyforge/platforms/macos/signing.py +78 -0
- kivyforge/platforms/macos/wheels_stage.py +108 -0
- kivyforge/platforms/windows/__init__.py +133 -0
- kivyforge/platforms/windows/assets.py +76 -0
- kivyforge/platforms/windows/bundle.py +298 -0
- kivyforge/platforms/windows/cli.py +314 -0
- kivyforge/platforms/windows/doctor.py +563 -0
- kivyforge/platforms/windows/fsswap.py +87 -0
- kivyforge/platforms/windows/icons.py +64 -0
- kivyforge/platforms/windows/launcher/__init__.py +193 -0
- kivyforge/platforms/windows/launcher/build_launcher.py +507 -0
- kivyforge/platforms/windows/launcher/launcher.c +379 -0
- kivyforge/platforms/windows/lock/__init__.py +112 -0
- kivyforge/platforms/windows/lock/profile.py +101 -0
- kivyforge/platforms/windows/lock/runtime.py +64 -0
- kivyforge/platforms/windows/naming.py +52 -0
- kivyforge/platforms/windows/native_stage.py +66 -0
- kivyforge/platforms/windows/petools.py +98 -0
- kivyforge/platforms/windows/rcedit.py +116 -0
- kivyforge/platforms/windows/runtime_stage.py +221 -0
- kivyforge/platforms/windows/signing.py +168 -0
- kivyforge/platforms/windows/vendor/LICENSE.rcedit +29 -0
- kivyforge/platforms/windows/vendor/NOTICE +17 -0
- kivyforge/platforms/windows/vendor/SHA256SUMS +4 -0
- kivyforge/platforms/windows/vendor/TOOLSET.txt +4 -0
- kivyforge/platforms/windows/vendor/__init__.py +12 -0
- kivyforge/platforms/windows/vendor/fetch_rcedit.py +97 -0
- kivyforge/platforms/windows/vendor/launcher-amd64.exe +0 -0
- kivyforge/platforms/windows/vendor/rcedit-x64.exe +0 -0
- kivyforge/platforms/windows/wheels_stage.py +139 -0
- kivyforge-3.0.0.dev0.dist-info/METADATA +609 -0
- kivyforge-3.0.0.dev0.dist-info/RECORD +225 -0
- kivyforge-3.0.0.dev0.dist-info/WHEEL +5 -0
- kivyforge-3.0.0.dev0.dist-info/entry_points.txt +3 -0
- kivyforge-3.0.0.dev0.dist-info/licenses/LICENSE +21 -0
- kivyforge-3.0.0.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""The AppDir ``AppRun`` launcher — a POSIX shell script (linux-spec).
|
|
2
|
+
|
|
3
|
+
AppImage does not require an ELF ``AppRun``, and Linux has no analog of the
|
|
4
|
+
Finder/LaunchServices problem that forced the compiled Mach-O stub on macOS, so
|
|
5
|
+
the launcher is a small shell script. It resolves its own directory (so the
|
|
6
|
+
AppDir stays relocatable), points the bundled CPython at its own home + the
|
|
7
|
+
app's ``lib``/``app`` directories, sets the SDL WM_CLASS so the window groups
|
|
8
|
+
under the ``.desktop``'s ``StartupWMClass``, and ``exec``s the interpreter on
|
|
9
|
+
the entry-point module.
|
|
10
|
+
|
|
11
|
+
By default there is deliberately **no ``LD_LIBRARY_PATH``**: PBS rpaths are
|
|
12
|
+
``$ORIGIN``-relative and manylinux wheels vendor their own native libs
|
|
13
|
+
(auditwheel), so the host's libGL/libEGL are found on the normal loader path.
|
|
14
|
+
The one exception is when the app declares ``[tool.kivy.linux.native.binaries]``:
|
|
15
|
+
then ``usr/bin`` is *prepended* to ``PATH`` (helpers win by name) and *appended*
|
|
16
|
+
to ``LD_LIBRARY_PATH`` (declared libs load by soname but never shadow the host's
|
|
17
|
+
or the wheels' own ``.so``s — decided Option B in linux-spec). The
|
|
18
|
+
PATH-prepend / LD_LIBRARY_PATH-append asymmetry is deliberate: declared tools
|
|
19
|
+
win; declared libs never shadow the host.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import keyword
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
from . import AppDirError
|
|
28
|
+
|
|
29
|
+
# ``{entry}`` is a ``/``-joined module path (a dotted ``entry_point`` such as
|
|
30
|
+
# ``pkg.start`` maps to ``pkg/start``); ``{app_id}`` is a validated ``.desktop``
|
|
31
|
+
# basename (letters/digits/hyphen/period) — both safe to inline.
|
|
32
|
+
_APPRUN = """\
|
|
33
|
+
#!/bin/sh
|
|
34
|
+
# Generated by kivyforge — do not edit.
|
|
35
|
+
HERE="$(dirname "$(readlink -f "$0")")"
|
|
36
|
+
|
|
37
|
+
export PYTHONHOME="$HERE/usr/python"
|
|
38
|
+
export PYTHONPATH="$HERE/usr/app:$HERE/usr/lib"
|
|
39
|
+
export PYTHONNOUSERSITE=1
|
|
40
|
+
{native_block}
|
|
41
|
+
# Match the window's WM_CLASS to the .desktop StartupWMClass so the app groups
|
|
42
|
+
# under its own icon on both X11 and Wayland.
|
|
43
|
+
export SDL_VIDEO_X11_WMCLASS="{app_id}"
|
|
44
|
+
export SDL_VIDEO_WAYLAND_WMCLASS="{app_id}"
|
|
45
|
+
|
|
46
|
+
exec "$HERE/usr/python/bin/python3" "$HERE/usr/app/{entry}.py" "$@"
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
# Only emitted when the app declares native binaries (no dead env vars
|
|
50
|
+
# otherwise — symmetry with the "no empty bin/" rule). PATH is prepended so a
|
|
51
|
+
# bundled helper wins by name; LD_LIBRARY_PATH is appended so the host's and the
|
|
52
|
+
# wheels' auditwheel-vendored .so's still win the search and a declared lib is
|
|
53
|
+
# only a last resort (decided Option B, linux-spec).
|
|
54
|
+
_NATIVE_BINARIES_BLOCK = """
|
|
55
|
+
# Declared native binaries (see linux-spec): helpers by name, libs by soname.
|
|
56
|
+
export PATH="$HERE/usr/bin:$PATH"
|
|
57
|
+
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$HERE/usr/bin"
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def entry_point_rel_path(entry_point: str) -> str:
|
|
62
|
+
"""Map a (possibly dotted) ``entry_point`` to its ``/``-joined module path.
|
|
63
|
+
|
|
64
|
+
``"main"`` -> ``"main"``; ``"pkg.start"`` -> ``"pkg/start"`` (i.e.
|
|
65
|
+
``usr/app/pkg/start.py``), matching the ``app_dir``/``entry_point`` layout
|
|
66
|
+
contract in the shared pyproject spec.
|
|
67
|
+
"""
|
|
68
|
+
return "/".join(entry_point.split("."))
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def render_apprun(
|
|
72
|
+
*, entry_point: str, app_id: str, has_native_binaries: bool = False
|
|
73
|
+
) -> str:
|
|
74
|
+
"""The ``AppRun`` shell source for *entry_point* + *app_id* (pure/testable).
|
|
75
|
+
|
|
76
|
+
*entry_point* may be a dotted module name (e.g. ``pkg.start``); each segment
|
|
77
|
+
must be a valid, non-keyword Python identifier. When *has_native_binaries*
|
|
78
|
+
is set, ``usr/bin`` is prepended to ``PATH`` and appended to
|
|
79
|
+
``LD_LIBRARY_PATH``; otherwise the block is omitted entirely.
|
|
80
|
+
"""
|
|
81
|
+
parts = entry_point.split(".")
|
|
82
|
+
if not entry_point or not all(
|
|
83
|
+
p.isidentifier() and not keyword.iskeyword(p) for p in parts
|
|
84
|
+
):
|
|
85
|
+
raise AppDirError(f"entry_point {entry_point!r} is not a valid module name.")
|
|
86
|
+
native_block = _NATIVE_BINARIES_BLOCK if has_native_binaries else ""
|
|
87
|
+
return _APPRUN.format(
|
|
88
|
+
entry=entry_point_rel_path(entry_point),
|
|
89
|
+
app_id=app_id,
|
|
90
|
+
native_block=native_block,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def build_apprun(
|
|
95
|
+
dest: Path, *, entry_point: str, app_id: str, has_native_binaries: bool = False
|
|
96
|
+
) -> None:
|
|
97
|
+
"""Write an executable ``AppRun`` at *dest*."""
|
|
98
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
99
|
+
dest.write_text(
|
|
100
|
+
render_apprun(
|
|
101
|
+
entry_point=entry_point,
|
|
102
|
+
app_id=app_id,
|
|
103
|
+
has_native_binaries=has_native_binaries,
|
|
104
|
+
),
|
|
105
|
+
"utf-8",
|
|
106
|
+
)
|
|
107
|
+
dest.chmod(0o755)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Linux lock stack (``pylock.linux.toml``).
|
|
2
|
+
|
|
3
|
+
A thin Linux *profile* (:class:`LinuxProfile`) over the generic wheel+runtime
|
|
4
|
+
lock engine (``kivyforge.lock.wheelruntime``). This module is the stable Linux
|
|
5
|
+
public surface: it binds the profile into the core and re-exports the engine's
|
|
6
|
+
types under Linux-friendly names so callers (the CLI, tests) never reach into
|
|
7
|
+
the generic package directly.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from kivyforge.config.model import Config
|
|
17
|
+
from kivyforge.lock.wheelruntime import (
|
|
18
|
+
PythonRuntime as LinuxPythonRuntime,
|
|
19
|
+
)
|
|
20
|
+
from kivyforge.lock.wheelruntime import (
|
|
21
|
+
ResolvedPackage,
|
|
22
|
+
ResolvedWheel,
|
|
23
|
+
RuntimeArtifact,
|
|
24
|
+
RuntimeProvider,
|
|
25
|
+
RuntimeProviderError,
|
|
26
|
+
Variant,
|
|
27
|
+
WheelResolver,
|
|
28
|
+
WheelResolverError,
|
|
29
|
+
WheelRuntimeBuildError,
|
|
30
|
+
WheelRuntimeLock,
|
|
31
|
+
build_wheel_runtime_lock,
|
|
32
|
+
diff_summary,
|
|
33
|
+
get_wheel_resolver,
|
|
34
|
+
semantic_equal,
|
|
35
|
+
)
|
|
36
|
+
from kivyforge.lock.wheelruntime import serialize as _ser
|
|
37
|
+
|
|
38
|
+
from .profile import (
|
|
39
|
+
LinuxProfile,
|
|
40
|
+
effective_glibc_floor,
|
|
41
|
+
is_plain_linux_tag,
|
|
42
|
+
linux_wheel_arch,
|
|
43
|
+
linux_wheel_coverage,
|
|
44
|
+
manylinux_platform_tags,
|
|
45
|
+
plain_linux_wheel_warning,
|
|
46
|
+
wheel_glibc_level,
|
|
47
|
+
)
|
|
48
|
+
from .runtime import PythonBuildStandaloneProvider
|
|
49
|
+
|
|
50
|
+
# Linux-friendly aliases for the generic engine types.
|
|
51
|
+
LinuxLockfile = WheelRuntimeLock
|
|
52
|
+
LinuxBuildError = WheelRuntimeBuildError
|
|
53
|
+
LinuxResolverError = WheelResolverError
|
|
54
|
+
|
|
55
|
+
_PROFILE = LinuxProfile()
|
|
56
|
+
|
|
57
|
+
__all__ = [
|
|
58
|
+
"LinuxBuildError",
|
|
59
|
+
"LinuxLockfile",
|
|
60
|
+
"LinuxProfile",
|
|
61
|
+
"LinuxPythonRuntime",
|
|
62
|
+
"LinuxResolverError",
|
|
63
|
+
"PythonBuildStandaloneProvider",
|
|
64
|
+
"ResolvedPackage",
|
|
65
|
+
"ResolvedWheel",
|
|
66
|
+
"RuntimeArtifact",
|
|
67
|
+
"RuntimeProvider",
|
|
68
|
+
"RuntimeProviderError",
|
|
69
|
+
"Variant",
|
|
70
|
+
"WheelResolver",
|
|
71
|
+
"build_linux_lockfile",
|
|
72
|
+
"diff_summary",
|
|
73
|
+
"dumps",
|
|
74
|
+
"effective_glibc_floor",
|
|
75
|
+
"get_linux_resolver",
|
|
76
|
+
"is_plain_linux_tag",
|
|
77
|
+
"linux_wheel_arch",
|
|
78
|
+
"linux_wheel_coverage",
|
|
79
|
+
"load",
|
|
80
|
+
"loads",
|
|
81
|
+
"manylinux_platform_tags",
|
|
82
|
+
"plain_linux_wheel_warning",
|
|
83
|
+
"semantic_equal",
|
|
84
|
+
"wheel_glibc_level",
|
|
85
|
+
]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_linux_lockfile(
|
|
89
|
+
config: Config,
|
|
90
|
+
pyproject_text: str,
|
|
91
|
+
*,
|
|
92
|
+
project_root: Path | None = None,
|
|
93
|
+
resolver: WheelResolver | None = None,
|
|
94
|
+
runtime_provider: RuntimeProvider | None = None,
|
|
95
|
+
offline: bool = False,
|
|
96
|
+
now: datetime | None = None,
|
|
97
|
+
on_warning: Callable[[str], None] | None = None,
|
|
98
|
+
) -> LinuxLockfile:
|
|
99
|
+
return build_wheel_runtime_lock(
|
|
100
|
+
_PROFILE,
|
|
101
|
+
config,
|
|
102
|
+
pyproject_text,
|
|
103
|
+
project_root=project_root,
|
|
104
|
+
resolver=resolver,
|
|
105
|
+
runtime_provider=runtime_provider,
|
|
106
|
+
native_binaries=config.linux.binaries if config.linux else (),
|
|
107
|
+
offline=offline,
|
|
108
|
+
now=now,
|
|
109
|
+
on_warning=on_warning,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def dumps(lock: LinuxLockfile) -> str:
|
|
114
|
+
return _ser.dumps(lock)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def loads(text: str) -> LinuxLockfile:
|
|
118
|
+
return _ser.loads(text, platform="linux")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def load(path: str | Path) -> LinuxLockfile:
|
|
122
|
+
return _ser.load(path, platform="linux")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def get_linux_resolver(backend: str = "pip", **kwargs) -> WheelResolver:
|
|
126
|
+
return get_wheel_resolver(backend, **kwargs)
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Linux lock profile — the platform-specific inputs to the wheel+runtime core.
|
|
2
|
+
|
|
3
|
+
Linux variants are CPU architectures (``x86_64`` only this phase). Wheels use
|
|
4
|
+
manylinux platform tags; because pip does not expand the manylinux hierarchy
|
|
5
|
+
from a single explicit ``--platform`` (linux-spec spike), each variant requests
|
|
6
|
+
the full ladder of compatible tags at or below the glibc floor in one pip
|
|
7
|
+
invocation. The bundled runtime comes from python-build-standalone (linux-gnu).
|
|
8
|
+
Everything else — resolve/serialize/build orchestration — is the shared core.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
|
|
15
|
+
from kivyforge.config.errors import ConfigError
|
|
16
|
+
from kivyforge.config.model import Config
|
|
17
|
+
from kivyforge.lock.wheelruntime.model import WheelRuntimeLock
|
|
18
|
+
from kivyforge.lock.wheelruntime.profile import PlatformLockProfile
|
|
19
|
+
from kivyforge.lock.wheelruntime.resolver import Variant
|
|
20
|
+
from kivyforge.lock.wheelruntime.runtime import RuntimeProvider
|
|
21
|
+
|
|
22
|
+
from .runtime import DEFAULT_GLIBC_FLOOR, PythonBuildStandaloneProvider
|
|
23
|
+
|
|
24
|
+
VALID_WHEEL_ARCHS = frozenset({"x86_64"})
|
|
25
|
+
|
|
26
|
+
# Legacy manylinux aliases and the perennial (PEP 600) glibc minor they map to.
|
|
27
|
+
_LEGACY_ALIASES = {5: "manylinux1", 12: "manylinux2010", 17: "manylinux2014"}
|
|
28
|
+
# manylinux1 (glibc 2.5) is the oldest tag; nothing predates it.
|
|
29
|
+
_MIN_MANYLINUX_MINOR = 5
|
|
30
|
+
|
|
31
|
+
_PERENNIAL_RE = re.compile(r"^manylinux_(\d+)_(\d+)_(?P<arch>.+)$")
|
|
32
|
+
_LINUX_TAG_RE = re.compile(
|
|
33
|
+
r"^(?:linux|manylinux1|manylinux2010|manylinux2014|manylinux_\d+_\d+)"
|
|
34
|
+
r"_(?P<arch>.+)$"
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _floor_parts(floor: str) -> tuple[int, int]:
|
|
39
|
+
"""``"2.17"`` -> ``(2, 17)``; tolerant of extra/absent components."""
|
|
40
|
+
nums = [int(p) for p in re.findall(r"\d+", floor)]
|
|
41
|
+
major = nums[0] if nums else 2
|
|
42
|
+
minor = nums[1] if len(nums) > 1 else 0
|
|
43
|
+
return major, minor
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def manylinux_platform_tags(floor: str, arch: str) -> tuple[str, ...]:
|
|
47
|
+
"""The pip ``--platform`` tags to request for a glibc *floor* + *arch*.
|
|
48
|
+
|
|
49
|
+
Returns the perennial ladder from the floor down to manylinux1 (glibc 2.5),
|
|
50
|
+
plus the legacy aliases (``manylinux1``/``manylinux2010``/``manylinux2014``)
|
|
51
|
+
at or below the floor. The floor tag is first (the variant's identity tag).
|
|
52
|
+
A wheel matching *any* of these runs on a host meeting the floor, so pip —
|
|
53
|
+
given all tags in one invocation — locks the newest compatible version.
|
|
54
|
+
"""
|
|
55
|
+
major, minor = _floor_parts(floor)
|
|
56
|
+
tags: list[str] = []
|
|
57
|
+
if major == 2:
|
|
58
|
+
for m in range(minor, _MIN_MANYLINUX_MINOR - 1, -1):
|
|
59
|
+
tags.append(f"manylinux_{major}_{m}_{arch}")
|
|
60
|
+
for m, alias in sorted(_LEGACY_ALIASES.items()):
|
|
61
|
+
if m <= minor:
|
|
62
|
+
tags.append(f"{alias}_{arch}")
|
|
63
|
+
else: # pragma: no cover - no manylinux_3_x exists yet
|
|
64
|
+
tags.append(f"manylinux_{major}_{minor}_{arch}")
|
|
65
|
+
return tuple(tags)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def linux_wheel_arch(tag: str) -> str | None:
|
|
69
|
+
"""The architecture a single Linux wheel platform (sub)tag targets.
|
|
70
|
+
|
|
71
|
+
``manylinux2014_x86_64`` / ``manylinux_2_17_x86_64`` / ``linux_x86_64`` ->
|
|
72
|
+
``x86_64``. ``musllinux_*`` never covers (returns ``None``). A tag that is
|
|
73
|
+
not a linux tag at all also returns ``None``.
|
|
74
|
+
"""
|
|
75
|
+
if tag.startswith("musllinux"):
|
|
76
|
+
return None
|
|
77
|
+
match = _LINUX_TAG_RE.match(tag)
|
|
78
|
+
return match.group("arch") if match else None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def is_plain_linux_tag(sub_tag: str) -> bool:
|
|
82
|
+
"""A bare ``linux_<arch>`` platform tag (no manylinux/musllinux prefix).
|
|
83
|
+
|
|
84
|
+
Plain ``linux_*`` wheels carry **no glibc promise** — the tag says nothing
|
|
85
|
+
about which glibc the wheel was built against — so a distro-built one tied
|
|
86
|
+
to a newer glibc would abort the AppImage on older hosts.
|
|
87
|
+
"""
|
|
88
|
+
return sub_tag.startswith("linux_")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def plain_linux_wheel_warning(wheel_name: str, sub_tag: str) -> str:
|
|
92
|
+
"""The mandated warning for accepting a vendored plain ``linux_*`` wheel."""
|
|
93
|
+
return (
|
|
94
|
+
f"warning: accepting vendored wheel {wheel_name} on its {sub_tag} tag; "
|
|
95
|
+
f"plain linux_* wheels make no glibc promise, so the AppImage may fail "
|
|
96
|
+
f"on hosts with an older glibc than this wheel's build host. Portability "
|
|
97
|
+
f"is your call (prefer a manylinux-tagged wheel where available)."
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def linux_wheel_coverage(wheel, archs: tuple[str, ...]) -> tuple[set[str], str | None]:
|
|
102
|
+
"""Archs a locked *wheel* covers on Linux, plus an optional warning.
|
|
103
|
+
|
|
104
|
+
A manylinux/legacy tag covers its arch unconditionally. A plain
|
|
105
|
+
``linux_<arch>`` tag covers **only when the wheel is vendored via
|
|
106
|
+
find_links** (``wheel.path`` is set) — a plain wheel pulled from
|
|
107
|
+
PyPI/an extra index makes no glibc promise and does *not* count toward
|
|
108
|
+
coverage — and yields the mandated warning when it does.
|
|
109
|
+
"""
|
|
110
|
+
from_find_links = wheel.path is not None
|
|
111
|
+
covered: set[str] = set()
|
|
112
|
+
warning: str | None = None
|
|
113
|
+
for sub in wheel.platform_tag.split("."):
|
|
114
|
+
arch = linux_wheel_arch(sub)
|
|
115
|
+
if arch not in archs:
|
|
116
|
+
continue
|
|
117
|
+
if is_plain_linux_tag(sub):
|
|
118
|
+
if from_find_links:
|
|
119
|
+
covered.add(arch)
|
|
120
|
+
warning = plain_linux_wheel_warning(wheel.name, sub)
|
|
121
|
+
else:
|
|
122
|
+
covered.add(arch)
|
|
123
|
+
return covered, warning
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _subtag_glibc_level(tag: str) -> tuple[int, int] | None:
|
|
127
|
+
"""The (major, minor) glibc a single manylinux sub-tag requires, or None."""
|
|
128
|
+
if tag.startswith("musllinux"):
|
|
129
|
+
return None
|
|
130
|
+
match = _PERENNIAL_RE.match(tag)
|
|
131
|
+
if match:
|
|
132
|
+
return int(match.group(1)), int(match.group(2))
|
|
133
|
+
if tag.startswith("manylinux1_"):
|
|
134
|
+
return 2, 5
|
|
135
|
+
if tag.startswith("manylinux2010_"):
|
|
136
|
+
return 2, 12
|
|
137
|
+
if tag.startswith("manylinux2014_"):
|
|
138
|
+
return 2, 17
|
|
139
|
+
return None # plain linux_* makes no glibc promise
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def wheel_glibc_level(platform_tag: str) -> tuple[int, int] | None:
|
|
143
|
+
"""The glibc a wheel requires = the *lowest* level among its sub-tags.
|
|
144
|
+
|
|
145
|
+
A compound (dot-joined) tag declares the wheel valid under any of its
|
|
146
|
+
platforms, so its real requirement is the least demanding one.
|
|
147
|
+
"""
|
|
148
|
+
levels = [
|
|
149
|
+
lvl
|
|
150
|
+
for sub in platform_tag.split(".")
|
|
151
|
+
if (lvl := _subtag_glibc_level(sub)) is not None
|
|
152
|
+
]
|
|
153
|
+
return min(levels) if levels else None
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def effective_glibc_floor(lock: WheelRuntimeLock) -> str:
|
|
157
|
+
"""The artifact's true host glibc requirement (derived, linux-spec).
|
|
158
|
+
|
|
159
|
+
``max(runtime floor, highest locked wheel manylinux level)``. Computed on
|
|
160
|
+
demand from the locked wheels for ``doctor``/docs rather than stored as a
|
|
161
|
+
distinct lock field, keeping the shared lock model platform-agnostic.
|
|
162
|
+
"""
|
|
163
|
+
floor = _floor_parts(lock.python_runtime.floor or DEFAULT_GLIBC_FLOOR)
|
|
164
|
+
for pkg in lock.packages:
|
|
165
|
+
for wheel in pkg.wheels:
|
|
166
|
+
level = wheel_glibc_level(wheel.platform_tag)
|
|
167
|
+
if level is not None and level > floor:
|
|
168
|
+
floor = level
|
|
169
|
+
return f"{floor[0]}.{floor[1]}"
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
class LinuxProfile(PlatformLockProfile):
|
|
173
|
+
platform = "linux"
|
|
174
|
+
|
|
175
|
+
def overlay(self, config: Config):
|
|
176
|
+
return config.linux
|
|
177
|
+
|
|
178
|
+
def missing_overlay_error(self) -> str:
|
|
179
|
+
return "pyproject.toml has no [tool.kivy.linux] table; nothing to lock."
|
|
180
|
+
|
|
181
|
+
def python_version(self, config: Config) -> str:
|
|
182
|
+
# [tool.kivy.linux.python].version is required (the loader raises a
|
|
183
|
+
# ConfigError when it is missing), so it is always set here. Never
|
|
184
|
+
# silently substitute a hidden default — that would pin an unexpected
|
|
185
|
+
# (and possibly unreleased) Python instead of surfacing the misconfig.
|
|
186
|
+
version = config.linux_required.python_version
|
|
187
|
+
if not version:
|
|
188
|
+
raise ConfigError(
|
|
189
|
+
"missing required [tool.kivy.linux.python].version",
|
|
190
|
+
key_path="tool.kivy.linux.python.version",
|
|
191
|
+
)
|
|
192
|
+
return version
|
|
193
|
+
|
|
194
|
+
def _floor(self, config: Config) -> str:
|
|
195
|
+
return config.linux_required.glibc_floor or DEFAULT_GLIBC_FLOOR
|
|
196
|
+
|
|
197
|
+
def variants(self, config: Config) -> tuple[Variant, ...]:
|
|
198
|
+
floor = self._floor(config)
|
|
199
|
+
variants: list[Variant] = []
|
|
200
|
+
for arch in config.linux_required.archs:
|
|
201
|
+
tags = manylinux_platform_tags(floor, arch)
|
|
202
|
+
variants.append(
|
|
203
|
+
Variant(
|
|
204
|
+
arch=arch,
|
|
205
|
+
platform_tag=tags[0],
|
|
206
|
+
extra_platform_tags=tags[1:],
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
return tuple(variants)
|
|
210
|
+
|
|
211
|
+
def wheel_covers(self, platform_tag: str, archs: tuple[str, ...]) -> set[str]:
|
|
212
|
+
covered: set[str] = set()
|
|
213
|
+
for sub in platform_tag.split("."):
|
|
214
|
+
arch = linux_wheel_arch(sub)
|
|
215
|
+
if arch in archs:
|
|
216
|
+
covered.add(arch)
|
|
217
|
+
return covered
|
|
218
|
+
|
|
219
|
+
def wheel_coverage(
|
|
220
|
+
self, wheel, archs: tuple[str, ...]
|
|
221
|
+
) -> tuple[set[str], str | None]:
|
|
222
|
+
# Source-gate plain linux_* wheels (accepted only from find_links) and
|
|
223
|
+
# emit the mandated no-glibc-promise warning (linux-spec coverage rule).
|
|
224
|
+
return linux_wheel_coverage(wheel, archs)
|
|
225
|
+
|
|
226
|
+
def runtime_provider(self, config: Config) -> RuntimeProvider:
|
|
227
|
+
return PythonBuildStandaloneProvider()
|
|
228
|
+
|
|
229
|
+
def declared_floor(self, config: Config) -> str | None:
|
|
230
|
+
return config.linux_required.glibc_floor
|
|
231
|
+
|
|
232
|
+
def coverage_error(self, name: str, missing: list[str]) -> str:
|
|
233
|
+
return (
|
|
234
|
+
f"{name} has no manylinux wheel for arch(es): {', '.join(missing)} at "
|
|
235
|
+
f"the configured glibc floor.\n"
|
|
236
|
+
f" A compiled package must publish a manylinux wheel that runs on the "
|
|
237
|
+
f"floor to be locked reproducibly.\n"
|
|
238
|
+
f" Raise [tool.kivy.linux].glibc_floor to admit a newer-manylinux "
|
|
239
|
+
f"wheel, or supply the wheel via extra_index_urls/find_links."
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
def floor_error(self, declared: str, runtime_floor: str, version: str) -> str:
|
|
243
|
+
return (
|
|
244
|
+
f"glibc_floor {declared} is below the glibc {runtime_floor} floor "
|
|
245
|
+
f"required by the python-build-standalone {version} runtime.\n"
|
|
246
|
+
f" Raise [tool.kivy.linux].glibc_floor to at least {runtime_floor}."
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
def wheel_scope_hint(self) -> str:
|
|
250
|
+
return (
|
|
251
|
+
"Vendored wheels must live under the project directory, a sibling "
|
|
252
|
+
"directory, or the enclosing repository (e.g. a wheels/ directory "
|
|
253
|
+
"beside pyproject.toml)."
|
|
254
|
+
)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Linux runtime provider — python-build-standalone with linux-gnu triples.
|
|
2
|
+
|
|
3
|
+
A one-line specialization of the generic :class:`PbsProvider`: it fixes the
|
|
4
|
+
arch→target-triple map to Linux's baseline ``*-unknown-linux-gnu`` builds (not
|
|
5
|
+
the ``_v2``/``_v3`` microarchitecture variants), and otherwise inherits the
|
|
6
|
+
shared PBS resolution + injectable metadata fetcher. The linux-gnu
|
|
7
|
+
``install_only`` archives share the same relocatable unix-prefix layout as the
|
|
8
|
+
darwin ones, so no patchelf pass is needed (linux-spec).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from kivyforge.lock.wheelruntime.runtime import (
|
|
14
|
+
MetadataFetcher,
|
|
15
|
+
PbsProvider,
|
|
16
|
+
ReleaseAsset,
|
|
17
|
+
RuntimeProvider,
|
|
18
|
+
RuntimeProviderError,
|
|
19
|
+
pbs_asset_glob,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"LINUX_TRIPLES",
|
|
24
|
+
"PythonBuildStandaloneProvider",
|
|
25
|
+
"ReleaseAsset",
|
|
26
|
+
"RuntimeProvider",
|
|
27
|
+
"RuntimeProviderError",
|
|
28
|
+
"get_runtime_provider",
|
|
29
|
+
"pbs_asset_name",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# The manylinux2014-class glibc floor PBS's linux-gnu builds inherit from their
|
|
33
|
+
# build host. Recorded on the runtime so the lock/doctor can state (and the
|
|
34
|
+
# builder can validate against) the artifact's host requirement.
|
|
35
|
+
#
|
|
36
|
+
# IMPORTANT — this is a *pinned assumption* about PBS's build baseline, not a
|
|
37
|
+
# value derived from inspecting the resolved artifact. PBS's ``install_only``
|
|
38
|
+
# archives carry no structured glibc metadata, and `kivyforge lock` records only
|
|
39
|
+
# the artifact URL + SHA-256 (it does not download the runtime), so there is
|
|
40
|
+
# nothing to derive from at lock time. This constant is versioned with kivyforge:
|
|
41
|
+
# if PBS ever raises its linux-gnu baseline above 2.17, THIS VALUE MUST BE
|
|
42
|
+
# BUMPED IN LOCKSTEP, otherwise the lock/doctor would advertise a floor the
|
|
43
|
+
# binary no longer meets. (A deeper, deferred safeguard would ELF-inspect the
|
|
44
|
+
# staged ``bin/python3`` version-needs at build time to prove the floor.)
|
|
45
|
+
DEFAULT_GLIBC_FLOOR = "2.17"
|
|
46
|
+
|
|
47
|
+
# kivyforge arch name -> PBS/LLVM linux target triple (baseline microarch).
|
|
48
|
+
LINUX_TRIPLES = {
|
|
49
|
+
"x86_64": "x86_64-unknown-linux-gnu",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# Linux-facing alias for the generic PBS asset glob helper.
|
|
53
|
+
pbs_asset_name = pbs_asset_glob
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PythonBuildStandaloneProvider(PbsProvider):
|
|
57
|
+
"""PBS provider fixed to Linux gnu triples (glibc 2.17 floor by default)."""
|
|
58
|
+
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
metadata_fetcher: MetadataFetcher | None = None,
|
|
62
|
+
*,
|
|
63
|
+
floor: str | None = DEFAULT_GLIBC_FLOOR,
|
|
64
|
+
) -> None:
|
|
65
|
+
super().__init__(LINUX_TRIPLES, metadata_fetcher, floor=floor)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_runtime_provider(
|
|
69
|
+
name: str = "python-build-standalone", **kwargs
|
|
70
|
+
) -> RuntimeProvider:
|
|
71
|
+
if name in ("python-build-standalone", "pbs", "python_build_standalone"):
|
|
72
|
+
return PythonBuildStandaloneProvider(**kwargs)
|
|
73
|
+
raise RuntimeProviderError(
|
|
74
|
+
f"unknown runtime provider {name!r} (expected python-build-standalone)"
|
|
75
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""Stage locked native binaries into the AppDir's ``usr/bin`` (linux-spec).
|
|
2
|
+
|
|
3
|
+
The ``[tool.kivy.linux.native.binaries]`` channel: each entry is fetched +
|
|
4
|
+
SHA-256-verified from ``pylock.linux.toml`` (URL or vendored path), then staged
|
|
5
|
+
into ``usr/bin`` — a single native file copied in with its exec bit set, or a
|
|
6
|
+
``.zip`` / ``.tar.gz`` / ``.tgz`` of several extracted with a path-traversal
|
|
7
|
+
guard. The directory is created only when the lock actually pins binaries (no
|
|
8
|
+
empty ``bin/``). AppRun exposes ``usr/bin`` on ``PATH`` (helpers by name) and
|
|
9
|
+
appends it to ``LD_LIBRARY_PATH`` (libraries by soname).
|
|
10
|
+
|
|
11
|
+
The staging mechanics live in the shared
|
|
12
|
+
:mod:`kivyforge.artifacts.native_stage_util`; this module is the Linux-facing
|
|
13
|
+
wrapper that translates the neutral :class:`NativeStageError` into
|
|
14
|
+
``AppDirError``.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
from kivyforge.artifacts.cache import ArtifactCache
|
|
22
|
+
from kivyforge.artifacts.native_stage_util import NativeStageError, stage_binaries
|
|
23
|
+
|
|
24
|
+
from . import AppDirError
|
|
25
|
+
from .lock import LinuxLockfile
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def stage_native_binaries(
|
|
29
|
+
lock: LinuxLockfile,
|
|
30
|
+
usr_dir: Path,
|
|
31
|
+
*,
|
|
32
|
+
project_root: Path,
|
|
33
|
+
cache: ArtifactCache | None = None,
|
|
34
|
+
no_cache: bool = False,
|
|
35
|
+
) -> None:
|
|
36
|
+
"""Stage every pinned native binary for the lock into ``usr_dir/bin``."""
|
|
37
|
+
try:
|
|
38
|
+
stage_binaries(
|
|
39
|
+
lock.native_binaries,
|
|
40
|
+
usr_dir,
|
|
41
|
+
project_root=project_root,
|
|
42
|
+
cache=cache,
|
|
43
|
+
no_cache=no_cache,
|
|
44
|
+
bin_label="usr/bin",
|
|
45
|
+
)
|
|
46
|
+
except NativeStageError as exc:
|
|
47
|
+
raise AppDirError(str(exc)) from exc
|