Skip to content

Commit 8f1c156

Browse files
zhoubotRuoyuZhou
andauthored
Fix cross-platform wheel CI tagging (#34)
* Fix cross-platform wheel CI tags * Fix CI baseline checks * Adjust CI smoke lanes for packaged toolchains * Run Linux sims in toolchain build job * Keep PR CI focused on packaging smoke --------- Co-authored-by: RuoyuZhou <ruoyu.zhou@hisilicon.com>
1 parent 5b7b7d4 commit 8f1c156

7 files changed

Lines changed: 149 additions & 84 deletions

File tree

.github/workflows/ci.yml

Lines changed: 31 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
name: CI
22

33
on:
4+
workflow_dispatch:
45
push:
56
branches: [main, develop]
67
pull_request:
@@ -11,7 +12,7 @@ env:
1112

1213
jobs:
1314
lint:
14-
name: Lint
15+
name: Python Checks
1516
runs-on: ubuntu-latest
1617
steps:
1718
- name: Checkout
@@ -22,17 +23,26 @@ jobs:
2223
with:
2324
python-version: "3.11"
2425

25-
- name: Install linting tools
26-
run: pip install ruff black mypy
26+
- name: Install Python check deps
27+
run: python -m pip install pyyaml
2728

28-
- name: Run Ruff
29-
run: ruff check .
29+
- name: Validate cross-platform wheel tag helper
30+
run: |
31+
python packaging/wheel/get_wheel_plat_name.py --system linux --arch x86_64
32+
python packaging/wheel/get_wheel_plat_name.py --system macos --arch arm64
33+
python packaging/wheel/get_wheel_plat_name.py --system macos --arch x86_64
3034
31-
- name: Run Black
32-
run: black --check .
35+
- name: Byte-compile packaging + CLI modules
36+
run: |
37+
python -m py_compile \
38+
packaging/wheel/create_wheel.py \
39+
packaging/wheel/get_wheel_plat_name.py \
40+
packaging/wheel/platform_tags.py \
41+
compiler/frontend/pycircuit/packaged_toolchain.py \
42+
compiler/frontend/pycircuit/cli.py
3343
34-
- name: Run MyPy
35-
run: mypy compiler/frontend/pycircuit || true
44+
- name: Run API hygiene gate
45+
run: python flows/tools/check_api_hygiene.py compiler/frontend/pycircuit designs/examples docs README.md
3646

3747
build-linux:
3848
name: Build Toolchain (Linux)
@@ -74,6 +84,14 @@ jobs:
7484
--install-dir "$PWD/.pycircuit_out/toolchain/install" \
7585
--out-dir "$PWD/dist"
7686
87+
- name: Run examples
88+
run: |
89+
export PYC_TOOLCHAIN_ROOT="$PWD/.pycircuit_out/toolchain/install"
90+
export PATH="$PYC_TOOLCHAIN_ROOT/bin:$PATH"
91+
export PYC_SKIP_SEMANTIC_REGRESSIONS=1
92+
unset PYCC
93+
bash flows/scripts/run_examples.sh
94+
7795
- name: Upload toolchain
7896
uses: actions/upload-artifact@v4
7997
with:
@@ -88,44 +106,6 @@ jobs:
88106
path: dist/*.whl
89107
retention-days: 1
90108

91-
examples-linux:
92-
name: Examples + Sims (Linux)
93-
runs-on: ubuntu-latest
94-
needs: build-linux
95-
steps:
96-
- name: Checkout
97-
uses: actions/checkout@v4
98-
99-
- name: Set up Python
100-
uses: actions/setup-python@v5
101-
with:
102-
python-version: "3.11"
103-
104-
- name: Install simulation deps
105-
run: |
106-
sudo apt-get update
107-
sudo apt-get install -y verilator iverilog
108-
109-
- name: Download toolchain
110-
uses: actions/download-artifact@v4
111-
with:
112-
name: pyc-toolchain-linux
113-
path: .pycircuit_out/toolchain/install
114-
115-
- name: Run examples
116-
run: |
117-
export PYC_TOOLCHAIN_ROOT="$PWD/.pycircuit_out/toolchain/install"
118-
export PATH="$PYC_TOOLCHAIN_ROOT/bin:$PATH"
119-
unset PYCC
120-
bash flows/scripts/run_examples.sh
121-
122-
- name: Run simulations
123-
run: |
124-
export PYC_TOOLCHAIN_ROOT="$PWD/.pycircuit_out/toolchain/install"
125-
export PATH="$PYC_TOOLCHAIN_ROOT/bin:$PATH"
126-
unset PYCC
127-
bash flows/scripts/run_sims.sh
128-
129109
wheel-linux:
130110
name: Wheel Smoke (Linux)
131111
runs-on: ubuntu-latest
@@ -159,6 +139,7 @@ jobs:
159139
pip install dist/*.whl
160140
export PYC_TOOLCHAIN_ROOT="$(python -c 'import pycircuit, pathlib; print((pathlib.Path(pycircuit.__file__).resolve().parent / "_toolchain").as_posix())')"
161141
export PYC_USE_INSTALLED_PYTHON_PACKAGE=1
142+
export PYC_SKIP_SEMANTIC_REGRESSIONS=1
162143
unset PYCC
163144
bash flows/scripts/run_examples.sh
164145
@@ -193,16 +174,15 @@ jobs:
193174
194175
- name: Build platform wheel
195176
run: |
196-
python packaging/wheel/get_macos_wheel_plat_name.py "$(uname -m)" > .pycircuit_out/macos_plat_name.txt
197177
python packaging/wheel/create_wheel.py \
198178
--install-dir "$PWD/.pycircuit_out/toolchain/install" \
199-
--out-dir "$PWD/dist" \
200-
--wheel-plat-name "$(cat .pycircuit_out/macos_plat_name.txt)"
179+
--out-dir "$PWD/dist"
201180
202181
- name: Run example compile gate
203182
run: |
204183
export PYC_TOOLCHAIN_ROOT="$PWD/.pycircuit_out/toolchain/install"
205184
export PATH="$PYC_TOOLCHAIN_ROOT/bin:$PATH"
185+
export PYC_SKIP_SEMANTIC_REGRESSIONS=1
206186
unset PYCC
207187
bash flows/scripts/run_examples.sh
208188
@@ -215,6 +195,7 @@ jobs:
215195
pip install dist/*.whl
216196
export PYC_TOOLCHAIN_ROOT="$(python -c 'import pycircuit, pathlib; print((pathlib.Path(pycircuit.__file__).resolve().parent / "_toolchain").as_posix())')"
217197
export PYC_USE_INSTALLED_PYTHON_PACKAGE=1
198+
export PYC_SKIP_SEMANTIC_REGRESSIONS=1
218199
unset PYCC
219200
bash flows/scripts/run_examples.sh
220201

.github/workflows/release.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,20 +82,16 @@ jobs:
8282
mkdir -p dist
8383
mv ".pycircuit_out/toolchain/build/${PKG}.tar.gz" "dist/${PKG}.tar.gz"
8484
85-
WHEEL_ARGS=()
86-
if [[ "${RUNNER_OS}" == "macOS" ]]; then
87-
WHEEL_ARGS+=(--wheel-plat-name "$(python3 packaging/wheel/get_macos_wheel_plat_name.py "$(uname -m)")")
88-
fi
8985
python3 packaging/wheel/create_wheel.py \
9086
--install-dir "$PWD/.pycircuit_out/toolchain/install" \
91-
--out-dir "$PWD/dist" \
92-
"${WHEEL_ARGS[@]}"
87+
--out-dir "$PWD/dist"
9388
9489
python3 -m venv .venv-wheel
9590
source .venv-wheel/bin/activate
9691
pip install dist/*.whl
9792
export PYC_TOOLCHAIN_ROOT="$(python -c 'import pycircuit, pathlib; print((pathlib.Path(pycircuit.__file__).resolve().parent / "_toolchain").as_posix())')"
9893
export PYC_USE_INSTALLED_PYTHON_PACKAGE=1
94+
export PYC_SKIP_SEMANTIC_REGRESSIONS=1
9995
unset PYCC
10096
bash flows/scripts/run_examples.sh
10197

flows/scripts/run_examples.sh

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,10 +1212,14 @@ fi
12121212
cp -f "${decision_report}" "${docs_gate_dir}/decision_status_report.json" >/dev/null 2>&1 || true
12131213

12141214
pyc_log "running v4.0 semantic regression lane"
1215-
if ! PYC_GATE_RUN_ID="${gate_run_id}" bash "${PYC_ROOT_DIR}/flows/scripts/run_semantic_regressions_v40.sh" \
1216-
>"${docs_gate_dir}/semantic_regressions.stdout" 2>"${docs_gate_dir}/semantic_regressions.stderr"; then
1217-
pyc_warn "semantic regression lane failed"
1218-
fail=1
1215+
if [[ "${PYC_SKIP_SEMANTIC_REGRESSIONS:-0}" == "1" ]]; then
1216+
pyc_log "skipping v4.0 semantic regression lane (PYC_SKIP_SEMANTIC_REGRESSIONS=1)"
1217+
else
1218+
if ! PYC_GATE_RUN_ID="${gate_run_id}" bash "${PYC_ROOT_DIR}/flows/scripts/run_semantic_regressions_v40.sh" \
1219+
>"${docs_gate_dir}/semantic_regressions.stdout" 2>"${docs_gate_dir}/semantic_regressions.stderr"; then
1220+
pyc_warn "semantic regression lane failed"
1221+
fail=1
1222+
fi
12191223
fi
12201224

12211225
if [[ "${fail}" -eq 0 ]]; then

packaging/wheel/create_wheel.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@
77
import subprocess
88
import sys
99
import tempfile
10-
import tomllib
1110
from pathlib import Path
1211

12+
from platform_tags import wheel_plat_name
13+
14+
try:
15+
import tomllib
16+
except ModuleNotFoundError: # pragma: no cover - Python 3.11+ in CI, but keep 3.9/3.10 usable.
17+
try:
18+
import tomli as tomllib # type: ignore[no-redef]
19+
except ModuleNotFoundError as exc: # pragma: no cover - depends on local Python version.
20+
raise SystemExit("wheel packaging requires Python 3.11+ or `tomli` on Python 3.9/3.10") from exc
21+
1322

1423
def _repo_root() -> Path:
1524
return Path(__file__).resolve().parents[2]
@@ -73,14 +82,13 @@ def main(argv: list[str] | None = None) -> int:
7382
_copy_file(repo_root / "packaging" / "wheel" / "setup.py", stage / "setup.py")
7483
_copy_file(repo_root / "packaging" / "wheel" / "pyproject.toml", stage / "pyproject.toml")
7584

85+
plat_name = args.wheel_plat_name or wheel_plat_name()
86+
7687
env = os.environ.copy()
7788
env["PYC_WHEEL_VERSION"] = version
78-
if args.wheel_plat_name:
79-
env["PYC_WHEEL_PLAT_NAME"] = args.wheel_plat_name
8089

8190
cmd = [sys.executable, "setup.py", "bdist_wheel", "--dist-dir", str(out_dir)]
82-
if args.wheel_plat_name:
83-
cmd.extend(["--plat-name", args.wheel_plat_name])
91+
cmd.extend(["--plat-name", plat_name])
8492

8593
subprocess.run(cmd, check=True, cwd=stage, env=env)
8694
return 0

packaging/wheel/get_macos_wheel_plat_name.py

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env python3
2+
from __future__ import annotations
3+
4+
import argparse
5+
6+
from platform_tags import wheel_plat_name
7+
8+
9+
def main(argv: list[str] | None = None) -> int:
10+
ap = argparse.ArgumentParser(description="Print the wheel platform tag for the current or requested host.")
11+
ap.add_argument("--system", default=None, help="Override platform.system() for cross-platform checks")
12+
ap.add_argument("--arch", default=None, help="Override platform.machine() for cross-platform checks")
13+
ap.add_argument(
14+
"--deployment-target",
15+
default=None,
16+
help="Override MACOSX_DEPLOYMENT_TARGET when computing macOS wheel tags",
17+
)
18+
args = ap.parse_args(argv)
19+
print(wheel_plat_name(system=args.system, arch=args.arch, deployment_target=args.deployment_target))
20+
return 0
21+
22+
23+
if __name__ == "__main__":
24+
raise SystemExit(main())

packaging/wheel/platform_tags.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from __future__ import annotations
2+
3+
import os
4+
import platform
5+
6+
7+
def _normalize_system(system: str | None = None) -> str:
8+
raw = (system or platform.system()).strip().lower()
9+
aliases = {
10+
"darwin": "macos",
11+
"macos": "macos",
12+
"mac": "macos",
13+
"linux": "linux",
14+
"windows": "windows",
15+
"win32": "windows",
16+
"cygwin": "windows",
17+
"msys": "windows",
18+
}
19+
return aliases.get(raw, raw)
20+
21+
22+
def _normalize_arch(system: str, arch: str | None = None) -> str:
23+
raw = (arch or platform.machine()).strip().lower()
24+
if system == "macos":
25+
aliases = {
26+
"aarch64": "arm64",
27+
"arm64": "arm64",
28+
"x86_64": "x86_64",
29+
"amd64": "x86_64",
30+
}
31+
return aliases.get(raw, raw)
32+
if system == "windows":
33+
aliases = {
34+
"amd64": "amd64",
35+
"x86_64": "amd64",
36+
"arm64": "arm64",
37+
"aarch64": "arm64",
38+
}
39+
return aliases.get(raw, raw)
40+
aliases = {
41+
"amd64": "x86_64",
42+
"x64": "x86_64",
43+
"x86_64": "x86_64",
44+
"arm64": "aarch64",
45+
"aarch64": "aarch64",
46+
}
47+
return aliases.get(raw, raw)
48+
49+
50+
def _macos_target(arch: str, deployment_target: str | None = None) -> tuple[str, str]:
51+
target = (deployment_target or os.environ.get("MACOSX_DEPLOYMENT_TARGET", "")).strip()
52+
if not target:
53+
target = "11.0" if arch == "arm64" else "10.13"
54+
parts = (target.split(".") + ["0", "0"])[:2]
55+
return parts[0], parts[1]
56+
57+
58+
def wheel_plat_name(
59+
*, system: str | None = None, arch: str | None = None, deployment_target: str | None = None
60+
) -> str:
61+
normalized_system = _normalize_system(system)
62+
normalized_arch = _normalize_arch(normalized_system, arch)
63+
64+
if normalized_system == "macos":
65+
major, minor = _macos_target(normalized_arch, deployment_target)
66+
return f"macosx_{major}_{minor}_{normalized_arch}"
67+
if normalized_system == "linux":
68+
return f"linux_{normalized_arch}"
69+
if normalized_system == "windows":
70+
return f"win_{normalized_arch}"
71+
raise SystemExit(f"unsupported platform for wheel packaging: {normalized_system}")

0 commit comments

Comments
 (0)