[CI] Build macOS arm64 CPU wheel natively on the macmini queue (#48289)
Signed-off-by: mgoin <mgoin64@gmail.com>
Michael Goin committed
Jul 14, 2026 at 15:40 UTC
0b54201a044c419e07a4bd464adf91e576640977
4 files changed
+90
-6
.buildkite/release-pipeline.yaml
+43
@@ -76,6 +76,49 @@ steps:
76
env:
77
DOCKER_BUILDKIT: "1"
78
79
+ - label: "Build wheel - macOS arm64 - CPU"
80
+ depends_on: ~
81
+ id: build-wheel-macos-arm64-cpu
82
+ agents:
83
+ queue: macmini
84
+ timeout_in_minutes: 90
85
+ commands:
86
+ - "bash .buildkite/scripts/build-macos-wheel.sh"
87
+ - "mkdir -p artifacts/transfer"
88
+ - "basename artifacts/dist/*.whl > artifacts/transfer/wheel.name"
89
+ - "shasum -a 256 artifacts/dist/*.whl > artifacts/transfer/wheel.sha256"
90
+ - "split -b 1m artifacts/dist/*.whl artifacts/transfer/wheel.part."
91
+ env:
92
+ BUILDKITE_ARTIFACT_UPLOAD_CONCURRENCY: "1"
93
+ BUILDKITE_NO_HTTP2: "true"
94
+ artifact_paths:
95
+ - "artifacts/transfer/*"
96
+
97
+ - label: "Upload wheel - macOS arm64 - CPU"
98
+ depends_on: build-wheel-macos-arm64-cpu
99
+ id: upload-wheel-macos-arm64-cpu
100
+ agents:
101
+ queue: small_cpu_queue_release
102
+ timeout_in_minutes: 15
103
+ commands:
104
+ - 'buildkite-agent artifact download "artifacts/transfer/*" .'
105
+ - "mkdir -p artifacts/dist artifacts/reassembled"
106
+ - 'wheel_name=$$(cat artifacts/transfer/wheel.name)'
107
+ - '[[ "$$wheel_name" =~ ^[A-Za-z0-9][A-Za-z0-9._+-]*\.whl$$ && "$$wheel_name" != *..* ]]'
108
+ - 'expected_sha=$$(awk ''{print $$1}'' artifacts/transfer/wheel.sha256)'
109
+ - '[[ "$$expected_sha" =~ ^[0-9a-f]{64}$$ ]]'
110
+ - 'cat artifacts/transfer/wheel.part.* > artifacts/reassembled/wheel'
111
+ - 'actual_sha=$$(shasum -a 256 artifacts/reassembled/wheel | awk ''{print $$1}'')'
112
+ - '[[ "$$actual_sha" == "$$expected_sha" ]]'
113
+ - 'mv artifacts/reassembled/wheel "artifacts/dist/$$wheel_name"'
114
+ - "aws sts get-caller-identity"
115
+ - "VLLM_WHEEL_PLATFORM=macos bash .buildkite/scripts/upload-nightly-wheels.sh"
116
+ - 'bash .buildkite/scripts/annotate-build-artifact.sh "$$BUILDKITE_LABEL" "s3://vllm-wheels/$$BUILDKITE_COMMIT/$(cd artifacts/dist && echo *.whl)"'
117
+ plugins:
118
+ - aws-assume-role-with-web-identity#v1.6.0:
119
+ role-arn: arn:aws:iam::936637512419:role/vllm-release-macos-wheel-uploader
120
+ region: us-west-2
121
+
122
- label: "Build wheel - x86_64 - CUDA 12.9"
123
depends_on: ~
124
id: build-wheel-x86-cuda-12-9
.buildkite/scripts/build-macos-wheel.sh
new
+32
@@ -0,0 +1,32 @@
1
+#!/usr/bin/env bash
2
+# SPDX-License-Identifier: Apache-2.0
3
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4
+#
5
+# Build the macOS arm64 CPU wheel natively on a macOS agent (the `macmini`
6
+# queue) into artifacts/dist/ for upload-nightly-wheels.sh.
7
+
8
+set -euo pipefail
9
+
10
+# The Rust frontend build needs protoc.
11
+if ! command -v protoc >/dev/null 2>&1; then
12
+ brew install protobuf
13
+fi
14
+
15
+# upload-nightly-wheels.sh expects exactly one wheel.
16
+rm -rf artifacts/dist
17
+mkdir -p artifacts/dist
18
+
19
+export VLLM_TARGET_DEVICE=cpu
20
+export VLLM_REQUIRE_RUST_FRONTEND=1
21
+export MACOSX_DEPLOYMENT_TARGET=11.0
22
+# uv's CPython is universal2; force an arm64-only build and tag so the wheel
23
+# isn't mislabelled universal2 and installed on Intel Macs where import fails.
24
+export ARCHFLAGS="-arch arm64"
25
+export _PYTHON_HOST_PLATFORM="macosx-11.0-arm64"
26
+export CMAKE_BUILD_PARALLEL_LEVEL="${CMAKE_BUILD_PARALLEL_LEVEL:-4}"
27
+
28
+uv venv --python 3.12
29
+uv pip install -r requirements/build/cpu.txt --index-strategy unsafe-best-match
30
+uv build --wheel --no-build-isolation -o artifacts/dist
31
+
32
+ls -l artifacts/dist/*.whl
.buildkite/scripts/upload-nightly-wheels.sh
+12
-4
@@ -6,8 +6,14 @@ set -ex
6
# manylinux platform tag with auditwheel.
7
# Index generation is handled separately by generate-and-upload-nightly-index.sh.
8
9
-# shellcheck source=lib/manylinux.sh
10
-source .buildkite/scripts/lib/manylinux.sh
9
+# auditwheel is Linux-only; macOS wheels already carry a valid tag, so skip the
10
+# manylinux retag for them.
11
+WHEEL_PLATFORM="${VLLM_WHEEL_PLATFORM:-linux}"
12
+
13
+if [[ "$WHEEL_PLATFORM" == "linux" ]]; then
14
+ # shellcheck source=lib/manylinux.sh
15
+ source .buildkite/scripts/lib/manylinux.sh
16
+fi
17
18
BUCKET="vllm-wheels"
19
SUBPATH=$BUILDKITE_COMMIT
@@ -27,8 +33,10 @@ wheel="${wheel_files[0]}"
33
34
# ========= detect manylinux tag and rename ==========
35
30
-wheel="$(apply_manylinux_tag "$wheel")"
31
-echo "Renamed wheel to: $wheel"
36
+if [[ "$WHEEL_PLATFORM" == "linux" ]]; then
37
+ wheel="$(apply_manylinux_tag "$wheel")"
38
+ echo "Renamed wheel to: $wheel"
39
+fi
40
41
# Extract the version from the wheel
42
version=$(unzip -p "$wheel" '**/METADATA' | grep '^Version: ' | cut -d' ' -f2)
csrc/cpu/torch_bindings.cpp
+3
-2
@@ -570,7 +570,8 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
570
#endif
571
572
// fused moe
573
-#if defined(__AVX512F__) || (defined(ARM_BF16_SUPPORT))
573
+#if defined(__AVX512F__) || \
574
+ (defined(__aarch64__) && !defined(__APPLE__) && defined(ARM_BF16_SUPPORT))
575
ops.def(
576
"prepack_moe_weight(Tensor weight, Tensor(a1!) packed_weight, str isa) "
577
"-> ()");
@@ -581,7 +582,7 @@ TORCH_LIBRARY_EXPAND(TORCH_EXTENSION_NAME, ops) {
582
"bool skip_weighted, "
583
"str act, str isa) -> ()");
584
ops.impl("cpu_fused_moe", torch::kCPU, &cpu_fused_moe);
584
-#endif // #if defined(__AVX512F__) || (defined(ARM_BF16_SUPPORT))
585
+#endif
586
ops.def(
587
"mla_decode_kvcache("
588
" Tensor! out, Tensor query, Tensor kv_cache,"