feat(windows): the ludic CLI and ludic bundle on Windows

The CLI's shell commands go through shell(), which is run() on POSIX and a
scratch script handed to Git for Windows' bash on Windows (exit codes read
directly there). compile_app links through `ludicc -o` on Windows, ludic run
starts the .exe, and ludic-dev build and ensure_ludicc assemble
selfhost/ludicc.win.seed.ll, which ludic-dev reseed now writes beside the
macOS seed. ludic bundle makes build/<name>/ with a GUI-subsystem exe carrying
the .ico beside `app icon` as an llvm-rc resource, game.lpak and packs.index;
ludicc gains --gui and --link, and quotes its whole link line for cmd.exe.

Verified: ludic-dev test 135/135, selfhost-test 32/32; on the PC a checkout
bootstraps from the Windows seed, ludic-dev build makes the toolchain, and
`ludic bundle` makes build/Maroon Lake/, which runs from its own folder.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-13 03:01:33 +03:00
parent 63d9f61bf1
commit 55b0e2ebf6
22 changed files with 112450 additions and 818 deletions

View file

@ -218,7 +218,7 @@ function cmd_new() -> int {
err(`ludic new: {name} already exists\n`)
return 1
}
run(`mkdir -p {name}/src {name}/tests {name}/assets`)
shell(`mkdir -p {name}/src {name}/tests {name}/assets`)
if not write_file(`{name}/package.ludic`, template_manifest(name)) {
err(`ludic new: cannot write {name}/package.ludic\n`)
return 1
@ -312,7 +312,7 @@ function cmd_run() -> int {
if entry == "" { return no_entry() }
let out = output_path(entry)
if not compile_app(entry, out, g_mode, g_save) { return 1 }
return sh(`./{out}`)
return sh(`./{exe_name(out)}`)
}
# `ludic mygame.ludic` — the file is argv[1], so the scan starts there.
@ -322,7 +322,7 @@ function cmd_run_file() -> int {
if entry == "" { return no_entry() }
let out = output_path(entry)
if not compile_app(entry, out, g_mode, g_save) { return 1 }
return sh(`./{out}`)
return sh(`./{exe_name(out)}`)
}
# ---- ludic test -------------------------------------------------------------
@ -354,7 +354,7 @@ function cmd_test() -> int {
if not file_exists(files[mi]) { err(`ludic test: no such file: {files[mi]}\n`); return 1 }
mi += 1
}
run("mkdir -p build")
shell("mkdir -p build")
var failed = 0
var i = 0
while i < len(files) {
@ -508,7 +508,7 @@ function cmd_doctor() -> int {
function cmd_version() -> int {
let cc = ludicc()
if is_exec(cc) {
run(`{cc} --version`)
shell(`{cc} --version`)
return 0
}
let v = read_file(`{ludic_home()}VERSION`)