Skip to content

windows: build under V's bundled tcc - #104

Merged
diiviocity merged 2 commits into
vlang:masterfrom
torial:tcc-compat-windows
Oct 29, 2026
Merged

diiviocity merged 2 commits into
vlang:masterfrom
torial:tcc-compat-windows

Conversation

@torial

@torial torial commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

What

ui2 builds on Windows with the tcc that V bundles, natively and with -d ui2_custom_rendering, so v run works on a stock V install without clang, gcc or MSVC.

  • windows/tcc_compat_windows.h (new, read only under __TINYC__) declares what the Windows helpers use from the four headers tcc's winapi set lacks, commctrl.h, commdlg.h, shlobj.h and oleacc.h: the common-control, tooltip and trackbar messages and structures, the subclassing calls, OPENFILENAMEW and the file dialogs, BROWSEINFOW and the folder browser, the tray icon, and IAccessible's vtable whole (the helpers call slots past IDispatch's). Layouts and values are mingw-w64's.
  • The same header fetches, at first use and behind macros of their own names, the eight exports that V's hand-listed gdi32.def, kernel32.def and shell32.def lack: GetGlyphIndicesW, AddFontResourceExW, CreateActCtxW, ActivateActCtx, ReleaseActCtx, SHBrowseForFolderW, SHGetPathFromIDListW, Shell_NotifyIconW. tcc links those three libraries through the lists, every other one from the DLL's export table.
  • It undefines small: tcc's rpcndr.h defines it as a type unconditionally (mingw-w64's only under RC_INVOKED), and ui2 has struct fields named small, which became double char.
  • The three helpers include it in place of the missing headers under __TINYC__; ui_windows.v, file_dialog_windows.c.v and window_chrome_windows.c.v add -I @VMODROOT/windows so the quoted include resolves (V inserts the helpers into the generated C).
  • -luuid is dropped: IAccessible's id is spelled in native_helpers_windows.h, so no compiler needs uuid for it.

Why

On Windows, V's tcc failed on library 'uuid' not found (native) and commctrl.h not found (custom rendering), and V's fallback asked for a gcc a stock install does not have:

warning: implicit tcc could not be used for this build (tcc: error: library 'uuid' not found), regenerating it with gcc
builder error: C compiler `gcc` was requested with `-cc`, but was not found.

Verified

Windows 11 x86-64, V master ee6d62a. examples/editor and examples/gpui_editor build with v -cc tcc -no-retry-compilation, natively and with -d ui2_custom_rendering, and run with their windows up; the native build shows themed controls (the activation context goes through the wrappers) and the code editor draws as the clang build draws it. The same examples still build with llvm-mingw's clang. The declared names and the wrapped exports were listed mechanically, every Win32 name the helpers and the V side use against tcc's headers, and tcc's .def lists against mingw-w64's import libraries, with known-missing and known-present names as controls.

Not verified

  • The tray icon and the folder browser run only through the wrappers' code path when an application opens them; no example here does, so those two wrappers compiled and linked but did not execute.
  • MSVC. The -luuid removal and the spelled interface id should not affect it, but it was not built.
  • Other examples than the two above.

🤖 Generated with Claude Code

sean-dss and others added 2 commits October 28, 2026 16:42
V's tcc on Windows could not build ui2: its winapi header set lacks commctrl.h,
commdlg.h, shlobj.h and oleacc.h, which the Windows helpers include; it has no
uuid import library, which ui_windows.v linked for one interface id; and its
hand-listed gdi32.def, kernel32.def and shell32.def lack eight exports the
helpers and ui_windows.v call. V then fell back to gcc, which a stock Windows
install does not have, so `v run` of any ui2 program needed clang or MSVC.

windows/tcc_compat_windows.h, read only under __TINYC__, declares what the
helpers use from those four headers (the common-control, tooltip and trackbar
messages and structures, the subclassing calls, OPENFILENAMEW and the file
dialogs, BROWSEINFOW and the folder browser, the tray icon, and IAccessible's
vtable whole, since the helpers call slots past IDispatch's), with the layouts
and values of mingw-w64's headers; it fetches the eight missing exports from
their DLLs at first use behind macros of their own names (GetGlyphIndicesW,
AddFontResourceExW, CreateActCtxW, ActivateActCtx, ReleaseActCtx,
SHBrowseForFolderW, SHGetPathFromIDListW, Shell_NotifyIconW); and it undefines
`small`, which tcc's rpcndr.h defines as a type unconditionally (mingw-w64's
only under RC_INVOKED) and which ui2 has struct fields named after. The three
helpers include it in place of the missing headers under __TINYC__, the files
that insert them pass the helpers' directory as an include path (V inserts the
helper into the generated C, so a quoted include needs it), and
IAccessible's id is spelled in native_helpers_windows.h so no compiler links
uuid for it.

