https://github.com/dot-asm/min-crt-poc
Trimmed-down MinGW DLL entry point in Rust
https://github.com/dot-asm/min-crt-poc
Last synced: about 1 year ago
JSON representation
Trimmed-down MinGW DLL entry point in Rust
- Host: GitHub
- URL: https://github.com/dot-asm/min-crt-poc
- Owner: dot-asm
- Created: 2022-04-07T10:12:16.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2024-07-13T17:45:21.000Z (almost 2 years ago)
- Last Synced: 2025-01-30T20:17:02.339Z (over 1 year ago)
- Language: Rust
- Homepage:
- Size: 11.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
MinGW compilers come in multiple flavours, "mingw", "ucrt" and "clang"/"llvm". This asks for the question how many Rust targets there should be. While both MinGW GCC and LLVM toolchains use the same C run-times, they are utilizing different exception handling mechanisms. This makes it impossible to produce a "universal" non-MSVC Windows target that would work with both GCC and Clang. But what about "mingw" vs. "ucrt"? The suggested approach aims to facilitate run-time-neutral `-pc-windows-gnu` target. In more practical terms, after executing `rustup target add -pc-windows-gnu` users will be free to choose between msvcrt and ucrt by simply adjusting their `PATH` environment variable(\*\*).
The key component is [`dllmain.rs`](src/dllmain.rs), a trimmed-down MinGW CRT initialization module, that should allow linking `std-.dll` without reference to a specific run-time, legacy msvcrt.dll or Universal CRT.
While compiling with `-C prefer-dynamic` might not be that popular, the fact that the `std-.dll` can be linked without reference to a specific run-time strongly suggests that the static `libstd-.rlib` and Rust-generated code in general don't actually have the dependency either. Or rather it's not strong enough(\*) to prevent the choice of the run-time to be postponed till the application link time. This is the main proposition.
The rest of the crate is a test-bed PoC around the `dllmain.rs`. You're more than likely going to have to run `cargo run ...` twice to test. This is because application code gets linked before the library is available. If you know how to arrange the link invocations in specific order, do tell:-) Either way, once confirmed to execute, double-check that `poc.dll` doesn't have imports from your CRT. The test registers a pre-main subroutine, an equivalent to `__attribute__((constructor))` in C, spawns a [rayon](https://docs.rs/rayon/) thread and prints the value set by the "constructor."
Even though the primary target is MinGW, the dllmain.rs and PoC work even with MSVC.
(\*) Rust compiler depends on memcpy/move/set/cmp and strlen being externally available. These are interchangeable between all known run-times.
(\*\*) Caveat lector. By default Rust compiler drivers invokes `x86_64-w64-mingw32-gcc` to link the final binary. The catch is that some MinGW clang packages were spotted to provide `x86_64-w64-mingw32-gcc`, presumably to smooth the switch. Since it's the C compiler driver that is responsible for linking the exception handling library, it would be a problem if the exception flavours chosen by Rust and first-on-the-PATH C compiler mismatch. In the context one can make a case for a sanity check for a matching C compiler. Most notably MinGW GCC target driver could verify that the library search path in `x86_64-w64-mingw32-gcc -print-search-dirs` output has corresponding exception handling library, `libgcc_eh.a`.