Files
core/build/online.py
T
2026-11-03 03:32:07 +00:00

116 lines
5.2 KiB
Python

#!/usr/bin/env python3
"""在开发容器组装在线安装资源;不下载工具链、不发布或激活版本。"""
import argparse
import json
from pathlib import Path
import subprocess
import tomllib
from development import SOURCE, TRIPLE, copy, digest, native_tools, output, prepare, record, script
def archive(directory, destination):
with destination.open("xb") as stream:
subprocess.run([
"tar", "--sort=name", "--mtime=@0", "--owner=0", "--group=0", "--numeric-owner",
"-C", str(directory.parent), "-I", "xz -T4 -6", "-cf", "-", directory.name,
], stdout=stream, check=True)
return digest(destination)
def checksum(path):
Path(str(path) + ".sha256").write_text(f"{digest(path)} {path.name}\n")
def dependencies(bundle, rust_version):
"""Cargo 自己裁剪锁文件;安装时只下载本机运行库依赖,不带作者编译依赖。"""
project = bundle / "toolchain/project"
(project / "src").mkdir(parents=True)
(project / "src/main.rs").write_text("fn main() {}\n")
features = sorted(tomllib.loads((bundle / "rust/src/runtime/Cargo.toml").read_text())["features"])
(project / "Cargo.toml").write_text(
'[package]\nname = "dever-development-dependencies"\nversion = "0.0.0"\nedition = "2024"\n'
'[workspace]\n[dependencies]\n'
f'dever-runtime = {{ path = "../../rust/src/runtime", features = {json.dumps(features)} }}\n'
)
copy(bundle / "rust/Cargo.lock", project / "Cargo.lock")
subprocess.run(["cargo", f"+{rust_version}", "metadata", "--offline", "--format-version", "1",
"--manifest-path", str(project / "Cargo.toml")], stdout=subprocess.DEVNULL, check=True)
def compiler_licenses(tools, rust_version):
metadata = json.loads(output("cargo", f"+{rust_version}", "metadata", "--locked", "--offline",
"--all-features", "--format-version", "1", cwd=SOURCE / "rust"))
for package in metadata["packages"]:
if not package["source"]:
continue
source = Path(package["manifest_path"]).parent
licenses = {path for path in source.rglob("*") if path.is_file()
and path.name.upper().startswith(("LICENSE", "COPYING", "COPYRIGHT", "NOTICE", "AUTHORS"))}
if package["license_file"]:
licenses.add(source / package["license_file"])
for path in licenses:
copy(path, tools / "licenses/cargo" / source.name / path.relative_to(source))
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--compiler", required=True, type=Path)
parser.add_argument("--work", required=True, type=Path)
parser.add_argument("--output", required=True, type=Path, help="new release assets directory")
args = parser.parse_args()
system = Path("/etc/os-release").read_text()
if 'ID=debian\n' not in system or 'VERSION_ID="13"' not in system:
parser.error("prepare native tools in the Debian 13 development container")
compiler = args.compiler.resolve(strict=True)
work, destination = args.work.absolute(), args.output.absolute()
if work.exists() or destination.exists():
parser.error("work and output must be new directories")
destination.mkdir(parents=True)
bundle, version, rust_version = prepare(compiler, work)
tools = bundle / "toolchain"
tools.mkdir()
native = work / "native-tools"
native.mkdir()
native_tools(native)
native_archive = destination / "native.tar.xz"
native_id = archive(native, native_archive)
native_archive = native_archive.rename(destination / f"dever-native-linux-x86_64-{native_id}.tar.xz")
checksum(native_archive)
copy(native / "bin/cc", tools / "bin/cc")
script(tools / "bin/cargo", '''export CARGO_HOME="$tools/cache"
export RUSTC="$tools/rust/bin/rustc"
export CC="$tools/bin/cc"
export AR="$tools/native/usr/bin/x86_64-linux-gnu-ar"
export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER="$CC"
export LD_LIBRARY_PATH="$tools/lib"
export PATH="$tools/native/usr/bin:/usr/bin:/bin"
exec "$tools/rust/bin/cargo" "$@"
''')
script(tools / "bin/rustc", '''export LD_LIBRARY_PATH="$tools/lib"
exec "$tools/rust/bin/rustc" "$@"
''')
(tools / "online").write_text(f"{rust_version} {native_id}\n")
copy(SOURCE / "build/prepare.sh", tools / "prepare")
dependencies(bundle, rust_version)
compiler_licenses(tools, rust_version)
copy(SOURCE / "build/README.md", bundle / "DEVELOPMENT.md")
record(bundle, [bundle / "DEVELOPMENT.md", *tools.rglob("*")])
core_archive = destination / f"dever-{version}-linux-x86_64.tar.xz"
archive(bundle, core_archive)
checksum(core_archive)
installer = (SOURCE / "install").read_text().replace('@DEVER_VERSION@', version)
(destination / "install").write_text(installer)
(destination / "install").chmod(0o755)
checksum(destination / "install")
print(json.dumps({"version": version, "compiler_sha256": digest(compiler),
"core_bytes": core_archive.stat().st_size,
"native_bytes": native_archive.stat().st_size,
"installer_bytes": (destination / "install").stat().st_size,
"rust": rust_version, "target": TRIPLE}))
if __name__ == "__main__":
main()