rust-lang / rust-lang/rust

Linking native code with the crate-type "staticlib" causes link failures with internal Windows APIs on Windows

Open
#119,109 17 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C-discussion O-windows
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

Code
I tried this project:

Cargo.toml:

[package]
name = "example"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = [ "lib", "staticlib", "cdylib" ]

rust-toolchain.toml:

[toolchain]
# channel = "1.56.0" # Does work
# channel = "1.60.0" # Does work
# channel = "1.69.0" # Does work
# channel = "1.70.0" # Does not work
# channel = "1.74.1" # Does not work
channel = "stable" # Does not work
# channel = "beta" # Does not work
# channel = "nightly" # Does not work

src/lib.rs:

#[no_mangle]
pub extern "C" fn hello_world()
{
    println!("Hello World");
}

src/main.cpp:

#if USE_STATIC_API
#define EXAMPLE_API __cdecl
#else
#define EXAMPLE_API __declspec(dllimport) __cdecl
#endif

extern "C"
{
    void EXAMPLE_API hello_world();
}

int wmain()
{
    hello_world();
    return 0;
}

build.ps1:

cargo clean

cargo b --release
cl /nologo /utf-8 /EHsc /std:c++latest /Zc:preprocessor /permissive- /W4 /Zc:__cplusplus /MD /Fotarget\release\build\ /Fetarget\release\main_static.exe /DUSE_STATIC_API=1 .\src\main.cpp .\target\release\example.lib OneCore.lib
cl /nologo /utf-8 /EHsc /std:c++latest /Zc:preprocessor /permissive- /W4 /Zc:__cplusplus /MD /Fotarget\release\build\ /Fetarget\release\main_dynamic.exe .\src\main.cpp .\target\release\example.dll.lib

build.ps1 is not required, but it was helpful for testing and documents how I'm building the code.

I expected to see this happen:

A C++ application linking against example.lib links & runs successfully.

> .\build.ps1
   Compiling example v0.1.0 (C:\Users\bartw\source\rust\Testing)
    Finished release [optimized] target(s) in 0.31s
main.cpp # using staticlib, all fine
main.cpp # using cdylib, all fine
> .\target\release\main_static.exe
Hello World
Instead, this happened:

Linking errors to internal Windows APIs:

> .\build.ps1
     Removed 23 files, 22.3MiB total
   Compiling example v0.1.0 (C:\Users\bartw\source\rust\Testing)
    Finished release [optimized] target(s) in 0.35s
main.cpp # using staticlib, linker errors
example.lib(std-0953e6946d141dd5.std.1acf644841c643e8-cgu.0.rcgu.o) : error LNK2019: unresolved external symbol __imp_NtCreateFile referenced in function _ZN3std3sys7windows2fs20open_link_no_reparse17hca07eefe7f3c23d8E
example.lib(std-0953e6946d141dd5.std.1acf644841c643e8-cgu.0.rcgu.o) : error LNK2019: unresolved external symbol __imp_RtlNtStatusToDosError referenced in function _ZN3std3sys7windows2fs20open_link_no_reparse17hca07eefe7f3c23d8E
example.lib(std-0953e6946d141dd5.std.1acf644841c643e8-cgu.0.rcgu.o) : error LNK2019: unresolved external symbol __imp_NtReadFile referenced in function _ZN3std3sys7windows6handle6Handle16synchronous_read17h5729adfb8e80a411E
example.lib(std-0953e6946d141dd5.std.1acf644841c643e8-cgu.0.rcgu.o) : error LNK2019: unresolved external symbol __imp_NtWriteFile referenced in function _ZN3std3sys7windows6handle6Handle17synchronous_write17h87d0e51b32ace2e3E
target\release\main_static.exe : fatal error LNK1120: 4 unresolved externals
main.cpp # using cdylib, all fine
Version it worked on

It most recently worked on:

rustc 1.69.0 (84c898d65 2023-04-16)
binary: rustc
commit-hash: 84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc
commit-date: 2023-04-16
host: x86_64-pc-windows-msvc
release: 1.69.0
LLVM version: 15.0.7
Version with regression

First noticed with:

rustc 1.74.1 (a28077b28 2023-12-04)
binary: rustc
commit-hash: a28077b28a02b92985b3a3faecf92813155f1ea1
commit-date: 2023-12-04
host: x86_64-pc-windows-msvc
release: 1.74.1
LLVM version: 17.0.4

Lowest version tested which did not work:

rustc 1.70.0 (90c541806 2023-05-31)
binary: rustc
commit-hash: 90c541806f23a127002de5b4038be731ba1458ca
commit-date: 2023-05-31
host: x86_64-pc-windows-msvc
release: 1.70.0
LLVM version: 16.0.2

Versions not listed in the rust-toolchain.toml example above where not tested.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the regression using Cargo.toml, rust-toolchain.toml, src/lib.rs, src/main.cpp, and build.ps1, comparing Rust 1.69.0 with 1.70.0 or later. Trace the staticlib link path and its Windows API dependencies, then verify that the static C++ executable links and runs without unresolved symbols while the cdylib case remains working.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, powershell, rust
Domain
build-system, compilers, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.