Skip to content

lib: Compile Mes libc against a compiler's own stddef.h and stdarg.h - #8

Merged
aoinoikaz merged 2 commits into
windows-pe32-ntcallfrom
libc-compiler-headers
Nov 6, 2026
Merged

aoinoikaz merged 2 commits into
windows-pe32-ntcallfrom
libc-compiler-headers

Conversation

@aoinoikaz

Copy link
Copy Markdown

TinyCC's first round in nova-nix compiles Mes libc with TCC_TARGET_PE and TinyCC's own include directory before Mes's, as nixpkgs' tinycc-boot-mes orders them. Two assumptions in Mes's headers stopped it:

  • include/sys/types.h defined wchar_t as int whatever the compiler. A PE tcc's stddef.h defines it as __WCHAR_TYPE__, unsigned short, and tcc refuses the second definition. wchar_t is now __WCHAR_TYPE__ where the compiler names one; MesCC names none and keeps int.
  • vfprintf.c and vsnprintf.c read %e, %f and %g with va_arg8, which only include/stdarg.h defines. Where it is undefined they now use va_arg, which a compiler's own stdarg.h defines to read a double. With include/stdarg.h nothing changes, so MesCC keeps va_arg8, for the reason 481d302 gives against nixpkgs' plain replacement.

A tcc built from janneke's ea3900f with tinycc-boot-mes's defines, as a cross compiler, compiles the x86.windows.gcc libc, crt1.c, libtcc1.c and getopt.c and links a hello against them with this change. Before it, libc stops at wchar_t, then at va_arg8.

Not covered: the MesCC-built libraries and the MesCC-built tcc on Windows, which nova-nix's TinyCC job builds once it pins this.

Refs Novavero-AI/nova-nix#389.

The type of a wide character literal is the compiler's to decide for its
target, and it names that type __WCHAR_TYPE__; a TinyCC that writes PE
names unsigned short, Windows' width.  Mes defined wchar_t as int
whatever the compiler, so such a TinyCC compiling Mes libc against its
own stddef.h, whose wchar_t is __WCHAR_TYPE__, stopped at the second
definition with "incompatible redefinition of 'wchar_t'".  MesCC names
no __WCHAR_TYPE__ and keeps int.

* include/sys/types.h (wchar_t): Define as __WCHAR_TYPE__ where the
compiler names one.
include/stdarg.h defines va_arg8, which these read the argument of %e,
%f and %g with, and, but for RISC-V and a system C library, a va_arg
that reads every argument as a long.  A compiler's own stdarg.h, which a
C library may be compiled against in its place, defines va_arg alone,
and its va_arg reads a double as one: TinyCC's for i386 steps over the
double's eight bytes.  So a TinyCC compiling Mes libc with its own
include directory first, as nixpkgs' tinycc-boot-mes does, stopped at
va_arg8.  Where va_arg8 is undefined these now read a double with
va_arg; with include/stdarg.h nothing changes.  nixpkgs replaces va_arg8
with va_arg instead, which with include/stdarg.h reads a double as a
long.

* lib/stdio/vfprintf.c (va_arg8): Define as va_arg where stdarg.h does
not define it.
* lib/stdio/vsnprintf.c (va_arg8): Likewise.
@aoinoikaz
aoinoikaz merged commit 4ea66eb into windows-pe32-ntcall Nov 6, 2026
3 checks passed
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