Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a .rc -> .res compiler to the Zig compiler #17069

Merged
merged 11 commits into from
Sep 22, 2023

Conversation

squeek502
Copy link
Collaborator

@squeek502 squeek502 commented Sep 4, 2023

This integrates resinator into the Zig compiler and closes #3702. This will provide Zig with the ability to compile (and cross-compile) Windows resource files into byte-for-byte identical .res files when compared to the canonical rc.exe implementation.

I gave a talk about resinator a little bit ago if you want more detail: https://www.youtube.com/watch?v=RZczLb_uI9E

Still some stuff left to do before this should be merged, but it's far enough along that it's ready for feedback.

How it's used

In the simplest form, you can just give the path to the .rc file via the command line like any other source file:

zig build-exe main.zig my_resource_file.rc

the equivalent in build.zig would be:

exe.addWin32ResourceFile(.{ .file = .{ .path = "my_resource_file.rc" } });

If you need to pass rc.exe-like flags, -rcflags <flags> -- can be used before the .rc file like so:

zig build-exe main.zig -rcflags /c65001 -- my_resource_file.rc

the equivalent in build.zig would be:

exe.addWin32ResourceFile(.{
    .file = .{ .path = "my_resource_file.rc" },
    // Anything that rc.exe accepts will work here
    // https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-
    // This sets the default code page to UTF-8
    .flags = &.{"/c65001"},
});

By default, zig will try to use the most appropriate system headers available (independent of the target ABI). On Windows, it will always try to use MSVC/Windows SDK include paths if they exist, and fall back to the MinGW headers bundled with Zig if not. On non-Windows, it will always use the MinGW header include paths. The intention with this is to make most .rc files work by default whenever possible, since the MSVC includes have some .rc-related include files that MinGW does not.

If the default header include behavior is unwanted, the -rcincludes option can be used:

zig build-exe main.zig my_resource_file.rc -rcincludes=none

the equivalent in build.zig would be:

exe.rc_includes = .none;

The possible values are any (this is the default), msvc (always use MSVC, no fall back), gnu (always use MinGW), or none (no system include paths provided automatically).

Note: If the target object file is not coff, then specifying a .rc or .res file on the command line is an error:

> zig build-exe main.zig zig.rc -target x86_64-linux-gnu
error: rc files are not allowed unless the target object format is coff (Windows/UEFI)

But std.Build.Compile.Step.addWin32ResourceFile can be used regardless of the target, and if the target object format is not coff, then the resource file will just be ignored.

How it works

There is a four step process for each .rc file:

  1. The flags are parsed by resinator, if there are any invalid flags it'll error and fail the compilation
  2. The .rc file is run through the clang preprocessor and turned into an intermediate .rcpp file
  3. The .rcpp file is compiled by resinator and turned into a .res file
  4. The .res file is added to the list of link objects and linked into the final binary by the linker

Note that this is all integrated with the cache system (or should be):

  • The flags are added to the cache manifest
  • The clang preprocessor outputs a .d and all dependencies are added to the cache manifest
  • Resinator provides a list of dependencies and those are all added to the cache manifest, too

So, for example, if a.rc includes b.rc and b.rc has a resource that references c.ico, then modifying any of the three will cause the .res to be recompiled.

Example

Here's a zip of an example project: zig-ico.zip

Building on Windows:

zig build

Cross-compiling:

zig build -Dtarget=x86_64-windows-gnu

Result (both the icon and the version information comes from the .rc file):

zig-ico

Stuff left to do

  • Add at least one standalone test
  • Handle non-Windows targets, most likely just ignore the RC files when the target is not Windows
  • Upstream as much of utils.zig as is feasible/wanted
  • More testing, etc, especially around error messages

@squeek502 squeek502 mentioned this pull request Sep 4, 2023
@squeek502 squeek502 force-pushed the resinator branch 2 times, most recently from c82d8c8 to 4e02f4a Compare September 6, 2023 10:50
@matu3ba
Copy link
Contributor

matu3ba commented Sep 7, 2023

All 4 failing tests on aarch64-windows have WindowsSdkNotFound:

zig build-obj llvm_targets Debug aarch64-windows-msvc: error: error: unable to create compilation: WindowsSdkNotFound