Verified on Windows 11 with V master ee6d62a: examples/editor and
examples/gpui_editor build with `-cc tcc -no-retry-compilation`, natively and
with -d ui2_custom_rendering, run with their windows up, the native one with
themed controls (the activation context works through the wrappers) and the
code editor drawn as the clang build draws it; the same examples still build
with llvm-mingw's clang. The declared names and the wrapped exports were
listed mechanically: every Win32 name the helpers and the V side use, checked
against tcc's headers and its .def lists against mingw-w64's import libraries,
with known-missing and known-present names as controls.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Three defects stopped the native (non-custom-rendering) tcc build, which
includes native_helpers_windows.h:

- tcc's own shellapi.h (copied from mingw-w64, in V's bundled tcc since
  2020) already defines struct _NOTIFYICONDATAW and declares
  Shell_NotifyIconW; the compat header redefined the tag, and tcc rejects
  a second definition even when identical ('struct/union/enum already
  defined' at the shellapi.h include). Include shellapi.h instead and
  keep the fallbacks behind #ifndef guards.
- the helpers call IAccessible's accDoDefaultAction
  (native_helpers_windows.h:1083), so the slot cannot stay a plain
  pointer: tcc says 'function pointer expected'. It is typed now, like
  the get_acc* slots the helpers call.
- GetTickCount64 is absent from V's hand-listed kernel32.def, so the
  plain declaration left the symbol unresolved at link; it goes through
  ui2_tcc_import like the other kernel32 exports.
- WM_MOUSEHWHEEL is missing from tcc's XP-era winuser.h; declared here
  like SM_CXPADDEDBORDER.

Verified against the real bundled header set (vlang/tccbin_win): the
whole native_helpers_windows.h, the file-dialog and window-chrome
headers, and every wrapped import compile clean with tcc 0.9.28rc; the
unfixed header reproduces all three failures.
@metif12

metif12 commented Oct 29, 2026

Copy link
Copy Markdown
Member

Verified on Windows 11 x64 with V 0.5.2 (bundled tcc) and gcc.

Builds (native): editor, tray_icon, file_dialog, fontchooser - OK.
Builds (custom rendering): gpui_editor, gpui_theme - OK.
Tests: windows/ui_windows_test.v, c/api_test.v, ui/file_dialog_test.v, component_catalog_test.v, vml_menu_test.v, embed_test.v, menu_tray_test.v, ui_custom_rendering_test.v - all pass with -cc tcc.
Non-tcc toolchain (gcc) still works.

Notes:

  • PR text says eight exports, but header wraps nine (includes GetTickCount64, which is already in V's kernel32.def, so redundant but harmless).
  • Typed accDoDefaultAction vtable slot and spelled IID_IAccessible are correct.
  • -luuid removal is safe (no other references).
  • CI runs examples with -W; five pre-existing mutability notices in windows/ui_windows.v become errors under -W. Unrelated to this PR, but worth a follow-up.

LGTM for the stated goal.

@diiviocity
diiviocity merged commit 1dc38c5 into vlang:master Oct 29, 2026
@torial

torial commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Thank you for the verification on Windows with both compilers. You are right on the count: the header wraps nine exports, not eight; GetTickCount64 is already in V's kernel32.def and its wrapper is redundant. If a follow-up on the five -W mutability notices in windows/ui_windows.v would be welcome, I can open it.

@metif12

metif12 commented Oct 29, 2026

Copy link
Copy Markdown
Member

Thank you for the verification on Windows with both compilers. You are right on the count: the header wraps nine exports, not eight; GetTickCount64 is already in V's kernel32.def and its wrapper is redundant. If a follow-up on the five -W mutability notices in windows/ui_windows.v would be welcome, I can open it.

yes, pls do. and thank you for your help

@torial

torial commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

Opened as #105: the five handle copies spelled voidptr(x), verified on Windows with V master under tcc and clang. Thank you again for the review.

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.

4 participants