There is no way to pass a linker flag to the platform linker driver. Some flags change what kind of executable you get rather than what it links against, and -mwindows — which selects the Windows GUI subsystem — is the one that blocked us.
Version: scriptc 0.0.35, checked on macOS 26.5 arm64 and on windows-latest with llvm-mingw.
What I tried
system_libraries rejects it:
$ scriptc build main.ts --ffi ffi.json -o app
ffi.json:1:1 - error SC5001: FFI manifest invalid: 'system_libraries[0]' is not a library name: '-mwindows'
and it would not have worked anyway, since entries are mapped to -l${name} — the flag would arrive as -l-mwindows.
libraries is not a route either: entries must resolve to existing files ('libraries[i]' does not name a file), so a bare flag can't ride in there.
Nor is there an environment variable: the only ones the cc backend reads are SCRIPTC_CACHE_DIR, SCRIPTC_CACHE_MAX_MB, SCRIPTC_FETCH_CURL, plus SCRIPTC_TEST_*. SCRIPTC_CC selects the driver but takes no extra arguments.
Why it matters
A console-subsystem Windows binary makes the OS open a console window behind the app's real window. For anything with a GUI that is simply wrong, and -mwindows (or -Wl,--subsystem,windows) is the standard one-flag fix.
Our workaround, for reference
We patch the linked PE afterwards: locate the optional header via the MZ/PE offsets, validate the magic (0x10b/0x20b), and rewrite the Subsystem byte from IMAGE_SUBSYSTEM_WINDOWS_CUI (3) to IMAGE_SUBSYSTEM_WINDOWS_GUI (2), refusing to touch anything that doesn't look like the console-subsystem PE we just produced. It works, and CI runs the resulting binary to a clean exit, but rewriting a compiler's output is a strange thing to have to do for a documented linker flag.
Suggestion
Any one of these would be enough, in rough order of how small they seem:
- an allowlist of safe passthrough flags in the FFI manifest (
link_flags, validated against a known set)
- a
SCRIPTC_LDFLAGS environment variable, matching the existing SCRIPTC_CC escape hatch
- a first-class
--subsystem=windows|console option, since this particular flag is really a property of the executable being produced rather than a linking detail
Context
We're building janela, a Tauri-style desktop framework: TypeScript backend compiled by scriptc, OS webview for the window, no JS engine bundled. Windows support otherwise works well — thanks for a compiler that made that possible at all. (Related: #255 is still open and still reproduces on 0.0.35.)
There is no way to pass a linker flag to the platform linker driver. Some flags change what kind of executable you get rather than what it links against, and
-mwindows— which selects the Windows GUI subsystem — is the one that blocked us.Version: scriptc 0.0.35, checked on macOS 26.5 arm64 and on
windows-latestwith llvm-mingw.What I tried
system_librariesrejects it:and it would not have worked anyway, since entries are mapped to
-l${name}— the flag would arrive as-l-mwindows.librariesis not a route either: entries must resolve to existing files ('libraries[i]' does not name a file), so a bare flag can't ride in there.Nor is there an environment variable: the only ones the cc backend reads are
SCRIPTC_CACHE_DIR,SCRIPTC_CACHE_MAX_MB,SCRIPTC_FETCH_CURL, plusSCRIPTC_TEST_*.SCRIPTC_CCselects the driver but takes no extra arguments.Why it matters
A console-subsystem Windows binary makes the OS open a console window behind the app's real window. For anything with a GUI that is simply wrong, and
-mwindows(or-Wl,--subsystem,windows) is the standard one-flag fix.Our workaround, for reference
We patch the linked PE afterwards: locate the optional header via the MZ/PE offsets, validate the magic (
0x10b/0x20b), and rewrite theSubsystembyte fromIMAGE_SUBSYSTEM_WINDOWS_CUI(3) toIMAGE_SUBSYSTEM_WINDOWS_GUI(2), refusing to touch anything that doesn't look like the console-subsystem PE we just produced. It works, and CI runs the resulting binary to a clean exit, but rewriting a compiler's output is a strange thing to have to do for a documented linker flag.Suggestion
Any one of these would be enough, in rough order of how small they seem:
link_flags, validated against a known set)SCRIPTC_LDFLAGSenvironment variable, matching the existingSCRIPTC_CCescape hatch--subsystem=windows|consoleoption, since this particular flag is really a property of the executable being produced rather than a linking detailContext
We're building janela, a Tauri-style desktop framework: TypeScript backend compiled by scriptc, OS webview for the window, no JS engine bundled. Windows support otherwise works well — thanks for a compiler that made that possible at all. (Related: #255 is still open and still reproduces on 0.0.35.)