zig build-obj llvm_targets Debug aarch64-windows-msvc: error: the following command exited with error code 1:
C:\actions-runner\_work\zig\zig\build-release\stage3-release\bin\zig.exe build-obj -fllvm C:\actions-runner\_work\zig\zig\build-release\zig-local-cache\o\3cbec9eef19706ea8d1fe135a9389b2e\tmp.zig -fno-emit-bin --cache-dir C:\actions-runner\_work\zig\zig\build-release\zig-local-cache --global-cache-dir C:\actions-runner\_work\zig\zig\build-release\zig-global-cache --name llvm_targets -target aarch64-windows-msvc -mcpu generic -L C:\actions-runner\_work\zig\zig\..\zig+llvm+lld+clang-aarch64-windows-gnu-0.11.0-dev.1869+df4cfc2ec\lib -I C:\actions-runner\_work\zig\zig\..\zig+llvm+lld+clang-aarch64-windows-gnu-0.11.0-dev.1869+df4cfc2ec\include --zig-lib-dir C:\actions-runner\_work\zig\zig\lib --listen=- 
zig build-obj llvm_targets Debug x86-windows-msvc: error: error: unable to create compilation: WindowsSdkNotFound

@squeek502
Copy link
Collaborator Author

Yeah, not sure what's up. From the #compiler-devel channel in Discord:

Compiling .rc files needs the libc include directories even when not linking libc, so it looking for them is expected, but it failing to find them when targeting msvc is unexpected.

@squeek502
Copy link
Collaborator Author

squeek502 commented Sep 11, 2023

Only populating the rc include dirs when there are .rc files seemed to fix the aarch64 errors (not sure exactly why that would be the case, but the fix is a straightforward improvement anyway).


Something unanticipated that I'm running into that I'm not sure how to handle:

  • rc.exe gets its include paths from exactly two places: the %INCLUDE% environment variable and the /i option on the command line. The %INCLUDE% environment variable is set by vcvarsall.bat which also puts rc.exe in your path (vcvarsall.bat is what is used when launcing the "Developer Command Prompt"). The %INCLUDE% environment variable will contain paths from the MSVC install (e.g. C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\include, etc) and the Windows SDK/Windows Kit (e.g. C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\ucrt, etc).
    • This is important because .rc files can #include both other .rc files and .h files that can be found within these include directories (e.g. windows.h is commonly included, but there are also some .rc files distributed in the ATLMFC include dir [e.g. afxres.rc])
  • The current resinator integration uses zig clang as the preprocessor and uses addCCArgs for setup which uses -nostdinc and gets the include directories from the current target (so if the target abi is msvc, it'll get the MSVC include paths, and if the target abi is gnu, it'll get the mingw-shipped-with-zig include paths)

The problem with this:

  • The mingw includes don't (and probably can't due to licensing) contain the ATLMFC includes (note also that the ATLMFC include dir has images, icons, cursors, etc that can be needed for .rc files, too)
  • Because of this, and other minor differences between the mingw/msvc include files, it seems very possible that you'd want to use the MSVC includes for .rc files, but still target the gnu/mingw ABI for the main compilation.
  • Note that the target should have no impact on the preprocessing step/.res compilation AFAIK--the gnu or msvc ABIs themselves aren't relevant for .res compilation

So, I'm not sure what the best thing to do here is. Allowing the user to separately choose the "ABI" (really, the include paths) for .rc compilation seems like a no brainer, but then there's the question of what the default should be. It might make some sense to:

  • Use the MSVC include paths whenever they are present on the system
  • Fall back to the mingw include paths when MSVC is not found

but I'm unsure about that.


Separately, there's also a question of whether or not %INCLUDE% should be looked at when compiling .rc files. Currently it is ignored (via the ignore_include_env_var resinator option). This seems like the right choice to me, but I'm not certain about that.

@andrewrk
Copy link
Member

One thing to consider which may help us resolve these design questions is that the idea of including a res compiler tool within zig itself is for these reasons:

  • So that you can compile your applications without MSVC installed.
  • So that you can cross-compile your application, including the icon in the .exe file, from a non-Windows OS.

Otherwise, there would be no benefit to using zig's res compiler over the system-installed one that ships with MSVC right?

Given this, I think we should try to figure out how to satisfy these dependencies without relying on an MSVC installation path.

Maybe we could consider a real world use case, of compiling a game or a GUI application from source. Without the MSVC include paths available, what goes wrong?

@squeek502
Copy link
Collaborator Author

squeek502 commented Sep 15, 2023

Agreed, those are precisely the use-cases I'm trying to enable. The goal here is for things to 'just work' for basically everyone by default.

  • So that you can compile your applications without MSVC installed.
  • So that you can cross-compile your application, including the icon in the .exe file, from a non-Windows OS.

These both work, and is what the added standalone test ensures. MSVC is not required (but its includes will be used if it's available), and cross-compiling from any target works fine (it'll use the MinGW includes when cross-compiling) as long as the .rc file doesn't reference anything MSVC-specific.

Without the MSVC include paths available, what goes wrong?

For most .rc files, nothing.

It will only go wrong if the .rc file references some of the stuff distributed in things like the ATLMFC includes, and MSVC is not available (or the ATLMFC optional component is not installed). This will result in file not found errors either during preprocessing (if it's an #included file that's missing) or during compilation (if it's a resource [.ico, .cur, etc] that's missing). This seems like very reasonable behavior to me.

To be clear, MSVC not being found is currently never an error condition on its own unless -rcincludes=msvc is used to force MSVC includes to be used. By default, if MSVC is not found, then it'll always just fall back to using the MinGW includes automatically. This slient fallback is the thing that feels a bit iffy/un-Zig-like to me, but I think it might make sense for dealing with .rc files, specifically.


In terms of a real example, here's a .rc file from Windows-classic-samples that includes afxres.rc from the ATLMFC includes (afxres.rc is not distributed by MinGW).

Note: I wasn't able to get the .cpp files of that example to build properly, so I'm just compiling the .rc file with a blank .zig file into a .dll here.

