Skip to content

gnullvm: link libunwind statically by default - #159782

Closed
mati865 wants to merge 4 commits into
rust-lang:mainfrom
mati865:gnullvm-static-libunwind
Closed

gnullvm: link libunwind statically by default#159782
mati865 wants to merge 4 commits into
rust-lang:mainfrom
mati865:gnullvm-static-libunwind

Conversation

@mati865

@mati865 mati865 commented Jul 23, 2026

Copy link
Copy Markdown
Member

View all comments

Previously shared library was used meaning that programs and libraries couldn't be loaded if libunwind.dll was missing from the PATH. Using Wine (on Linux) because it better shows the problem (and is more convenient):

❯ cargo new hello &> /dev/null

❯ cargo rustc --target x86_64-pc-windows-gnullvm &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe
...
Import {
  Name: libunwind.dll
  ImportLookupTableRVA: 0x3D308
  ImportAddressTableRVA: 0x3D678
  Symbol: _GCC_specific_handler (0)
  Symbol: _Unwind_DeleteException (0)
  Symbol: _Unwind_GetDataRelBase (0)
  Symbol: _Unwind_GetIPInfo (0)
  Symbol: _Unwind_GetLanguageSpecificData (0)
  Symbol: _Unwind_GetRegionStart (0)
  Symbol: _Unwind_GetTextRelBase (0)
  Symbol: _Unwind_RaiseException (0)
  Symbol: _Unwind_Resume (0)
  Symbol: _Unwind_SetGR (0)
  Symbol: _Unwind_SetIP (0)
}
...

Optionally libunwind could be linked statically via +crt-static:

❯ cargo rustc --target x86_64-pc-windows-gnullvm -- -C target-feature=+crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind

This PR turns that the other way, libunwind will be now linked statically by default and could be linked dynamically with -crt-static:

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind

❯ cargo rustc --target x86_64-pc-windows-gnullvm -q -- -C target-feature=-crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
  Name: libunwind.dll

This is how I intended it to work previously, but couldn't manage to get it working 🤷🏻
Related PRs: #121794 #122003

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 23, 2026
@mati865

mati865 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-x86_64-llvm-mingw

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 23, 2026
gnullvm: link libunwind statically by default


try-job: dist-x86_64-llvm-mingw
@rust-bors

rust-bors Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

💔 Test for be73c40 failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@mati865

mati865 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-x86_64-llvm-mingw

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Jul 23, 2026
gnullvm: link libunwind statically by default


try-job: dist-x86_64-llvm-mingw
@rust-bors

rust-bors Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

💔 Test for e559b52 failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@mati865

mati865 commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

This is how I intended it to work previously, but couldn't manage to get it working 🤷🏻

So, that must be why...

ld.lld: error: undefined symbol: _Unwind_Resume
#159782 (comment)

@rustbot rustbot added the T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) label Aug 3, 2026
@mati865

mati865 commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-x86_64-llvm-mingw,dist-i686-llvm-mingw

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 3, 2026
gnullvm: link libunwind statically by default


try-job: dist-x86_64-llvm-mingw
try-job: dist-i686-llvm-mingw
@rust-bors

rust-bors Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

💔 Test for ae7481e failed: CI. Failed job:

@mati865

mati865 commented Aug 3, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-*-llvm-mingw

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 3, 2026
gnullvm: link libunwind statically by default


try-job: dist-*-llvm-mingw
@rust-log-analyzer

This comment has been minimized.

@rust-bors

rust-bors Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

💔 Test for 9539b53 failed: CI. Failed jobs:

@mati865
mati865 force-pushed the gnullvm-static-libunwind branch from 7cdc05a to 2f44eaf Compare August 5, 2026 11:28
@mati865

mati865 commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

@bors try jobs=dist-*-llvm-mingw

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Aug 5, 2026
gnullvm: link libunwind statically by default


try-job: dist-*-llvm-mingw
@rust-bors

rust-bors Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

☀️ Try build successful (CI)
Build commit: cf04f4c (cf04f4cb78db05a8f7f4ef0a5c2dc58b8eabbad8)
Base parent: 1b29cfd (1b29cfdbee8ee37333f4b24afb936350eb57e705)

@mati865 mati865 closed this Aug 6, 2026
@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 6, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Sep 8, 2026
…r=petrochenkov

windows-gnullvm: always link libunwind statically

Previously shared library was used by default, meaning that programs and libraries couldn't be loaded if `libunwind.dll` was missing from the PATH. Using Wine (on Linux) because it better shows the problem (and is more convenient):
```
❯ cargo new hello &> /dev/null

❯ cargo rustc --target x86_64-pc-windows-gnullvm &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe
...
Import {
  Name: libunwind.dll
  ImportLookupTableRVA: 0x3D308
  ImportAddressTableRVA: 0x3D678
  Symbol: _GCC_specific_handler (0)
  Symbol: _Unwind_DeleteException (0)
  Symbol: _Unwind_GetDataRelBase (0)
  Symbol: _Unwind_GetIPInfo (0)
  Symbol: _Unwind_GetLanguageSpecificData (0)
  Symbol: _Unwind_GetRegionStart (0)
  Symbol: _Unwind_GetTextRelBase (0)
  Symbol: _Unwind_RaiseException (0)
  Symbol: _Unwind_Resume (0)
  Symbol: _Unwind_SetGR (0)
  Symbol: _Unwind_SetIP (0)
}
...
```
Optionally libunwind could be linked statically via `+crt-static`:
```
❯ cargo rustc --target x86_64-pc-windows-gnullvm -- -C target-feature=+crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind
```

After a discussion of approach in rust-lang#159782 with @bjorn3 (thanks BTW!), I changed the proposed approach to always link static libunwind.

I don't have a good solution for rust-lang#121794 that will resurface. I guess the user has three options:
- symlink `libunwind.dll.a` as `libunwind.a`
- add `--unwindlib=none -lunwind` to the linker args
- create linker wrapper
- use self-contained mode which is likely is undesirable

I think the ease of use (not having to deal with additional DLL dependency) outweights the benefit of working with incomplete C toolchain.

The size bloat is also not a problem, sizes (in bytes) of the binary for the literal hello world project:
- debug build:
  - shared libunwind 4194816
  - static libunwind 4323328
- release build:
  - shared libunwind 382464
  - static libunwind 423424

Debug diff +125.5 KiB, release diff: +40 KiB.
Size of `libunwind.dll` that has to be provided when linking shared libunwind: 204288 bytes (199.5 KiB).
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Sep 8, 2026
…r=petrochenkov

windows-gnullvm: always link libunwind statically

Previously shared library was used by default, meaning that programs and libraries couldn't be loaded if `libunwind.dll` was missing from the PATH. Using Wine (on Linux) because it better shows the problem (and is more convenient):
```
❯ cargo new hello &> /dev/null

❯ cargo rustc --target x86_64-pc-windows-gnullvm &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe
...
Import {
  Name: libunwind.dll
  ImportLookupTableRVA: 0x3D308
  ImportAddressTableRVA: 0x3D678
  Symbol: _GCC_specific_handler (0)
  Symbol: _Unwind_DeleteException (0)
  Symbol: _Unwind_GetDataRelBase (0)
  Symbol: _Unwind_GetIPInfo (0)
  Symbol: _Unwind_GetLanguageSpecificData (0)
  Symbol: _Unwind_GetRegionStart (0)
  Symbol: _Unwind_GetTextRelBase (0)
  Symbol: _Unwind_RaiseException (0)
  Symbol: _Unwind_Resume (0)
  Symbol: _Unwind_SetGR (0)
  Symbol: _Unwind_SetIP (0)
}
...
```
Optionally libunwind could be linked statically via `+crt-static`:
```
❯ cargo rustc --target x86_64-pc-windows-gnullvm -- -C target-feature=+crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind
```

