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,269 @@
|
|
|
1
|
+
"""macOS dispatch for the shared ``build`` / ``run`` / ``package`` verbs.
|
|
2
|
+
|
|
3
|
+
Keeps the macOS ``.app`` flow out of the (iOS/Xcode-centric) verb modules: each
|
|
4
|
+
verb resolves the target platform and, when it is macOS, calls in here. Loads the
|
|
5
|
+
macOS config + ``pylock.macos.toml``, runs the drift check, and drives the
|
|
6
|
+
``.app`` bundler.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import subprocess
|
|
12
|
+
import time
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
import click
|
|
16
|
+
|
|
17
|
+
from kivyforge.cli._common import ToolchainError, lockfile_path_for
|
|
18
|
+
from kivyforge.config import ConfigError, load_config
|
|
19
|
+
from kivyforge.lock.reader import LockError, is_in_sync
|
|
20
|
+
|
|
21
|
+
from .. import HostCapabilityError, get_platform
|
|
22
|
+
from . import AppBundleError
|
|
23
|
+
from .bundle import build_app_bundle
|
|
24
|
+
from .lock import MacosLockfile
|
|
25
|
+
from .lock import load as load_macos_lock
|
|
26
|
+
from .notarize import notarize_and_staple
|
|
27
|
+
from .signing import sign_bundle_developer_id
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def macos_build(
|
|
31
|
+
project_root: Path,
|
|
32
|
+
*,
|
|
33
|
+
arch: str | None,
|
|
34
|
+
no_verify_lock: bool,
|
|
35
|
+
no_cache: bool,
|
|
36
|
+
sign: bool = True,
|
|
37
|
+
release: bool = False,
|
|
38
|
+
) -> Path:
|
|
39
|
+
"""Assemble (and ad-hoc sign) the macOS ``.app``; return its path."""
|
|
40
|
+
_require_macos_host()
|
|
41
|
+
config = _load_config(project_root)
|
|
42
|
+
lock = _load_lock(project_root)
|
|
43
|
+
|
|
44
|
+
pyproject = project_root / "pyproject.toml"
|
|
45
|
+
if not no_verify_lock and not is_in_sync(lock, pyproject.read_text("utf-8")):
|
|
46
|
+
raise ToolchainError(
|
|
47
|
+
f"{lockfile_path_for('macos').name} is out of date with "
|
|
48
|
+
"pyproject.toml.\n"
|
|
49
|
+
" Run `kivyforge lock -p macos` to regenerate it (or pass "
|
|
50
|
+
"--no-verify-lock to build against the stale lock anyway)."
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
app = build_app_bundle(
|
|
55
|
+
config,
|
|
56
|
+
lock,
|
|
57
|
+
project_root,
|
|
58
|
+
arch=arch,
|
|
59
|
+
sign=sign,
|
|
60
|
+
no_cache=no_cache,
|
|
61
|
+
release=release,
|
|
62
|
+
)
|
|
63
|
+
except AppBundleError as exc:
|
|
64
|
+
raise ToolchainError(str(exc)) from exc
|
|
65
|
+
|
|
66
|
+
click.echo(f"Built {app.relative_to(project_root)}")
|
|
67
|
+
return app
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def macos_run(
|
|
71
|
+
project_root: Path,
|
|
72
|
+
*,
|
|
73
|
+
arch: str | None,
|
|
74
|
+
no_build: bool,
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Build (unless --no-build) and launch the ``.app`` in the foreground."""
|
|
77
|
+
if no_build:
|
|
78
|
+
_require_macos_host()
|
|
79
|
+
config = _load_config(project_root)
|
|
80
|
+
app = project_root / "build" / "macos" / f"{config.display_name}.app"
|
|
81
|
+
if not app.exists():
|
|
82
|
+
raise ToolchainError(
|
|
83
|
+
f"no built app at {app.relative_to(project_root)}; run without "
|
|
84
|
+
"--no-build first."
|
|
85
|
+
)
|
|
86
|
+
else:
|
|
87
|
+
app = macos_build(project_root, arch=arch, no_verify_lock=False, no_cache=False)
|
|
88
|
+
|
|
89
|
+
executable = app / "Contents" / "MacOS" / _executable_name(app)
|
|
90
|
+
click.echo(f"Launching {app.name} ...")
|
|
91
|
+
# Foreground exec (not `open`) so the dev sees stdout/stderr + tracebacks,
|
|
92
|
+
# the desktop analog of the simulator console.
|
|
93
|
+
proc = subprocess.run([str(executable)])
|
|
94
|
+
if proc.returncode != 0:
|
|
95
|
+
raise ToolchainError(f"{app.name} exited with status {proc.returncode}.")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def macos_package(
|
|
99
|
+
project_root: Path,
|
|
100
|
+
*,
|
|
101
|
+
arch: str | None,
|
|
102
|
+
no_verify_lock: bool,
|
|
103
|
+
no_cache: bool,
|
|
104
|
+
signing_identity: str | None = None,
|
|
105
|
+
notarize: bool | None = None,
|
|
106
|
+
notary_profile: str | None = None,
|
|
107
|
+
) -> Path:
|
|
108
|
+
"""Produce the finished, signed ``.app`` distributable.
|
|
109
|
+
|
|
110
|
+
Signing tier is config-driven: with ``[tool.kivy.macos.signing].identity``
|
|
111
|
+
set (or ``--signing-identity``), the bundle is Developer-ID deep-signed
|
|
112
|
+
(Hardened Runtime + timestamp) and — when a notary profile is configured —
|
|
113
|
+
notarized and stapled. Without an identity, the ad-hoc floor applies.
|
|
114
|
+
"""
|
|
115
|
+
_require_macos_host()
|
|
116
|
+
config = _load_config(project_root)
|
|
117
|
+
signing = config.macos_required.signing
|
|
118
|
+
identity = signing_identity or signing.identity
|
|
119
|
+
profile = notary_profile or signing.notary_profile
|
|
120
|
+
# None = config-driven: notarize whenever a profile is configured.
|
|
121
|
+
do_notarize = notarize if notarize is not None else bool(profile)
|
|
122
|
+
|
|
123
|
+
if not identity:
|
|
124
|
+
if notarize:
|
|
125
|
+
raise ToolchainError(
|
|
126
|
+
"--notarize requires Developer ID signing, but no identity is "
|
|
127
|
+
"configured.\n"
|
|
128
|
+
" Set [tool.kivy.macos.signing].identity to your 'Developer ID "
|
|
129
|
+
"Application: ...' certificate (or pass --signing-identity)."
|
|
130
|
+
)
|
|
131
|
+
app = macos_build(
|
|
132
|
+
project_root,
|
|
133
|
+
arch=arch,
|
|
134
|
+
no_verify_lock=no_verify_lock,
|
|
135
|
+
no_cache=no_cache,
|
|
136
|
+
sign=True,
|
|
137
|
+
release=True,
|
|
138
|
+
)
|
|
139
|
+
click.echo(
|
|
140
|
+
f"Packaged {app.relative_to(project_root)} (ad-hoc signed).\n"
|
|
141
|
+
" Distribute the .app directly, or wrap it in a .dmg with an "
|
|
142
|
+
"external tool (see docs). For Gatekeeper-trusted distribution, "
|
|
143
|
+
"configure [tool.kivy.macos.signing]."
|
|
144
|
+
)
|
|
145
|
+
return app
|
|
146
|
+
|
|
147
|
+
if do_notarize and not profile:
|
|
148
|
+
raise ToolchainError(
|
|
149
|
+
"notarization needs a notary keychain profile.\n"
|
|
150
|
+
" Create one: `xcrun notarytool store-credentials <name> "
|
|
151
|
+
"--apple-id <id> --team-id <team>` and set "
|
|
152
|
+
'[tool.kivy.macos.signing].notary_profile = "<name>" '
|
|
153
|
+
"(or pass --notary-profile)."
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Assemble unsigned; the Developer ID deep-sign below seals every Mach-O.
|
|
157
|
+
app = macos_build(
|
|
158
|
+
project_root,
|
|
159
|
+
arch=arch,
|
|
160
|
+
no_verify_lock=no_verify_lock,
|
|
161
|
+
no_cache=no_cache,
|
|
162
|
+
sign=False,
|
|
163
|
+
release=True,
|
|
164
|
+
)
|
|
165
|
+
try:
|
|
166
|
+
click.echo(f"Developer ID signing with {identity!r} ...")
|
|
167
|
+
count = sign_bundle_developer_id(
|
|
168
|
+
app,
|
|
169
|
+
identity,
|
|
170
|
+
extra_entitlements=config.macos_required.entitlements,
|
|
171
|
+
)
|
|
172
|
+
click.echo(f" signed {count} Mach-O binaries + the bundle")
|
|
173
|
+
if do_notarize:
|
|
174
|
+
notarize_and_staple(app, profile=profile)
|
|
175
|
+
except AppBundleError as exc:
|
|
176
|
+
raise ToolchainError(str(exc)) from exc
|
|
177
|
+
|
|
178
|
+
trust = "notarized + stapled" if do_notarize else "signed (not notarized)"
|
|
179
|
+
click.echo(
|
|
180
|
+
f"Packaged {app.relative_to(project_root)} (Developer ID {trust}).\n"
|
|
181
|
+
" Distribute the .app directly, or wrap it in a .dmg with an external "
|
|
182
|
+
"tool (see docs)."
|
|
183
|
+
)
|
|
184
|
+
return app
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def macos_status(project_root: Path) -> None:
|
|
188
|
+
"""Show app identity, Python version, lock sync, and build state."""
|
|
189
|
+
config = _load_config(project_root)
|
|
190
|
+
macos = config.macos_required
|
|
191
|
+
click.echo(f"App: {config.display_name} ({macos.bundle_id})")
|
|
192
|
+
click.echo(f"Python: {macos.python_version or '(unset)'}")
|
|
193
|
+
click.echo(f"Lock: {_lock_state(project_root)}")
|
|
194
|
+
|
|
195
|
+
app = project_root / "build" / "macos" / f"{config.display_name}.app"
|
|
196
|
+
click.echo(f"Build: {_build_state(app)}")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def _lock_state(project_root: Path) -> str:
|
|
200
|
+
path = lockfile_path_for("macos", project_root)
|
|
201
|
+
if not path.is_file():
|
|
202
|
+
return "missing (run `kivyforge lock -p macos`)"
|
|
203
|
+
try:
|
|
204
|
+
lock = load_macos_lock(path)
|
|
205
|
+
except LockError:
|
|
206
|
+
return "unreadable (run `kivyforge lock -p macos`)"
|
|
207
|
+
pyproject = project_root / "pyproject.toml"
|
|
208
|
+
if is_in_sync(lock, pyproject.read_text("utf-8")):
|
|
209
|
+
return "in sync"
|
|
210
|
+
return "out of date (run `kivyforge lock -p macos`)"
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _build_state(app: Path) -> str:
|
|
214
|
+
if not app.exists():
|
|
215
|
+
return "not built"
|
|
216
|
+
age = time.time() - app.stat().st_mtime
|
|
217
|
+
return f"last built {_humanize(age)}"
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _humanize(seconds: float) -> str:
|
|
221
|
+
seconds = int(seconds)
|
|
222
|
+
if seconds < 60:
|
|
223
|
+
return "just now"
|
|
224
|
+
if seconds < 3600:
|
|
225
|
+
m = seconds // 60
|
|
226
|
+
return f"{m} minute{'s' if m != 1 else ''} ago"
|
|
227
|
+
if seconds < 86400:
|
|
228
|
+
h = seconds // 3600
|
|
229
|
+
return f"{h} hour{'s' if h != 1 else ''} ago"
|
|
230
|
+
d = seconds // 86400
|
|
231
|
+
return f"{d} day{'s' if d != 1 else ''} ago"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _executable_name(app: Path) -> str:
|
|
235
|
+
macos_dir = app / "Contents" / "MacOS"
|
|
236
|
+
entries = (
|
|
237
|
+
[p for p in macos_dir.iterdir() if p.is_file()] if macos_dir.is_dir() else []
|
|
238
|
+
)
|
|
239
|
+
if not entries:
|
|
240
|
+
raise ToolchainError(f"{app.name} has no launcher in Contents/MacOS.")
|
|
241
|
+
return entries[0].name
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _require_macos_host() -> None:
|
|
245
|
+
try:
|
|
246
|
+
get_platform("macos").check_host_capability()
|
|
247
|
+
except HostCapabilityError as exc:
|
|
248
|
+
raise ToolchainError(str(exc)) from exc
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def _load_config(project_root: Path):
|
|
252
|
+
try:
|
|
253
|
+
return load_config(
|
|
254
|
+
project_root / "pyproject.toml", require_ios=False, require_macos=True
|
|
255
|
+
)
|
|
256
|
+
except ConfigError as exc:
|
|
257
|
+
raise ToolchainError(exc.format()) from exc
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _load_lock(project_root: Path) -> MacosLockfile:
|
|
261
|
+
path = lockfile_path_for("macos", project_root)
|
|
262
|
+
if not path.is_file():
|
|
263
|
+
raise ToolchainError(
|
|
264
|
+
f"no {path.name} found. Run `kivyforge lock -p macos` first."
|
|
265
|
+
)
|
|
266
|
+
try:
|
|
267
|
+
return load_macos_lock(path)
|
|
268
|
+
except LockError as exc:
|
|
269
|
+
raise ToolchainError(str(exc)) from exc
|