[Build][SM70] Fix the Docker source build and keep all SM70 extensions (#1207)

Two gaps in the Docker source build (docker/Dockerfile --target build):

- setup.py preloads vllm/envs_metadata.py before vllm/envs.py and installs
  scripts/serve_flash_next_nvfp4_v100.sh, but the native csrc-build stage
  copies only envs.py, __init__.py and the 27B serve script, so the stage
  stops with FileNotFoundError before compiling anything. Copy both files.
- The build stage reinstalls vLLM from the native-stage wheel with
  VLLM_USE_PRECOMPILED=1, and setup.py copies only the native libraries its
  extraction patterns name. The SM70 pattern lists sampler, exact_reduce,
  sparse_attention and qsa_device, so _sm70_qsa_indexer_C (#1127) and
  _sm70_router_C (#1147) are built but left out of the final wheel. Without
  the indexer, the QSA shared-key path reports native_extension_unavailable
  and falls back to the paged Triton indexer; the router operator tests
  skip. Add both names.

The extraction test now derives the expected libraries from the SM70/H3
CMakeExtension declarations in setup.py, so a newly declared extension
cannot be dropped silently again.

Signed-off-by: Leonccaa <166551845+Leonccaa@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
LeonandClaude Opus 5.5 authored and GitHub committed 2026-10-28 10:26:16 +08:00
1 parent 3bf45b2d86
commit 7b1cbd1727
3 files changed
+31 -11

No files matched your search

+2 -1
View File
@@ -342,13 +342,14 @@ RUN --mount=type=cache,target=/opt/uv/cache \
WORKDIR /workspace
COPY pyproject.toml setup.py CMakeLists.txt ./
COPY scripts/serve_qwen38_27b_nvfp4_v100.sh scripts/
COPY scripts/serve_qwen38_27b_nvfp4_v100.sh scripts/serve_flash_next_nvfp4_v100.sh scripts/
COPY cmake cmake/
COPY csrc csrc/
COPY flash_qla flash_qla/
COPY flashinfer-sm70 flashinfer-sm70/
COPY flash-attention-v100 flash-attention-v100/
COPY vllm/envs.py vllm/envs.py
COPY vllm/envs_metadata.py vllm/envs_metadata.py
COPY vllm/__init__.py vllm/__init__.py
# max jobs used by Ninja to build extensions
+2 -2
View File
@@ -949,8 +949,8 @@ class precompiled_wheel_utils:
r"flash_qla/ops/gated_delta_rule/chunk/sm70/[^/]+\.so"
)
sm70_ext_regex = re.compile(
r"vllm/_sm70_(?:sampler|exact_reduce|sparse_attention|qsa_device)_C"
r"(?:\.[^/]+)?\.so$"
r"vllm/_sm70_(?:sampler|exact_reduce|sparse_attention|qsa_device"
r"|qsa_indexer|router)_C(?:\.[^/]+)?\.so$"
)
h3_ext_regex = re.compile(
r"vllm/_h3_(?:w8a16|flashinfer|flashattn)_C(?:\.[^/]+)?\.so$"
+27 -8
View File
@@ -301,15 +301,34 @@ def test_source_wheel_reuse_keeps_sm70_native_operators(
compile(ast.Module(body=[function], type_ignores=[]), str(source), "exec"),
scope,
)
wheel = tmp_path / "native.whl"
names = [
f"_h3_{kind}_C.cpython-312-x86_64-linux-gnu.so"
for kind in ("w8a16", "flashinfer", "flashattn")
] + [
# The Docker build stage reinstalls from the native-stage wheel, so every
# SM70/H3 extension declared in setup.py must survive the extraction.
names: list[str] = []
for node in ast.walk(tree):
if not (
isinstance(node, ast.Call)
and getattr(node.func, "id", None) == "CMakeExtension"
):
continue
keywords = {k.arg: k.value for k in node.keywords}
declared = keywords.get("name")
module = declared.value if isinstance(declared, ast.Constant) else None
if not (
isinstance(module, str)
and re.fullmatch(r"vllm\._(?:sm70|h3)_\w+_C", module)
):
continue
limited = keywords.get("py_limited_api")
abi3 = not (isinstance(limited, ast.Constant) and limited.value is False)
suffix = ".abi3.so" if abi3 else ".cpython-312-x86_64-linux-gnu.so"
names.append(module.removeprefix("vllm.") + suffix)
assert {
"_sm70_sampler_C.abi3.so",
"_sm70_exact_reduce_C.cpython-312-x86_64-linux-gnu.so",
"_sm70_sparse_attention_C.cpython-312-x86_64-linux-gnu.so",
]
"_sm70_qsa_indexer_C.cpython-312-x86_64-linux-gnu.so",
"_sm70_router_C.cpython-312-x86_64-linux-gnu.so",
"_h3_w8a16_C.cpython-312-x86_64-linux-gnu.so",
} <= set(names)
wheel = tmp_path / "native.whl"
with zipfile.ZipFile(wheel, "w") as archive:
for name in names:
archive.writestr("vllm/" + name, b"native-test-bytes")