An open API service indexing awesome lists of open source software.

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

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`.