Skip to content

i686-pc-windows-gnu target fails to link with Homebrew MinGW i686 SJLJ runtime #158933

Closed

Description

@gsurrel

Disclamer: I encountered a problem when cross-compiling from macOS to Windows 32 bits. I was guided by ChatGPT to fix the issue, and when asked where and how to report the bug, it suggested the official Rust project bug-tracker. I do not have the knowledge to perform the same toolchain investigation of this problem, so feel free to close this report if not applicable.

Summary

The Rust i686-pc-windows-gnu target cannot be linked using the Homebrew mingw-w64 i686 toolchain because Rust's prebuilt standard library references the DW2 unwinder symbol _Unwind_Resume, while the provided MinGW i686 runtime only exports the SJLJ unwinder symbols (__Unwind_SjLj_*).

This results in a linker failure for any normal Rust program using std.

Environment

  • Host:
    • macOS Apple Silicon (aarch64-apple-darwin)
  • Rust:
    • cargo 1.94.0 (85eff7c80 2026-01-15)
    • stable toolchain
    • target: i686-pc-windows-gnu
  • GCC:
    • Homebrew mingw-w64
    • GCC 16.1.0
  • Rust target installed:
    rustup target add i686-pc-windows-gnu
    

Reproduction

Create a new project:

cargo new helloworld
cd helloworld
cargo build --target i686-pc-windows-gnu --release

The build fails during linking with:

undefined reference to `_Unwind_Resume'

Linker configuration

Cargo config:

[target.i686-pc-windows-gnu]
linker = "i686-w64-mingw32-gcc"

Relevant diagnostics

The MinGW compiler:

$ i686-w64-mingw32-gcc -v

gcc version 16.1.0 (GCC)
Target: i686-w64-mingw32

The runtime library does not provide _Unwind_Resume:

$ nm libgcc_eh.a | grep _Unwind_Resume

(no output)

The i686 libgcc_s.a provides SJLJ unwinding only:

__Unwind_SjLj_Register
__Unwind_SjLj_Unregister
__Unwind_SjLj_Resume
__Unwind_SjLj_RaiseException
__Unwind_SjLj_ForcedUnwind

However, Rust's shipped i686-pc-windows-gnu standard library contains references to:

_Unwind_Resume

and Cargo attempts to link:

-lgcc_eh

which cannot satisfy those symbols.

Expected behavior

The Rust i686-pc-windows-gnu target should either:

  1. Document the required MinGW exception model/runtime compatibility, or
  2. Provide a target toolchain configuration that works with currently available MinGW i686 distributions, or
  3. Detect and provide a clearer error message when the MinGW runtime exception model is incompatible.

Additional context

The same GCC installation's x86_64 runtime does provide:

_Unwind_Resume
_Unwind_Resume_or_Rethrow

The issue appears specific to the i686 MinGW runtime using SJLJ exceptions.

This prevents building ordinary Rust std applications for i686-pc-windows-gnu with this toolchain.

Question

Is i686-pc-windows-gnu expected to support only DW2 MinGW runtimes? If so, could this requirement be documented more prominently?

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 7, 2026
  2. gsurrel commented on Jul 7, 2026

    @gsurrel
    Author
  3. deleted a comment from on Jul 8, 2026
  4. workingjubilee commented on Jul 8, 2026

    @workingjubilee
    Member

    My condolences, we docked the target from tier 1 maintenance to tier 2 for reasons that are indeed shaped like "we do not actually have a clear answer to questions like this one".

    It's not clear that fixing this is correct. Is this the only unwinding runtime code that is distributed for this target? It seems unlikely, given I've been told other people cross-build to windows-gnu from things like Linux, but maybe it was only x86_64-pc-windows-gnu?

  5. workingjubilee commented on Jul 8, 2026

    @workingjubilee
    Member

    You see, what's perplexing to me is that the only SJLJ exceptions targets our library is aware of is, indeed, an Apple target:

    /// 32-bit ARM Darwin platforms uses SjLj exceptions.
    ///
    /// The exception is watchOS armv7k (specifically that subarchitecture), which
    /// instead uses DWARF Call Frame Information (CFI) unwinding.
    ///
    /// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.4/clang/lib/Driver/ToolChains/Darwin.cpp#L3107-L3119>
    pub const USING_SJLJ_EXCEPTIONS: bool =
    cfg!(all(target_vendor = "apple", not(target_os = "watchos"), target_arch = "arm"));

    Are you sure the libgcc.a in question is the right one?

  6. workingjubilee commented on Jul 8, 2026

    @workingjubilee
    Member

    Hmm, we're apparently compatible specifically with the toolchain produced by things like the MSYS2 PKGBUILD:

    build() {
      mkdir -p "${srcdir}"/build-${MSYSTEM} && cd "${srcdir}"/build-${MSYSTEM}
    
      declare -a _extra_config
      if check_option "debug" "n"; then
        _extra_config+=("--disable-libstdcxx-debug")
      else
        _extra_config+=("--enable-libstdcxx-debug")
      fi
    
      if [[ "${CARCH}" == "i686" ]]; then
        _extra_config+=(
          "--disable-sjlj-exceptions"
          "--with-dwarf2"
        )
        LDFLAGS+=" -Wl,--large-address-aware"
        local _arch=pentium4
      else
        #_extra_config+=("--enable-plugin")
        local _arch=nocona
      fi
  7. added
    O-windows-gnuToolchain: GNU, Operating system: Windows
    O-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)
    on Jul 8, 2026
  8. gsurrel commented on Jul 8, 2026

    @gsurrel
    Author

    Yes. I checked the libraries that i686-w64-mingw32-gcc itself resolves.

    $ i686-w64-mingw32-gcc -print-file-name=libgcc_s.a
    /opt/homebrew/Cellar/mingw-w64/14.0.0_1/toolchain-i686/lib/gcc/i686-w64-mingw32/16.1.0/../../../../i686-w64-mingw32/lib/../lib/libgcc_s.a

    This archive exports only the SJLJ unwinder:

    $ nm $(i686-w64-mingw32-gcc -print-file-name=libgcc_s.a) | grep SjLj
    00000000 T __Unwind_SjLj_Unregister
    00000000 I __imp___Unwind_SjLj_Unregister
    00000000 T __Unwind_SjLj_Resume_or_Rethrow
    00000000 I __imp___Unwind_SjLj_Resume_or_Rethrow
    00000000 T __Unwind_SjLj_Resume
    00000000 I __imp___Unwind_SjLj_Resume
    00000000 T __Unwind_SjLj_Register
    00000000 I __imp___Unwind_SjLj_Register
    00000000 T __Unwind_SjLj_RaiseException
    00000000 I __imp___Unwind_SjLj_RaiseException
    00000000 T __Unwind_SjLj_ForcedUnwind
    00000000 I __imp___Unwind_SjLj_ForcedUnwind

    Cargo invokes the linker with -lgcc_eh, so I also inspected the corresponding archive:

    $ nm $(i686-w64-mingw32-gcc -print-file-name=libgcc_eh.a) | grep _Unwind_Resume
    

    which produces no output.

    For information, it works well using x86_64-w64-mingw32-gcc. Maybe this is not really a Rust bug, but more of an incompatibility with the 32bits toolchain options shipped by Homebrew?

  9. mati865 commented on Jul 8, 2026

    @mati865
    Member

    32-bit GCC for Windows indeed can be built with SJLJ or Dwarf-2 exceptions. Rust only supports Dwarf-2 model, and has been doing so for like a decade.

  10. workingjubilee commented on Jul 8, 2026

    @workingjubilee
    Member

    Homebrew's provided tooling for a while was not capable of basic tasks like "not corrupting binaries built for the host platform", which prompted us to start shipping llvm-objcopy.

  11. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 8, 2026
  12. workingjubilee commented on Jul 8, 2026

    @workingjubilee
    Member

    I think this is just a platform support documentation issue.

  13. added 5 commits that reference this issue on Sep 8, 2026
    203cbe3
    416312b
    e4b0e9f
    1663ff8
    10d166a
  14. added a commit that references this issue on Sep 8, 2026
    1306f42
  15. added a commit that references this issue on Sep 14, 2026
    0726049
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-bugCategory: This is a bug.O-windows-gnuToolchain: GNU, Operating system: WindowsO-x86_32Target: x86 processors, 32 bit (like i686-*) (also known as IA-32, i386, i586, i686)T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions