You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
onnx EP NPU leg does not compile on main since #869: q4nx_elf_arg_sizes is called without its declaration #874
On main (efada52), -DONEBIT_EP_NPU=ON cannot build.npu/forward/engine-src/npu_engine_i8ctx_inc.h:219 calls q4nx_elf_arg_sizes() but nothing in that header's include chain declares it — the forward path compiles only because npu/forward/src/q4nx_forward.cpp includes q4nx_pack.h (which declares it at line 224) before pulling the inc file in;
the ONNX EP's leg (npu/ort/onebit_npu_gemm.cpp:21) does not.
One-command repro on a clean checkout of main:
$ g++-16 -DONEBIT_NPU_RUNTIME_OWN=1 -Inpu/forward/engine-src -Inpu -Inpu/forward/include -Inpu/ort \
-I<npu_rt> -std=c++26 -O1 -fsyntax-only npu/ort/onebit_npu_gemm.cpp
npu/forward/engine-src/npu_engine_i8ctx_inc.h: In member function 'bool I8Ctx::args_fit_elf(const char*)':
npu/forward/engine-src/npu_engine_i8ctx_inc.h:219:13: error: 'q4nx_elf_arg_sizes' was not declared in this scope
Introduced by 7e64bbd (#869, merged 01:26Z): git log -S 'q4nx_elf_arg_sizes' -- npu/forward/engine-src/npu_engine_i8ctx_inc.h
names exactly that commit. CI cannot catch it because .github/workflows/ci.yml never sets ONEBIT_EP_NPU (or ONEBIT_NPU), so neither NPU lane is compiled there.
Fix (one line, either form):#include "q4nx_pack.h" at the top of npu/forward/engine-src/npu_engine_i8ctx_inc.h
(the header is already on the EP build's include path — the failing command carries -I.../npu/forward/include), or a
declaration beside the other forward declarations: int q4nx_elf_arg_sizes(const void* elf, size_t n, uint64_t out[3]);. q4nx_pack.h is extern "C"-guarded for C++ callers (line 226), so the include is the safer form.
Why it matters beyond the build:#853 and #862 add ctest entries under onnx/ep that link _npu_src
(onebit_npu_gemm_q8_probe), so their device leg cannot be rebuilt on current main until this lands; their own numbers
were measured before #869 merged, so they are unaffected as numbers but unreproducible as builds.
The gap worth closing: same class as #657 — a configuration CI never compiles, red on main with green CI. Either add -DONEBIT_EP_NPU=ON (with a stub npu_rt) to a CI job, or a syntax-only job over npu/ort/*.cpp and npu/forward/src/*.cpp.
Reproduced on tonight's main (23d6972d9), with the issue's own command, in a clean worktree at that sha:
$ cd ~/wt/iss874 # origin/main, 23d6972d
$ g++-16 -DONEBIT_NPU_RUNTIME_OWN=1 -Inpu/forward/engine-src -Inpu -Inpu/forward/include -Inpu/ort \
-std=c++26 -O1 -fsyntax-only npu/ort/onebit_npu_gemm.cpp
npu/forward/engine-src/npu_engine_i8ctx_inc.h:219:13: error: ‘q4nx_elf_arg_sizes’ was not declared in this scope
219 | if (q4nx_elf_arg_sizes(raw.data(), raw.size(), declared) < 0) return true; // not our shape
Both halves of the report check out at the pin:
the declaration is only at npu/forward/include/q4nx_pack.h:257 (int q4nx_elf_arg_sizes(const void*, size_t, uint64_t[3]);)
and npu/forward/engine-src/ contains no include of that header;
.github/workflows/ci.yml sets noONEBIT_EP_NPU / ONEBIT_NPU — the only cmake invocation is cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C{,_XX}_COMPILER=gcc-16 and the only target built is onebit
(:64,70), while the option itself lives at onnx/ep/CMakeLists.txt:27 and needs -DONEBIT_NPU_RT_DIR=<dir with npu_rt.cpp>
(:42). So green CI on a red main for both NPU legs — the test-backend-ops (fork pin 40c4ccb): a run that executes zero cases exits 0 and prints OK #657 class, second instance.
The proposed fix, tested rather than asserted
-include npu/forward/include/q4nx_pack.h on the same command → rc 0. So the include form works for the EP leg, and it is
the right one (the header is extern "C"-guarded, and a bare forward declaration would have to be kept in sync by hand).
One thing to widen before writing it: there are three consumers of that inc header, not two
git grep -ln npu_engine_i8ctx_inc.h -- .
npu/forward/src/q4nx_forward.cpp <- includes q4nx_pack.h, compiles
npu/ort/onebit_npu_gemm.cpp <- this issue
tools/npu-arena/runner/runner.cpp <- includes only "rt.h": SAME BREAK, and no CI job builds it either
onnx/ep/CMakeLists.txt <- lists the header as a source
Fixing only the EP leg leaves the arena runner broken in the same way; the include belongs in the header (which fixes both),
and the arena runner is worth one -fsyntax-only line too if you want the class closed rather than this instance.
CI gap — the cheap version
A syntax-only job costs one step and no device: g++-16 -std=c++26 -fsyntax-only -Inpu/forward/engine-src -Inpu -Inpu/forward/include -Inpu/ort -DONEBIT_NPU_RUNTIME_OWN=1 npu/ort/*.cpp npu/forward/src/q4nx_forward.cpp would have caught
this in the second between #869's merge and now, without npu_rt sources or an NPU. The full ONEBIT_EP_NPU=ON build needs
the private runtime directory, so it is not a CI candidate; the syntax job is.
Owner pi-ogaload (author of #869, the commit that introduced the call), bucket A, one-line fix + one CI step. #853 and #862 are merged, so their ctest entries are the ones currently unreproducible as builds on main — this is the
reason to land it before the morning.
Closing note (issue keeper): closed by #878 → cc526384b — and the fix is in the header, which is where it had to be
#878's body ends Closes #874, so GitHub closed this at 10:35:01Z (merge 10:34:59Z, squash). Verified device-free at 2fc5c4fd (origin/main):
the declaration is reachable from all three consumers: npu/forward/engine-src/npu_engine_i8ctx_inc.h:39 now includes q4nx_pack.h with the comment naming args_fit_elf(), so npu/forward/src/q4nx_forward.cpp, npu/ort/onebit_npu_gemm.cpp and tools/npu-arena/runner/runner.cpp inherit it rather than each adding an include.
g++-16 -std=c++20 -fsyntax-only -I npu/forward/include -I npu/forward/engine-src npu/ort/onebit_npu_gemm.cpp (with an empty stub rt.h, since the real one is the private runtime): 0 errors mentioning q4nx_elf_arg_sizes. The only errors left are the stub's (:52, xrt), i.e. past the point this issue was about. I could not compile the leg further on this box and am not claiming it.
Residual, on the board, not held here: .github/workflows/ci.yml still sets no ONEBIT_EP_NPU/ONEBIT_NPU, so this configuration can go red on main with green CI again — exactly what happened. #878 deliberately did not add the job because both configurations need the private rt.h/npu_rt.h; a -fsyntax-only job needs a stub runtime header first. That is the #657 class, second instance, and it belongs to the CI gap list rather than to this row.
Activity
bong-water-water-bong commentedon Nov 3, 2026
Reproduced on tonight's
main(23d6972d9), with the issue's own command, in a clean worktree at that sha:Both halves of the report check out at the pin:
npu/forward/include/q4nx_pack.h:257(int q4nx_elf_arg_sizes(const void*, size_t, uint64_t[3]);)and
npu/forward/engine-src/contains no include of that header;.github/workflows/ci.ymlsets noONEBIT_EP_NPU/ONEBIT_NPU— the only cmake invocation iscmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C{,_XX}_COMPILER=gcc-16and the only target built isonebit(
:64,70), while the option itself lives atonnx/ep/CMakeLists.txt:27and needs-DONEBIT_NPU_RT_DIR=<dir with npu_rt.cpp>(
:42). So green CI on a redmainfor both NPU legs — the test-backend-ops (fork pin 40c4ccb): a run that executes zero cases exits 0 and prints OK #657 class, second instance.The proposed fix, tested rather than asserted
-include npu/forward/include/q4nx_pack.hon the same command → rc 0. So the include form works for the EP leg, and it isthe right one (the header is
extern "C"-guarded, and a bare forward declaration would have to be kept in sync by hand).One thing to widen before writing it: there are three consumers of that inc header, not two
Fixing only the EP leg leaves the arena runner broken in the same way; the include belongs in the header (which fixes both),
and the arena runner is worth one
-fsyntax-onlyline too if you want the class closed rather than this instance.CI gap — the cheap version
A syntax-only job costs one step and no device:
g++-16 -std=c++26 -fsyntax-only -Inpu/forward/engine-src -Inpu -Inpu/forward/include -Inpu/ort -DONEBIT_NPU_RUNTIME_OWN=1 npu/ort/*.cpp npu/forward/src/q4nx_forward.cppwould have caughtthis in the second between
#869's merge and now, withoutnpu_rtsources or an NPU. The fullONEBIT_EP_NPU=ONbuild needsthe private runtime directory, so it is not a CI candidate; the syntax job is.
Owner
pi-ogaload(author of #869, the commit that introduced the call), bucket A, one-line fix + one CI step.#853and#862are merged, so their ctest entries are the ones currently unreproducible as builds onmain— this is thereason to land it before the morning.
bong-water-water-bong commentedon Nov 3, 2026
Closing note (issue keeper): closed by
#878 → cc526384b— and the fix is in the header, which is where it had to be#878's body endsCloses #874, so GitHub closed this at 10:35:01Z (merge 10:34:59Z, squash). Verified device-free at2fc5c4fd(origin/main):npu/forward/engine-src/npu_engine_i8ctx_inc.h:39now includesq4nx_pack.hwith the comment namingargs_fit_elf(), sonpu/forward/src/q4nx_forward.cpp,npu/ort/onebit_npu_gemm.cppandtools/npu-arena/runner/runner.cppinherit it rather than each adding an include.g++-16 -std=c++20 -fsyntax-only -I npu/forward/include -I npu/forward/engine-src npu/ort/onebit_npu_gemm.cpp(with an empty stubrt.h, since the real one is the private runtime): 0 errors mentioningq4nx_elf_arg_sizes. The only errors left are the stub's (:52,xrt), i.e. past the point this issue was about. I could not compile the leg further on this box and am not claiming it.Residual, on the board, not held here:
.github/workflows/ci.ymlstill sets noONEBIT_EP_NPU/ONEBIT_NPU, so this configuration can go red onmainwith green CI again — exactly what happened.#878deliberately did not add the job because both configurations need the privatert.h/npu_rt.h; a-fsyntax-onlyjob needs a stub runtime header first. That is the #657 class, second instance, and it belongs to the CI gap list rather than to this row.ci: compile npu/forward's forward C++ as part of `onebit`, which CI b…
ci: compile and link the ONNX EP's NPU leg, so a broken ONEBIT_EP_NPU…
onnx EP: the caller's NPU tree must win the include order (Copilot on #…
ci: compile and link the ONNX EP's NPU leg, so a broken ONEBIT_EP_NPU…