feat(windows): Http.* over WinHTTP, and the splash and window icon through WIC

http_win.ll implements http.ll's hs_* contract over WinHTTP: the request is a
record built on the game thread, the whole exchange runs on a worker thread,
TLS uses the system's certificate checks, and headers are answered from the
kept request handle. ludicc links it with winhttp instead of refusing Http.* on
Windows.

win32.ll decodes the splash and App.set_icon images with WIC (ole32): the
splash is a topmost borderless window at the artwork's size in points times the
display scale, composited over its background colour; the icon becomes an
HICON set on the window now or when win_open makes one.

Verified on the PC: examples/library/http.ludic prints its expected output, a
real GET to https://git.workshopsoft.io/ returns 200 with its body and
Content-Type, and the bundled Maroon Lake shows its splash centred at launch and
its icon in the title bar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-13 03:24:50 +03:00
parent 55b0e2ebf6
commit 40d78cbd92
4 changed files with 988 additions and 12 deletions

View file

@ -203,9 +203,6 @@ entry {
if emit_ir { ir_flush(out); return }
if not has_target { ir_flush(null); return }
# Http.* is still a macOS platform layer (NSURLConnection) with no Windows
# counterpart; linking it would fail on Objective-C symbols rather than say so.
if g_target_win and g_uses_http { die("ludicc: Http.* is not available on Windows yet\n") }
# a run with no explicit -o lands in a temp file
if run and (out == null) {
@ -243,7 +240,8 @@ entry {
let win32 = join_path(home, "runtime/native/win32.ll")
# xinput.lib carries an import named DllMain, which lld skips with a warning on every
# link; it is the SDK's, not a mistake in the program, so it is silenced
cmd = `{cmd} {win32} -luser32 -lgdi32 -lxinput -Wl,/ignore:importeddllmain`
# ole32 for WIC, which decodes the splash and the window icon
cmd = `{cmd} {win32} -luser32 -lgdi32 -lxinput -lole32 -Wl,/ignore:importeddllmain`
if g_uses_audio {
let audiow = join_path(home, "runtime/native/audio_win.ll")
cmd = `{cmd} {audiow} -lxaudio2 -lole32`
@ -268,9 +266,15 @@ entry {
# Http.* (#6) links the native transport and Foundation (NSURLConnection etc.,
# reached by name). Works headless too, so it is outside the windowed block —
# macOS-only for now, which is where the toolchain runs.
# On Windows the transport is http_win.ll, over WinHTTP.
if g_uses_http {
let http = join_path(home, "runtime/native/http.ll")
cmd = `{cmd} {http} -Wl,-needed_framework,Foundation`
if g_target_win {
let httpw = join_path(home, "runtime/native/http_win.ll")
cmd = `{cmd} {httpw} -lwinhttp`
} else {
let http = join_path(home, "runtime/native/http.ll")
cmd = `{cmd} {http} -Wl,-needed_framework,Foundation`
}
}
# Gl.* links the OpenGL backend: gl.ll (offscreen contexts, float helpers), the
# generated per-entry-point ABI thunks, and OpenGL.framework. Windowed or not.