By default it compiles fine (MSVC includes are used since it's installed on my system):

> zig build-lib -dynamic empty.zig COMRTS.rc

> echo %errorlevel%
0

When using -rcincludes=gnu to force the MinGW includes to get used (this emulates what would happen if MSVC wasn't installed, or we were cross-compiling from non-Windows), it will error during preprocessing:

> zig build-lib -dynamic empty.zig COMRTS.rc -rcincludes=gnu
error(compilation): clang preprocessor failed with stderr:
COMRTS.rc:210:10: fatal error: 'afxres.rc' file not found

COMRTS.rc:1:1: error: clang preprocessor exited with code 1

Note that which include paths get used when compiling .rc files is separate from the -target, so -target x86_64-windows-gnu/-target x86_64-windows-msvc will not affect which includes get used for the .rc file. This is the second part that feels a bit iffy/un-Zig-like, but again, might make sense for dealing with .rc files (without this part, then by default afxres.rc would fail to be found since it would use the gnu abi include paths).

@andrewrk
Copy link
Member

It all sounds pretty reasonable to me.

One possible idea- what if it just never tried to do the MSVC include paths ever, so that the behavior was always the same no matter the host. Then there would never be any surprises when doing a compilation on one host or another. And for people who want the MSVC includes, they could use addSystemCommand in their build scripts to use the MSVC-provided res tool instead of the Zig compiler one.

@squeek502
Copy link
Collaborator Author

squeek502 commented Sep 15, 2023

To me that would depend on what we expect the primary/supported use case of this to be. If the primary/supported use case is cross-compiling Windows programs, then consistently using MinGW includes would make some sense (to essentially force .rc files to be cross-platform in terms of which files they reference). However, if we want to support the use-case of Windows developers using Zig to compile their Windows programs on Windows, then using MinGW consistently would make it less useful than it could be.

The current approach of "use MSVC, fall back to MinGW" is geared towards being maximally useful-by-default when compiling on Windows, at the expense of a little bit of potentially surprising behavior when cross-compiling that same program from other platforms (e.g. being able to reference afxres.rc on Windows but having that fail when cross-compiling from Linux).

The other possibility (and this is how it worked at the start of this PR) would be to have the include directories match the target, so -target x86_64-windows-gnu would always use the MinGW includes, -target x86_64-windows-msvc would always use the MSVC includes, and the MinGW includes would be used by default everywhere (#6565). This would be the most consistent with how Zig works generally, but would be less useful than the "use MSVC, fall back to MinGW" strategy for Windows developers compiling on Windows.

EDIT: Also just to note, any usage of addSystemCommand with rc.exe would be a failure of the Zig resource compiler implementation in my eyes.

@andrewrk
Copy link
Member

Ultimately, I think it's your call! You did the hard work of implementing it, and you've consistently been the champion of the zig toolchain user experience on Windows. I'm happy to brainstorm with you and discuss pros and cons, but, in this matter, you da boss.

@squeek502
Copy link
Collaborator Author

Sounds good. In that case, I'm going to stick with the MSVC + fallback approach and potentially re-evaluate depending on any issues that come up afterwards.

Note that I'm nearly ready to remove the draft status of this PR. Let me know if there's anything I can do to make this easier to review for you.

…age when source_line is 0

The zero value needs special handling since it means 'no source line' and should be preserved through the copy.
https://learn.microsoft.com/en-us/cpp/mfc/mfc-and-atl

Note that this include directory gets added to %INCLUDE% by vcvarsall.bat, and is especially crucial when working with resource files (many .rc files within the https://github.com/microsoft/Windows-classic-samples/ set reference files from the ATLMFC include directory).
The include directories used when preprocessing .rc files are now separate from the target, and by default will use the system MSVC include paths if the MSVC + Windows SDK are present, otherwise it will fall back to the MinGW includes distributed with Zig. This default behavior can be overridden by the `-rcincludes` option (possible values: any (the default), msvc, gnu, or none).

This behavior is useful because Windows resource files may `#include` files that only exist with in the MSVC include dirs (e.g. in `<MSVC install directory>/atlmfc/include` which can contain other .rc files, images, icons, cursors, etc). So, by defaulting to the `any` behavior (MSVC if present, MinGW fallback), users will by default get behavior that is most-likely-to-work.

It also should be okay that the include directories used when compiling .rc files differ from the include directories used when compiling the main binary, since the .res format is not dependent on anything ABI-related. The only relevant differences would be things like `#define` constants being different values in the MinGW headers vs the MSVC headers, but any such differences would likely be a MinGW bug.
…GNU abi

Also update the standalone test so that this failure would have been detected on any host system.
@squeek502
Copy link
Collaborator Author

squeek502 commented Sep 22, 2023

Okay, I'm marking this as ready for review.

Some stuff that might be relevant:

  • I've updated the How it's used section of the OP with more complete information.
  • I've put all the resinator files into src/resinator. I noticed that Aro translate-c #17221 put the aro files into a deps/aro folder instead. Let me know if you'd like the resinator files to be put in deps as well
  • Most of the integration is based on how C source files are handled, e.g. -rcflags is modeled after -cflags, and most of the code in src/Compilation.zig is based on how C source files work

Also, I made a modified version of the scripts I use that test all the .rc files in Windows-classic-samples here:

zig now has exactly the same (perfect) results as standalone resinator on Windows (can't use Windows-classic-samples to test cross-compilation since there's a lot of case-insensitive filesystem assumptions in the .rc files, #includeing of MSVC-specific files, etc):

Processed 485 .rc files

---------------------------
  zig
---------------------------

485 .rc files processed without discrepancies
identical .rsrc outputs:    460
expected compile errors:    25

---------------------------

@squeek502 squeek502 marked this pull request as ready for review September 22, 2023 04:59
@marler8997
Copy link
Contributor

marler8997 commented Sep 22, 2023

Here are some of my thoughts as a real-world user of resinator.

First, I don't mind having to add an entry to my build.zig.zon file to use resinator...though upstreaming it into Zig does mean it should break less often.

Next, all this messy business with include directories around RC files is a pain just like it is in C. For new projects, I'd like to be able to generate .res files using a new and improved build.zig solution. Supporting the RC format is still great for enabling Zig as a general-purpose toolchain and build system, but I think we should explore new alternatives, and if we plan on doing that maybe it would affect what we decide to do with resinator in the meantime?

I'm certain Squeek is much more expert than me on the topic of win32 RC/RES files, but I imagine a build.zig solution for res files to look something like this:

const res = b.addResources();
res.addIcon("icon16", .{ .path = "myicon16.ico" });
res.addIcon("icon32", .{ .path = "myicon32.ico" });
res.addRcData("stuff", .{ .path = "generic-data-to-hide-in-my-exe"});

exe.addResources(res);

Then maybe some way to access those names:

const std = @import("std");
const res_names = @import("resource_names");

fn main() {
     std.log.info("icon16 id is {}", .{res_names.icon16});
}

@squeek502
Copy link
Collaborator Author

squeek502 commented Sep 22, 2023

I imagine a build.zig solution for res files to look something like this

This may look appealing on first glance, but there are some issues with it:

  • It would realistically only be able to support a small subset of .rc-related features, like the stuff in your example which would be relatively easy (although adding an .ico requires parsing the file , may error depending on the format, and it adds an ICON-resource-per-embedded-resolution + a GROUP_ICON resource [EDIT: oh, also it can be an animated RIFF icon]). If support for all resource types was desired, it would quickly grow in complexity to rival resinator all the same (see resources like STRINGTABLE, VERSIONINFO, DIALOG, etc)
  • For the subset of things the hypothetical addResources would support, the equivalent .rc file would be trivial to write and wouldn't need to care about include paths at all, e.g. this would be the equivalent to your example:
icon16 ICON "myicon16.ico"
icon32 ICON "myicon32.ico"
stuff RCDATA "generic-data-to-hide-in-my-exe"
  • zig plans to have a zig cc-like command that is a drop-in replacement for rc.exe (zig windres #9564). This will be easy with resinator, but essentially impossible with the hypothetical addResources

EDIT: Thinking about it more, the two approaches could probably coexist. Either addResources could generate an .rc file behind the scenes and then the path to the generated .rc file could be given to Compile.Step.addWin32ResourceFile and/or the return of addResources could have a function like addScript that takes an .rc file (and then it would do everything the current Compile.Step.addWin32ResourceFile does for the .rc files, but do something simpler for icons, etc). I'm not fully convinced it would be worth the effort, but it's something to think about for sure.

Then maybe some way to access those names:

It seems like this would mostly be reimplementing @embedFile, wouldn't it? Note also that the resources would only actually be able to be put in a useful location in the compiled binary when the object format is PE/COFF (since it's the only format with a resource table / .rsrc section).

@marler8997
Copy link
Contributor

marler8997 commented Sep 22, 2023

To clarify, I was suggesting another "front end" on top of what resinator is providing:

RC Frontend > Resinator > RES File

Suggestion:

Zig Build > Resinator > RES File

The idea being that maybe the RC frontend could remain a third party package if Zig has a way of adding resources to windows binaries in its build system. However, this is only advantageous if separating the RC frontend into another package is possible and would save a noticeable amount of code/space in the Zig toolchain. For example, if you need to parse an icon file to create a res file, then that's a piece that Zig would need either way and I would categorize that in the "Resinator" piece in the diagrams above rather than the "RC Frontend" piece. It's unclear to me how much of Resinator is responsible for parsing/processing RC files and how much is responsible for piecing that information together to generate the RES files?

To add even more clarification, this means there is some theoretical "simpler interface" to resinator other than RC. Maybe this interface already exists in the form of some sort of AST within resinator already, or maybe this is a pipe dream that doesn't exist because RC is already a "simple enough" interface? These are questions I'm hoping you can answer Squeek.

P.S. I just thought of another important advantage to this. This theoretical simpler interface wouldn't have any dependence on the Clang preprocessor which prevents us from becoming more dependent on Clang when Zig's goal is to make this an optional dependency.

Copy link
Member

@andrewrk andrewrk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work. Thanks for taking the time to grok Compilation.zig and fully integrate this into the frontend of the compiler, including with error message reporting and parallelism. Love it!

One follow-up change that would be interesting to explore would be using Aro for the preprocessor rather than clang.

@andrewrk andrewrk merged commit 3fc7413 into ziglang:master Sep 22, 2023
@squeek502
Copy link
Collaborator Author

Thanks! Will definitely have a follow-up soon--that reportRetryableWin32ResourceError TODO was a complete oversight from me, that wasn't meant to make the final PR.

One follow-up change that would be interesting to explore would be using Aro for the preprocessor rather than clang.

Shouldn't be too hard to swap between them, since the preprocessing is a very distinct step and resinator basically just expects a blob of text from the preprocessor. Some of the rc.exe-preprocessor-like behavior might need special support in aro, though.

I've also considered writing a custom preprocessor (by forking aro, probably): squeek502/resinator#5 since in theory an rc.exe preprocessor only needs to support a subset of the full preprocessor features, and for full compatibility the preprocessor would need to support UTF-16 encoded files which I'm guessing aro would not be interested in having upstream.


@marler8997 here's a very rough estimate of the size of the different parts if that's helpful:

  • Lexing and parsing (source -> AST): ~5000 SLoC
  • The AST definitions: ~1000 SLoC
  • The compiler (AST -> .res): ~4000 SLoC

Again, though, dropping the lexing/parsing part would not be compatible with #9564

I think it would also be possible to implement roughly what you want as userland code that you call in build.zig to generate a .rc file and pass that to addWin32ResourceFile (or that same code could be put into std.Build if it's useful enough).

@marler8997
Copy link
Contributor

marler8997 commented Sep 22, 2023

My main point is that I think depending on a C preprocessor and the esoteric RC language just to add resources to our windows executables seems like a "local maximum".

I think it would be better for Zig to have native support for resource configuration without a dependence on these old clunky technologies. Adding a new frontend that runs before the RC frontend doesn't remove these dependencies, rather, the pipeline I'm suggesting would look more like this:

RC Parser > ZigResourceConfig > RES File
    ^
Optional (could be third party package, note this also requires windres also be a third party package)

I expect "ZigResourceConfig" could just be an internal data structure within std.Build that's created from calling various functions. We have other options such as using ZON to serialize/deserialize the configuration if that's beneficial. This being said, if you think depending on a C preprocessor and the RC language is not an issue (not as old/clunky as I'm suggesting) then my point is moot.

@squeek502
Copy link
Collaborator Author

My position is that the clunky RC language is necessary for use cases that I think Zig cares about (compiling existing .rc files, people that know how to write RC files not needing to learn something new), and that Zig making its own better "compiles to .res" language/build system would not be able to enable the same use cases. It would be nicer to use for sure, but I think the potential benefit is small enough that it's not worth the effort.

As a thought experiment, how would your same argument apply to C files? Is translate-c a similar local maximum?

@marler8997
Copy link
Contributor

marler8997 commented Sep 22, 2023

My position is that the clunky RC language is necessary for use cases that I think Zig cares about (compiling existing .rc files, people that know how to write RC files not needing to learn something new), and that Zig making its own better "compiles to .res" language/build system would not be able to enable the same use cases.

Completely agree

It would be nicer to use for sure, but I think the potential benefit is small enough that it's not worth the effort.

I'm actually less concerned about how easy it is to use and more concerned with the dependency on the C preprocessor. For example, one way to implement this idea is to make the "ZigResourceConfig" interface the RC language but without the C preprocessor. Instead of C preprocessor macros, format a string in your build.zig file. Instead of shared header files, use build options to pass names to your program. I'm not saying this is what we should or shouldn't do (not familiar enough with RC syntax) but since your RC code was only 5000 lines, it doesn't seem totally unreasonable. But before this I would first want to explore a "higher maximum" which would be a syntax that's more familiar to Zig developers and checked by the Zig compiler.

As a thought experiment, how would your same argument apply to C files? Is translate-c a similar local maximum?

The C language is the local maximum in this case :) Ziglang is the higher plateau in which we strive for. That being said, I believe the same idea about making the RC frontend an optional package have also been considered for general C interoperability. I can imagine one day Zig making translate-c and compiling C an optional dependency that's not included out-of-the box. Note that this is all predicated on it being very easy to add these dependencies. A couple lines in a build.zig.zon file for example.

@squeek502
Copy link
Collaborator Author

more concerned with the dependency on the C preprocessor.

resinator will be able to use aro, so unless I'm mistaken, resinator doesn't add an extra dependency on a C preprocessor as Zig already intends to depend on a C preprocessor. In this vein, Andrew added this checkbox to #16270:

make resinator use Aro for preprocessing rather than relying on clang

Basically, I think I'm mostly going to take a "we'll cross that bridge when we come to it" stance on this for now. If there ends up being a need for a preprocessor-less resource compiler, then something can be figured out.

@marler8997
Copy link
Contributor

In any case thanks so much for doing this @squeek502! Every part of what you've done here is valuable, I'm just wondering if we should add an additional piece to this puzzle and get your thoughts/guidance on it since you've become very familiar with this topic now.

squeek502 added a commit to squeek502/zig that referenced this pull request Sep 22, 2023
Follow up to ziglang#17069.

This TODO being left in was a complete oversight.

Before, any 'retryable' error would hit:

error: thread 2920 panic: access of union field 'success' while field 'failure_retryable' is active

Now, it will be reported/handled properly:

C:\Users\Ryan\Programming\Zig\zig\test\standalone\windows_resources\res\zig.rc:1:1: error: FileNotFound
andrewrk pushed a commit that referenced this pull request Sep 23, 2023
Follow up to #17069.

This TODO being left in was a complete oversight.

Before, any 'retryable' error would hit:

error: thread 2920 panic: access of union field 'success' while field 'failure_retryable' is active

Now, it will be reported/handled properly:

C:\Users\Ryan\Programming\Zig\zig\test\standalone\windows_resources\res\zig.rc:1:1: error: FileNotFound
squeek502 added a commit to squeek502/zig that referenced this pull request Oct 5, 2023
andrewrk pushed a commit that referenced this pull request Oct 12, 2023
Uses resinator under-the-hood (see #17069)

Closes #9564
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.

Add support for compiling .rc files into Windows .res files
4 participants