{"id":17137152,"url":"https://github.com/squeek502/resinator","last_synced_at":"2025-04-06T10:11:11.023Z","repository":{"id":63507138,"uuid":"556435913","full_name":"squeek502/resinator","owner":"squeek502","description":"Cross-platform Windows resource-definition script (.rc) to resource file (.res) compiler","archived":false,"fork":false,"pushed_at":"2025-03-19T23:54:24.000Z","size":1561,"stargazers_count":116,"open_issues_count":13,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T08:12:11.325Z","etag":null,"topics":["rc","win32","windows-resource-file","zig"],"latest_commit_sha":null,"homepage":"","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"0bsd","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/squeek502.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["squeek502"]}},"created_at":"2022-10-23T21:00:47.000Z","updated_at":"2025-03-19T23:54:27.000Z","dependencies_parsed_at":"2023-10-19T02:45:12.133Z","dependency_job_id":"191ac92b-d039-4d53-8450-38102e58912c","html_url":"https://github.com/squeek502/resinator","commit_stats":{"total_commits":645,"total_committers":1,"mean_commits":645.0,"dds":0.0,"last_synced_commit":"aa04415451b500ffe4b3d10e74aef9b18fda6c3e"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squeek502%2Fresinator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squeek502%2Fresinator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squeek502%2Fresinator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/squeek502%2Fresinator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/squeek502","download_url":"https://codeload.github.com/squeek502/resinator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247464220,"owners_count":20942970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["rc","win32","windows-resource-file","zig"],"created_at":"2024-10-14T20:06:22.465Z","updated_at":"2025-04-06T10:11:11.003Z","avatar_url":"https://github.com/squeek502.png","language":"Zig","funding_links":["https://github.com/sponsors/squeek502"],"categories":[],"sub_categories":[],"readme":"![](https://www.ryanliptak.com/images/resinator-dynamic-32.svg) resinator\n=========\n\nA cross-platform Windows resource-definition script (.rc) to resource file (.res) compiler. It has been merged into the Zig compiler ([#17069](https://github.com/ziglang/zig/pull/17069), [#17412](https://github.com/ziglang/zig/pull/17412)), but it is also maintained as a separate standalone tool.\n\n- This is a fully from-scratch and [clean-room](https://en.wikipedia.org/wiki/Clean_room_design) implementation, using [fuzz testing](#testing-resinator) as the primary method of determining how `rc.exe` works and how compatible `resinator` is with its implementation.\n  + See [this talk](https://www.youtube.com/watch?v=RZczLb_uI9E) for a deeper dive into this\n- `resinator` can successfully compile every `.rc` file in the [Windows-classic-samples repo](https://github.com/microsoft/Windows-classic-samples) byte-for-byte identically to the Windows RC compiler when using the includes from MSVC/the Windows SDK. This is tested via [win32-samples-rc-tests](https://github.com/squeek502/win32-samples-rc-tests).\n- `resinator` has zero external dependencies at runtime (it embeds [Aro](https://github.com/Vexu/arocc) for preprocessing) and can be used to cross-compile from any system out-of-the-box (if Windows system include paths are not found, a complete set of [MinGW](https://www.mingw-w64.org/) include files are extracted on-demand).\n- [Documentation](https://squeek502.github.io/resinator/) (really just a dumping ground for documentation-adjacent stuff; to-be-improved-upon)\n\n## Overview\n\nA Windows resource-definition file (`.rc`) is made up of both C/C++ preprocessor commands and resource definitions.\n\n- The preprocessor commands are evaluated first via [Aro](https://github.com/Vexu/arocc)\n- The preprocessed `.rc` file is then compiled into a `.res` file\n- The `.res` file can then be linked into an executable by a linker\n\n`resinator` is similar to `llvm-rc` and GNU's `windres`, in that it aims to be a cross-platform alternative to [the Windows `rc.exe` tool](https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-).\n\nHowever, unlike `llvm-rc` and `windres` (see [this section](#an-example-of-the-differences-between-the-implementations)), `resinator` aims to get as close to 1:1 compatibility with the Windows `rc.exe` implementation as possible. That is, the ideal would be:\n\n- The `.res` output of `resinator` should match the `.res` output of the Windows `rc.exe` in as many cases as possible (if not exactly, then functionally). However, `resinator` will not support all valid `.rc` files (i.e. `#pragma code_page` support will be limited to particular code pages).\n- `resinator` should fail to compile `.rc` files that the Windows `rc.exe` tool fails to compile.\n\nIn practice, though, 1:1 compatibility is not actually desirable, as there are quirks/bugs in the `rc.exe` implementation that `resinator` attempts to handle better.\n\n## Comparison to `rc.exe` (the Win32 RC compiler)\n\n`resinator` is a drop-in replacement for `rc.exe` with some improvements, some known exceptions, and some caveats.\n\n#### `resinator` has better error messages\n\n![](https://github.com/squeek502/resinator/assets/2389051/1d2a6dd1-dbcb-4df8-88b1-ab1b84ea36eb)\n\n#### `resinator` handles edge cases better and avoids miscompilations\n\n`resinator` avoids some miscompilations of the Win32 RC compiler and generally handles edge cases better (e.g. resource data size overflow). See [this exhaustive list of intentional differences between `resinator` and `rc.exe`](https://squeek502.github.io/resinator/divergences.html).\n\nAlso, `resinator` will emit helpful warnings/errors for many of these differences:\n\n![](https://github.com/squeek502/resinator/assets/2389051/85150176-a06f-47a4-9e80-ed15961a1d72)\n\n#### `resinator` does not support UTF-16 encoded scripts\n\nThis is a limitation of the preprocessor that is used by `resinator` (see [this issue](https://github.com/squeek502/resinator/issues/5)).\n\n#### `resinator` will auto-detect system include paths by default\n\n`.rc` files can `#include` files from MSVC/Windows SDKs (most commonly, `windows.h`). The paths for these files are typically provided via the `INCLUDE` environment variable or the `/i` command line option. `resinator` supports the same options, but it will also try to auto-detect system include paths on Windows, or extract a full set of MinGW includes on-demand (meaning `#include \"windows.h\"` in a `.rc` file will work out-of-the-box on Linux/MacOS/etc).\n\nThis behavior can be controlled with the `/:auto-includes` CLI option.\n\n## Comparison to `windres` and `llvm-rc`\n\n| Feature | `resinator` | `windres` | `llvm-rc` | `rc.exe` |\n| --- | --- | --- | --- | --- |\n| Cross-platform | ✅ | ✅ | ✅ | ❌ |\n| Identical [`win32-samples-rc-tests`](https://github.com/squeek502/win32-samples-rc-tests) outputs as `rc.exe` | ✅ | ❌ | ❌ | ✅ |\n| Support for UTF-16 encoded `.rc` files | ❌ \u003csup\u003e[(TODO)](https://github.com/squeek502/resinator/issues/5)\u003c/sup\u003e | ❌ | ❌ | ✅ |\n| CLI compatibility with `rc.exe` | ✅ | ❌ | ✅ | ✅ |\n| Includes preprocessor | ✅ | ❌ | ❌ | ✅ |\n| Support for outputting `.rc` files | ❌ | ✅ | ❌ | ❌ |\n| Support for outputting COFF object files | ❌ \u003csup\u003e[(TODO)](https://github.com/squeek502/resinator/issues/7)\u003c/sup\u003e | ✅ | ❌ | ❌ |\n\n#### An example of the differences between the implementations\n\nHere is an example `.rc` script that is handled differently by each of `windres`, `llvm-rc`, and the canonical Windows `rc.exe` implementation:\n\n```c\n// \u003cid\u003e \u003cresource type\u003e { \u003cdata\u003e }\n1 \"FOO\" { \"bar\" }\n```\n\n- `rc.exe` compiles this to a `.res` file with a resource of ID `1` that has the type `\"FOO\"` (the quotes are part of the user-defined resource type name)\n- `windres` compiles this to a `.res` file with a resource of ID `1` that has the type `FOO` (the `\"FOO\"` is parsed as a quoted string)\n- `llvm-rc` errors on this file with: `Error: expected int or identifier, got \"FOO\"`\n- `resinator` matches the `rc.exe` behavior exactly in this case\n\nThis particular example is mostly inconsequential in terms of real-world `.rc` files, but it is indicative of how closely the different implementations conform with the `rc.exe` behavior. See [win32-samples-rc-tests](https://github.com/squeek502/win32-samples-rc-tests) for a more wide-ranging comparison on real-world `.rc` files.\n\n## Compiling `resinator`\n\nSee [the version of Zig used in CI](https://github.com/squeek502/resinator/blob/master/.github/workflows/ci.yml#L23) to determine which version of Zig should be used to build `resinator`.\n\n```\ngit clone https://github.com/squeek502/resinator\ncd resinator\nzig build\n```\n\n## Testing `resinator`\n\n```\nzig build test\n```\n\n### 'Fuzzy' tests\n\nThe 'fuzzy' tests are a collection of tests that may be similar to either fuzz testing or property testing. With default settings, the more fuzzing-like tests will run for 1000 iterations. These tests rely on `rc.exe` being available on `PATH` since each test uses `rc.exe` as an oracle to determine if `resinator` behavior is expected or not.\n\n```\nzig build test_fuzzy\n```\n\nwill run all of the 'fuzzy' tests.\n\nEach 'fuzzy' test can be run individually, too. For example, this will run the `fuzzy_numbers` test infinitely:\n\n```\nzig build test_fuzzy_numbers -Diterations=0\n```\n\n### Fuzz testing\n\n#### On Windows\n\n- Requires [winafl](https://github.com/googleprojectzero/winafl) to be installed/built.\n- Requires `rc.exe` to be available on the `PATH`\n\nTo build the fuzzer:\n\n```\nzig build fuzz_winafl\n```\n\nTo run the fuzzer, from within the `winafl/build64/bin` directory (replace `C:\\path\\to\\` with the actual path to the relevant directories):\n\n```\nset PATH_TO_INPUTS_DIR=C:\\path\\to\\resinator\\test\\inputs\nset PATH_TO_OUTPUTS_DIR=C:\\path\\to\\resinator\\test\\outputs\nset PATH_TO_DYNAMORIO_BIN=C:\\path\\to\\DynamoRIO-Windows\\bin64\nset PATH_TO_RESINATOR_FUZZER=C:\\path\\to\\resinator\\zig-out\\bin\\fuzz_winafl.exe\nafl-fuzz.exe -i \"%PATH_TO_INPUTS_DIR%\" -o \"%PATH_TO_OUTPUTS_DIR%\" -D \"%PATH_TO_DYNAMORIO_BIN%\" -t 20000 -- -coverage_module fuzz_winafl.exe -target_module fuzz_winafl.exe -target_method fuzzMain -fuzz_iterations 5000 -nargs 2 -- \"%PATH_TO_RESINATOR_FUZZER%\" @@\n```\n\n#### On Linux\n\nCurrently, Linux fuzz testing only tests the `resinator` implementation for crashes/bugs, and does not check for correctness against `rc.exe`.\n\n- Requires [afl++](https://github.com/AFLplusplus/AFLplusplus) with `afl-clang-lto` to be installed.\n\n```\nzig build fuzz_rc\n```\n\nTo run the fuzzer:\n```\nafl-fuzz -i test/inputs -o test/outputs -- ./zig-out/bin/fuzz_rc\n```\n\nIdeally, this fuzzer would compare the outputs against `rc.exe` but `wine` was not able to perfectly emulate `rc.exe` last I tried (need to investigate this more, I was using a rather old version of wine).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqueek502%2Fresinator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqueek502%2Fresinator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqueek502%2Fresinator/lists"}