After a discussion of approach in rust-lang#159782 with @bjorn3 (thanks BTW!), I changed the proposed approach to always link static libunwind.

I don't have a good solution for rust-lang#121794 that will resurface. I guess the user has three options:
- symlink `libunwind.dll.a` as `libunwind.a`
- add `--unwindlib=none -lunwind` to the linker args
- create linker wrapper
- use self-contained mode which is likely is undesirable

I think the ease of use (not having to deal with additional DLL dependency) outweights the benefit of working with incomplete C toolchain.

The size bloat is also not a problem, sizes (in bytes) of the binary for the literal hello world project:
- debug build:
  - shared libunwind 4194816
  - static libunwind 4323328
- release build:
  - shared libunwind 382464
  - static libunwind 423424

Debug diff +125.5 KiB, release diff: +40 KiB.
Size of `libunwind.dll` that has to be provided when linking shared libunwind: 204288 bytes (199.5 KiB).
rust-bors Bot pushed a commit that referenced this pull request Sep 8, 2026
Rollup merge of #160712 - mati865:gnullvm-static-libunwind, r=petrochenkov

windows-gnullvm: always link libunwind statically

Previously shared library was used by default, meaning that programs and libraries couldn't be loaded if `libunwind.dll` was missing from the PATH. Using Wine (on Linux) because it better shows the problem (and is more convenient):
```
❯ cargo new hello &> /dev/null

❯ cargo rustc --target x86_64-pc-windows-gnullvm &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
0024:err:module:import_dll Library libunwind.dll (which is needed by L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe") not found
0024:err:module:loader_init Importing dlls for L"Z:\\tmp\\hello\\target\\x86_64-pc-windows-gnullvm\\debug\\hello.exe" failed, status c0000135

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe
...
Import {
  Name: libunwind.dll
  ImportLookupTableRVA: 0x3D308
  ImportAddressTableRVA: 0x3D678
  Symbol: _GCC_specific_handler (0)
  Symbol: _Unwind_DeleteException (0)
  Symbol: _Unwind_GetDataRelBase (0)
  Symbol: _Unwind_GetIPInfo (0)
  Symbol: _Unwind_GetLanguageSpecificData (0)
  Symbol: _Unwind_GetRegionStart (0)
  Symbol: _Unwind_GetTextRelBase (0)
  Symbol: _Unwind_RaiseException (0)
  Symbol: _Unwind_Resume (0)
  Symbol: _Unwind_SetGR (0)
  Symbol: _Unwind_SetIP (0)
}
...
```
Optionally libunwind could be linked statically via `+crt-static`:
```
❯ cargo rustc --target x86_64-pc-windows-gnullvm -- -C target-feature=+crt-static &> /dev/null

❯ wine target/x86_64-pc-windows-gnullvm/debug/hello.exe
Hello, world!

❯ llvm-readobj --coff-imports target/x86_64-pc-windows-gnullvm/debug/hello.exe | rg 'libunwind.dll' || echo "doesn't depend on shared libunwind"
doesn't depend on shared libunwind
```

After a discussion of approach in #159782 with @bjorn3 (thanks BTW!), I changed the proposed approach to always link static libunwind.

I don't have a good solution for #121794 that will resurface. I guess the user has three options:
- symlink `libunwind.dll.a` as `libunwind.a`
- add `--unwindlib=none -lunwind` to the linker args
- create linker wrapper
- use self-contained mode which is likely is undesirable

I think the ease of use (not having to deal with additional DLL dependency) outweights the benefit of working with incomplete C toolchain.

The size bloat is also not a problem, sizes (in bytes) of the binary for the literal hello world project:
- debug build:
  - shared libunwind 4194816
  - static libunwind 4323328
- release build:
  - shared libunwind 382464
  - static libunwind 423424

Debug diff +125.5 KiB, release diff: +40 KiB.
Size of `libunwind.dll` that has to be provided when linking shared libunwind: 204288 bytes (199.5 KiB).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

T-bootstrap Relevant to the bootstrap subteam: Rust's build system (x.py and src/bootstrap) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants