Skip to content

Commit 317afa6

Browse files
builtin: fix GetFinalPathNameByHandleW declaration for TCC on Windows
TCC''s bundled <windows.h> does not include <fileapi.h>, so GetFinalPathNameByHandleW had no C declaration in scope when TCC compiled any program that pulled in builtin (e.g. via os.real_path). TCC (in C99 mode) treats implicit function declarations as hard errors. Provide the declaration for TCC only, via a header that is #insert-ed under $if windows and guarded with `#ifdef __TINYC__`: - TCC: __TINYC__ is defined, so the extern is supplied. TCC''s own <fileapi.h> cannot be used instead because it pulls in <apiset.h>, a header TCC does not ship. - GCC/MSVC: __TINYC__ is not defined, so the extern is skipped and the call resolves against the SDK header that <windows.h> pulls in transitively. Emitting a V-side extern here would conflict with the SDK''s `DWORD WINAPI` signature (DWORD is unsigned long, not u32). Gating in the C preprocessor (rather than a comptime `$if tinyc`) is deliberate: it keeps the guard intact under `-cross`, where V emits all declarations unconditionally. The same `#ifdef __TINYC__` idiom is already used for TCC/Windows in vlib/v/gen/c/cheaders.v. Verified on Windows: generated C wraps the extern in `#ifdef __TINYC__` for both normal and -cross GCC builds (gcc compiles both with no conflict), and `vlib/os/` tests pass (24/24) with GCC. Co-Authored-By: WOZCODE <contact@withwoz.com>
1 parent 6c4d26f commit 317afa6

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

vlib/builtin/cfns.c.v

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,13 @@ fn C.CreateFile(lpFilename &u16, dwDesiredAccess u32, dwShareMode u32, lpSecurit
295295
fn C.CreateFileW(lpFilename &u16, dwDesiredAccess u32, dwShareMode u32, lpSecurityAttributes &u16, dwCreationDisposition u32,
296296
dwFlagsAndAttributes u32, hTemplateFile voidptr) voidptr
297297

298-
fn C.GetFinalPathNameByHandleW(hFile voidptr, lpFilePath &u16, nSize u32, dwFlags u32) u32
298+
$if windows {
299+
// The TCC-only declaration is guarded with `#ifdef __TINYC__` in the
300+
// header, so it survives cross compilation; GCC/MSVC use the SDK header.
301+
#insert "@VEXEROOT/vlib/builtin/cfns_windows_tcc.h"
302+
303+
fn C.GetFinalPathNameByHandleW(hFile voidptr, lpFilePath &u16, nSize u32, dwFlags u32) u32
304+
}
299305

300306
fn C.CreatePipe(hReadPipe &voidptr, hWritePipe &voidptr, lpPipeAttributes voidptr, nSize u32) bool
301307

vlib/builtin/cfns_windows_tcc.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// TCC's bundled <windows.h> does not include <fileapi.h>, and TCC's own
2+
// <fileapi.h> cannot be used either because it pulls in <apiset.h>, a header
3+
// TCC does not ship. As a result GetFinalPathNameByHandleW has no declaration
4+
// in scope when TCC compiles code that uses it (e.g. os.real_path).
5+
//
6+
// Provide the declaration for TCC only. GCC/MSVC get it from the Windows SDK
7+
// (via <windows.h> -> <fileapi.h>); emitting a V-side extern there would
8+
// conflict with the SDK's `DWORD WINAPI` signature, since DWORD is
9+
// `unsigned long`, not `unsigned int`.
10+
#ifdef __TINYC__
11+
#ifndef GetFinalPathNameByHandleW
12+
extern unsigned int GetFinalPathNameByHandleW(void *hFile, unsigned short *lpFilePath,
13+
unsigned int nSize, unsigned int dwFlags);
14+
#endif
15+
#endif

0 commit comments

Comments
 (0)