Skip to content

ggml: fix MSVC linkage conflict on the TurboQuant vec_dot - #6

Open
Pascal-SAPUI5 wants to merge 1 commit into
masterfrom
fix/msvc-linkage-conflict
Open

ggml: fix MSVC linkage conflict on the TurboQuant vec_dot#6
Pascal-SAPUI5 wants to merge 1 commit into
masterfrom
fix/msvc-linkage-conflict

Conversation

@Pascal-SAPUI5

Copy link
Copy Markdown
Owner

The inherited Server workflow has been failing its server-windows job. It is a real bug in the TurboQuant code, not fork infrastructure:

ggml-quants.h(112,15): error C2375: 'ggml_vec_dot_turbo3_0': redefinition; different linkage
ggml-quants.h(113,15): error C2375: 'ggml_vec_dot_turbo4_0': redefinition; different linkage

Cause

ggml_vec_dot_turbo3_0 / _turbo4_0 were declared in two places:

  • ggml/src/ggml-quants.h — with GGML_API
  • ggml/src/ggml-cpu/quants.h — without it

ggml-cpu/quants.c includes both. On MSVC GGML_API expands to __declspec(dllexport/dllimport), so the two declarations disagree on linkage and the compiler rejects it. gcc and clang accept it silently, so neither of our own CI jobs could see it.

Which declaration is wrong

GGML_API is the correct one. Every other vec_dot is defined in ggml-cpu/quants.c and used within the same library, so none of them needs an export attribute. TurboQuant's is the exception: it is defined in ggml-quants.c, which builds into ggml-base, and its only caller is the type-traits table in ggml-cpu/ggml-cpu.c — a different shared library. Crossing that boundary requires the attribute.

So the undecorated declaration is the one that goes, and ggml-cpu.c now takes the declaration from ggml-quants.h.

(Moving the implementation into ggml-cpu/quants.c where the other vec_dots live would also fix it and match upstream layering better, but it would drag the codebooks and unpack helpers across the same boundary — those are needed by the reference quantizer in ggml-base. Not worth it for this.)

Also: a Windows job

Added to the fork's CI. This error class is invisible to both existing jobs, and windows-latest costs nothing on a public repo. It builds ggml-cpu — the target that broke — and runs test-turboquant.

Verified

  • HIP build clean, test-turboquant 23/23
  • the MSVC job in this PR is the real check

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q5jMcvdevae8j4T36C9h2z

ggml_vec_dot_turbo3_0 and _turbo4_0 were declared twice: in ggml-quants.h with
GGML_API, and in ggml-cpu/quants.h without it. ggml-cpu/quants.c includes both,
so MSVC saw one declaration with __declspec and one without and rejected it:

  ggml-quants.h(112,15): error C2375: 'ggml_vec_dot_turbo3_0': redefinition;
  different linkage

gcc and clang accept this silently, which is why it only ever showed up in the
Windows job of an inherited upstream workflow.

GGML_API is the correct attribute here, not the spurious one: unlike every
other vec_dot, TurboQuant's is defined in ggml-quants.c, which builds into
ggml-base, while its only caller is the type-traits table in ggml-cpu — a
different shared library. So the declaration without the attribute is the one
that had to go, and ggml-cpu.c now takes it from ggml-quants.h directly.

Adds a Windows MSVC job to the fork's CI. This class of error is invisible to
both existing jobs, and windows-latest is free on a public repo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5jMcvdevae8j4T36C9h2z
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant