Here’s something I wrote about some different use-cases and information on how to use the recently-merged Windows resource compilation powers of the Zig compiler.
This is amazing work, thank you @squeek502 !
Some comments on the article:
- Perhaps you could suggest what to do when you have a non-UTF16
.rcfile – how do you convert it so that it is accepted byzig rc? - In one of the command-line examples you pass an option as
-rcflags /c65001. Would-rcflags c65001be better / nicer? This looks particularly weird inbuild.zig’s code, such as.flags = &.{"/c65001"}, where.flags = &.{"c65001"}seems (to me) more natural. - Maybe you could accept
-and/to introduce command-line options everywhere? And perhaps even be clever about what was actually used, so that-path /bin/foois not interpreted as two options, but an option name and a path? I have been bitten in the past by/in the command line…
Anyway, again, wonderful work!
It’s a little bit complicated. If the .rc file contains only characters within the Windows-1252 range, then converting to Windows-1252 would be the way to go (Windows-1252 is the default code page). If the .rc file has characters outside of that range, then you’d need to convert to UTF-8 and set the code page to UTF-8 (either via the /c65001 CLI option or via #pragma code_page(65001) in the .rc file).
I’ll likely update the article to include some info along these lines.
Note that -rcflags <flags> -- just passes whatever is in <flags> to the resinator CLI parser, so e.g. -rcflags /c65001 /DUNICODE -- would just pass the flags /c65001 /DUNICODE to resinator. The -rcflags <flags> -- model is based on the similar -cflags <flags> -- used by Zig for passing C compiler flags for .c files (you can use Build.Step.Compile.addCSourceFiles with some flags specified and then zig build --verbose to see -cflags <flags> -- in action).
The argument parsing matches how rc.exe works, so because drop-in compatibility is a goal, there’s not much wiggle room here. Note that any of /, -, or -- are accepted prefixes for all options/flags, though (-- being an accepted prefix is not true of rc.exe, but it doesn’t hurt drop-in compatibility). Another thing to note is that options can be combined together in a single argument, and that spaces are optional between an option and its value. For example, these are all equivalent command line options:
rc.exe /vnlnen-us file.rc
rc.exe /v /n /lnen-us file.rc
rc.exe /v /n /ln en-us file.rc
rc.exe -v -n -ln en-us file.rc
(this set of options means ‘enable verbose mode’, ‘append NUL to string table strings’, and ‘set default language to US English’)
As a fun little aside, I’m pretty proud of how resinator prints error messages for CLI argument errors given how CLI parsing works:

(sadly, these diagnostics will only show up when using zig rc, they won’t be quite as fancy when you’re compiling via zig build-exe or zig build since the Zig error messages are very geared towards source file-based errors)
EDIT: Another thing worth noting: resinator/zig rc tries to be helpful if it thinks an argument parsing failure is due to an absolute path being treated as a CLI option:
> resinator /some/absolute/path/option.rc
<cli>: error: the /s option is unsupported
... /some/absolute/path/option.rc
~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
<cli>: error: missing input filename
<cli>: note: if this argument was intended to be the input filename, then -- should be specified in front of it to exclude it from option parsing
... /some/absolute/path/option.rc
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Awesome to see this come to fruition! Great work!