Summary
When winml build --compile targets a device/EP that isn't present on the build machine and the EP produces an EPContext (e.g. OpenVINO, QNN), the build runs the entire pipeline — export → optimize → analyze → quantize (~minutes) — and only fails at the final Compile stage.
Repro
On a machine without an NPU:
winml build -m microsoft/resnet-50 --ep openvino --device npu --compile --use-cache
✅ Export 9.5s
✅ Optimize 140.0s
✅ Quantize 13.2s
⏳ Compile Compiling for OPENVINO…
Error: Build failed: Failed to compile for npu … Device 'npu' requested but no compatible EP is available.
Exit 1 after ~163s of wasted work.
Desired
For a compile build, fail fast — right after config generation, before export — when the target EP/device isn't available. The error already exists (resolve_device raises it at the compile stage); it just needs to be surfaced up front.
Must NOT regress (verified working in #947)
--no-compile cross-compile: builds a portable, analyzed/quantized ONNX for a device absent on the machine → must still succeed.
--compile with an EP that has no EPContext (MIGraphX, DML): compile is a no-op → must still succeed.
So the early gate must be conditioned on config.compile is not None (i.e. an EPContext-producing provider), not merely on --compile being passed.
Context
Surfaced in #947. An earlier iteration of that PR added a compile-availability gate but it was reverted in favor of the resolve_check_device_ep static-validation approach (which enables cross-compile). This early fail-fast gate for real compile builds is the deferred remaining piece.
Summary
When
winml build --compiletargets a device/EP that isn't present on the build machine and the EP produces an EPContext (e.g. OpenVINO, QNN), the build runs the entire pipeline — export → optimize → analyze → quantize (~minutes) — and only fails at the final Compile stage.Repro
On a machine without an NPU:
Exit 1 after ~163s of wasted work.
Desired
For a compile build, fail fast — right after config generation, before export — when the target EP/device isn't available. The error already exists (
resolve_deviceraises it at the compile stage); it just needs to be surfaced up front.Must NOT regress (verified working in #947)
--no-compilecross-compile: builds a portable, analyzed/quantized ONNX for a device absent on the machine → must still succeed.--compilewith an EP that has no EPContext (MIGraphX, DML): compile is a no-op → must still succeed.So the early gate must be conditioned on
config.compile is not None(i.e. an EPContext-producing provider), not merely on--compilebeing passed.Context
Surfaced in #947. An earlier iteration of that PR added a compile-availability gate but it was reverted in favor of the
resolve_check_device_epstatic-validation approach (which enables cross-compile). This early fail-fast gate for real compile builds is the deferred remaining piece.