Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
108
android/tools/prepare-toolchain.py
Normal file
108
android/tools/prepare-toolchain.py
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Install the locked Linux x86_64 Android build tools in the ignored toolchain/."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import platform
|
||||
import shutil
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import urllib.request
|
||||
import zipfile
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
TOOLS = ROOT / "toolchain"
|
||||
|
||||
|
||||
def fetch(name, entry):
|
||||
path = TOOLS / "downloads" / name
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
algorithm = "sha256" if "sha256" in entry else "sha1"
|
||||
if not path.exists():
|
||||
partial = path.with_suffix(path.suffix + ".partial")
|
||||
with urllib.request.urlopen(entry["url"], timeout=60) as source, partial.open("wb") as out:
|
||||
shutil.copyfileobj(source, out)
|
||||
partial.replace(path)
|
||||
with path.open("rb") as stream:
|
||||
digest = hashlib.file_digest(stream, algorithm).hexdigest()
|
||||
if digest != entry[algorithm]:
|
||||
raise RuntimeError(f"Checksum mismatch; archive left unextracted: {path}")
|
||||
return path
|
||||
|
||||
|
||||
def extract(archive, member_root, target):
|
||||
if target.exists():
|
||||
raise RuntimeError(f"Incomplete installation left untouched: {target}")
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
with tempfile.TemporaryDirectory(prefix=".install-", dir=TOOLS) as temporary:
|
||||
stage = Path(temporary)
|
||||
if archive.name.endswith(".tar.gz"):
|
||||
with tarfile.open(archive) as package:
|
||||
package.extractall(stage, filter="data")
|
||||
else:
|
||||
with zipfile.ZipFile(archive) as package:
|
||||
for info in package.infolist():
|
||||
path = stage / info.filename
|
||||
if not path.resolve().is_relative_to(stage) or "\\" in info.filename:
|
||||
raise RuntimeError("Unsafe toolchain archive entry")
|
||||
if (info.external_attr >> 16) & 0o170000 == 0o120000:
|
||||
raise RuntimeError("Symlink in toolchain ZIP archive")
|
||||
package.extract(info, stage)
|
||||
mode = (info.external_attr >> 16) & 0o777
|
||||
if mode and path.is_file():
|
||||
path.chmod(mode)
|
||||
(stage / member_root).rename(target)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--check", action="store_true", help="Check installed tools without downloading"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if platform.system() != "Linux" or platform.machine() not in ("x86_64", "amd64"):
|
||||
raise RuntimeError("This bootstrap currently supports Linux x86_64 only")
|
||||
lock = json.loads((ROOT / "toolchain-lock.json").read_text())
|
||||
jdk = TOOLS / "jdk-21.0.12.1+1"
|
||||
gradle = TOOLS / "gradle-9.5.0"
|
||||
sdk = TOOLS / "sdk"
|
||||
installs = [
|
||||
("jdk.tar.gz", "jdk-21.0.12.1+1", jdk, jdk / "bin/java"),
|
||||
("gradle-9.5.zip", "gradle-9.5.0", gradle, gradle / "bin/gradle"),
|
||||
(
|
||||
"commandlinetools.zip",
|
||||
"cmdline-tools",
|
||||
sdk / "cmdline-tools/latest",
|
||||
sdk / "cmdline-tools/latest/bin/sdkmanager",
|
||||
),
|
||||
]
|
||||
missing = [
|
||||
str(executable.relative_to(ROOT))
|
||||
for _, _, _, executable in installs
|
||||
if not executable.is_file()
|
||||
]
|
||||
packages = [sdk / "platforms/android-37.1/android.jar", sdk / "build-tools/37.0.0/apksigner"]
|
||||
if args.check:
|
||||
missing += [str(path.relative_to(ROOT)) for path in packages if not path.is_file()]
|
||||
if missing:
|
||||
raise RuntimeError("Missing tools: " + ", ".join(missing))
|
||||
else:
|
||||
TOOLS.mkdir(exist_ok=True)
|
||||
for name, member, target, executable in installs:
|
||||
if not executable.is_file():
|
||||
extract(fetch(name, lock["archives"][name]), member, target)
|
||||
if not all(path.is_file() for path in packages):
|
||||
env = {**os.environ, "JAVA_HOME": str(jdk)}
|
||||
manager = sdk / "cmdline-tools/latest/bin/sdkmanager"
|
||||
# sdkmanager asks the user to review any licenses not already accepted.
|
||||
subprocess.run(
|
||||
[str(manager), "--sdk_root=" + str(sdk), *lock["sdk"]], env=env, check=True
|
||||
)
|
||||
print("Android build tools available in", TOOLS)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in a new issue