feat: 添加 ARM64 manylinux wheel 构建选项
复用现有 Docker 和 Nuitka 流程,隔离架构镜像并支持 aarch64 标签。已通过 47 项测试、代码及文档门禁,并完成 Python 3.10 ARM64 wheel 构建、隔离导入与内容审计。
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
"""Exercise the Windows launcher without downloading or compiling Docker images."""
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
POWERSHELL = shutil.which("powershell")
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
pytestmark = pytest.mark.skipif(not POWERSHELL, reason="Windows PowerShell is required")
|
||||
|
||||
|
||||
def run_launcher(tmp_path, arguments, image_architecture):
|
||||
docker_dir = tmp_path / "build" / "wheel" / "docker"
|
||||
docker_dir.mkdir(parents=True)
|
||||
shutil.copy2(REPO_ROOT / "build/wheel/docker/run.ps1", docker_dir)
|
||||
(docker_dir / "entrypoint.sh").write_text("#!/bin/bash\n", encoding="utf-8")
|
||||
parameters = {}
|
||||
iterator = iter(arguments)
|
||||
for argument in iterator:
|
||||
parameters[argument.lstrip("-")] = (
|
||||
True if argument == "-SkipImageBuild" else next(iterator)
|
||||
)
|
||||
(tmp_path / "arguments.json").write_text(json.dumps(parameters), encoding="utf-8")
|
||||
harness = tmp_path / "harness.ps1"
|
||||
harness.write_text(
|
||||
"""
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$global:Calls = [System.Collections.Generic.List[object]]::new()
|
||||
function docker {
|
||||
$global:Calls.Add(@($args))
|
||||
$global:LASTEXITCODE = 0
|
||||
if ($args[0] -eq 'version') { return 'linux' }
|
||||
if ($args[0] -eq 'image') { return '__ARCH__' }
|
||||
}
|
||||
$decoded = Get-Content (Join-Path $PSScriptRoot 'arguments.json') -Raw | ConvertFrom-Json
|
||||
$parameters = @{}
|
||||
foreach ($property in $decoded.PSObject.Properties) { $parameters[$property.Name] = $property.Value }
|
||||
try {
|
||||
& (Join-Path $PSScriptRoot 'build/wheel/docker/run.ps1') @parameters
|
||||
} finally {
|
||||
ConvertTo-Json -InputObject @($global:Calls.ToArray()) -Depth 5 |
|
||||
Set-Content (Join-Path $PSScriptRoot 'calls.json') -Encoding UTF8
|
||||
}
|
||||
""".replace("__ARCH__", image_architecture),
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = subprocess.run(
|
||||
[POWERSHELL, "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", str(harness)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
calls = json.loads((tmp_path / "calls.json").read_text(encoding="utf-8-sig"))
|
||||
return result, calls
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"arguments,image_architecture,platform,architecture,image_name",
|
||||
[
|
||||
([], "amd64", "linux/amd64", "x86_64", "orisys-manylinux"),
|
||||
(
|
||||
["-Architecture", "aarch64"],
|
||||
"arm64",
|
||||
"linux/arm64",
|
||||
"aarch64",
|
||||
"orisys-manylinux-aarch64",
|
||||
),
|
||||
(
|
||||
["-Architecture", "AARCH64"],
|
||||
"arm64",
|
||||
"linux/arm64",
|
||||
"aarch64",
|
||||
"orisys-manylinux-aarch64",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_architecture_controls_build_and_run(
|
||||
tmp_path, arguments, image_architecture, platform, architecture, image_name
|
||||
):
|
||||
result, calls = run_launcher(tmp_path, arguments, image_architecture)
|
||||
assert result.returncode == 0, result.stderr
|
||||
build = next(call for call in calls if call[0] == "build")
|
||||
run = next(call for call in calls if call[0] == "run")
|
||||
assert build[build.index("--platform") + 1] == platform
|
||||
assert build[build.index("--build-arg") + 1] == f"MANYLINUX_ARCH={architecture}"
|
||||
assert build[build.index("-t") + 1] == image_name
|
||||
assert run[run.index("--platform") + 1] == platform
|
||||
assert run[-1] == image_name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"image_architecture,success", [("arm64", True), ("amd64", False)]
|
||||
)
|
||||
def test_reused_image_must_match_requested_architecture(
|
||||
tmp_path, image_architecture, success
|
||||
):
|
||||
result, calls = run_launcher(
|
||||
tmp_path,
|
||||
[
|
||||
"-Architecture",
|
||||
"aarch64",
|
||||
"-SkipImageBuild",
|
||||
"-ImageName",
|
||||
"custom-arm",
|
||||
"-PythonVersions",
|
||||
"3.10",
|
||||
],
|
||||
image_architecture,
|
||||
)
|
||||
assert not any(call[0] == "build" for call in calls)
|
||||
assert (result.returncode == 0) == success
|
||||
runs = [call for call in calls if call[0] == "run"]
|
||||
if success:
|
||||
assert runs[0][-1] == "custom-arm"
|
||||
assert "ORISYS_PYTHON_TAGS=cp310-cp310" in runs[0]
|
||||
else:
|
||||
assert not runs
|
||||
assert "architecture" in result.stderr.lower()
|
||||
Reference in New Issue
Block a user